Blame view

web/static/js/swapp.js 37.9 KB
438929a4   Goutte   Rewrite the orbit...
1
2
// Generated by LiveScript 1.5.0
(function(){
b60e7acd   Goutte   Rename "source" i...
3
  var GOLDEN_RATIO, Target, SpaceWeather, TimeSeries, Orbits, out$ = typeof exports != 'undefined' && exports || this;
438929a4   Goutte   Rewrite the orbit...
4
  GOLDEN_RATIO = 2 / (1 + Math.sqrt(5));
b60e7acd   Goutte   Rename "source" i...
5
6
7
8
9
10
11
  Target = (function(){
    Target.displayName = 'Target';
    var prototype = Target.prototype, constructor = Target;
    function Target(slug, name, config){
      this.slug = slug;
      this.name = name;
      this.config = config;
2c0e1515   Goutte   Refactor loading ...
12
      this.active = this.config.active;
b60e7acd   Goutte   Rename "source" i...
13
14
15
    }
    return Target;
  }());
ae0aa7d2   Goutte   Add an x axis lab...
16
  out$.SpaceWeather = SpaceWeather = (function(){
6bb225d6   Goutte   Link the time ser...
17
    "The main app, instanciated from an inline script.\nIt defaults to an interval starting a year ago, and ending in seven days.\n(both at midnight)";
ae0aa7d2   Goutte   Add an x axis lab...
18
    SpaceWeather.displayName = 'SpaceWeather';
243cd8a4   Goutte   Timestamp party c...
19
    var API_TIME_FORMAT, INPUT_TIME_FORMAT, prototype = SpaceWeather.prototype, constructor = SpaceWeather;
2c0e1515   Goutte   Refactor loading ...
20
    API_TIME_FORMAT = "YYYY-MM-DDTHH:mm:ss";
243cd8a4   Goutte   Timestamp party c...
21
    INPUT_TIME_FORMAT = "YYYY-MM-DD";
ae0aa7d2   Goutte   Add an x axis lab...
22
    function SpaceWeather(configuration){
fe3132dd   Goutte   Refactor even more.
23
      var configs, res$, k, this$ = this;
f75faf5f   Goutte   WIP
24
      this.configuration = configuration;
05e269d1   Goutte   Show an error mes...
25
      console.info("©2017\n  _   _      _ _       ____\n | | | | ___| (_) ___ |  _ \\ _ __ ___  _ __   __ _\n | |_| |/ _ \\ | |/ _ \\| |_) | '__/ _ \\| '_ \\ / _` |\n |  _  |  __/ | | (_) |  __/| | | (_) | |_) | (_| |\n |_| |_|\\___|_|_|\\___/|_|_  |_|_ \\___/| .__/ \\__,_|\n | |__  _   _   / ___|  _ \\|  _ \\|  _ \\_|\n | '_ \\| | | | | |   | | | | |_) | |_) |\n | |_) | |_| | | |___| |_| |  __/|  __/\n |_.__/ \\__, |  \\____|____/|_|   |_|\n        |___/\n\nThe full source of this website is available at :\nhttps://gitlab.irap.omp.eu/CDPP/SPACEWEATHERONLINE");
b60e7acd   Goutte   Rename "source" i...
26
      this.targets = {};
fe3132dd   Goutte   Refactor even more.
27
      res$ = [];
b60e7acd   Goutte   Rename "source" i...
28
29
      for (k in this.configuration.targets) {
        res$.push(this.configuration.targets[k]);
fe3132dd   Goutte   Refactor even more.
30
31
      }
      configs = res$;
b60e7acd   Goutte   Rename "source" i...
32
      configs.forEach(function(target_config){
cad44b6d   Goutte   Finish adding the...
33
        return this$.addTarget(new Target(target_config.slug, target_config.name, target_config));
fe3132dd   Goutte   Refactor even more.
34
      });
b7fe650c   Goutte   Misc bundle of ol...
35
36
37
38
      this.parameters = {};
      this.configuration['parameters'].forEach(function(p){
        return this$.parameters[p['id']] = p;
      });
7994cf1a   Goutte   Hunt bugs.
39
      this.orbiter = null;
80352490   Goutte   Multi model suppo...
40
      this.time_series = [];
ae0aa7d2   Goutte   Add an x axis lab...
41
    }
b60e7acd   Goutte   Rename "source" i...
42
43
    SpaceWeather.prototype.init = function(){
      "This is called by the inline bootstrap javascript code.\nThis ain't in the constructor because it might return a Promise later on.\n(for the loader, for example)";
2c0e1515   Goutte   Refactor loading ...
44
      var started_at, stopped_at, this$ = this;
cad44b6d   Goutte   Finish adding the...
45
      started_at = moment().subtract(1, 'year').hours(0).minutes(0).seconds(0);
1324cc91   Goutte   Make the footer i...
46
      stopped_at = moment().add(3, 'week').hours(0).minutes(0).seconds(0);
7994cf1a   Goutte   Hunt bugs.
47
      this.setStartAndStop(started_at, stopped_at);
2c0e1515   Goutte   Refactor loading ...
48
      this.loadAndCreatePlots(started_at, stopped_at);
b60e7acd   Goutte   Rename "source" i...
49
50
51
52
53
      return window.addEventListener('resize', function(){
        return this$.resize();
      });
    };
    SpaceWeather.prototype.buildDataUrlForTarget = function(target_slug, started_at, stopped_at){
f75faf5f   Goutte   WIP
54
55
      var url;
      url = this.configuration['api']['data_for_interval'];
b60e7acd   Goutte   Rename "source" i...
56
      url = url.replace('<target>', target_slug);
a4a9ef03   Goutte   Cache generated C...
57
58
      url = url.replace('<started_at>', started_at);
      url = url.replace('<stopped_at>', stopped_at);
f75faf5f   Goutte   WIP
59
60
      return url;
    };
6b149919   Goutte   Add a Download bu...
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
    SpaceWeather.prototype.buildDownloadUrl = function(){
      var ref$, started_at, stopped_at, targets, t, url;
      ref$ = this.getDomain(), started_at = ref$[0], stopped_at = ref$[1];
      targets = (function(){
        var results$ = [];
        for (t in this.targets) {
          if (this.targets[t].active) {
            results$.push(t);
          }
        }
        return results$;
      }.call(this)).sort().join('-');
      url = this.configuration['api']['download'];
      url = url.replace('<targets>', targets);
      url = url.replace('<started_at>', started_at.format(API_TIME_FORMAT));
      url = url.replace('<stopped_at>', stopped_at.format(API_TIME_FORMAT));
      return url;
    };
cad44b6d   Goutte   Finish adding the...
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
    SpaceWeather.prototype.buildSampUrl = function(){
      var ref$, started_at, stopped_at, targets, t, parameters, p, url;
      ref$ = this.getDomain(), started_at = ref$[0], stopped_at = ref$[1];
      targets = (function(){
        var results$ = [];
        for (t in this.targets) {
          if (this.targets[t].active) {
            results$.push(t);
          }
        }
        return results$;
      }.call(this)).sort().join('-');
      parameters = (function(){
        var results$ = [];
        for (p in this.parameters) {
          if (this.parameters[p].active) {
            results$.push(p);
          }
        }
        return results$;
      }.call(this)).sort().join('-');
      url = this.configuration['api']['samp'];
      url = url.replace('<targets>', targets);
      url = url.replace('<params>', parameters);
      url = url.replace('<started_at>', started_at.format(API_TIME_FORMAT));
      url = url.replace('<stopped_at>', stopped_at.format(API_TIME_FORMAT));
      return url;
    };
    SpaceWeather.prototype.buildSampName = function(){
      var ref$, started_at, stopped_at, targets, t;
      ref$ = this.getDomain(), started_at = ref$[0], stopped_at = ref$[1];
      targets = (function(){
        var i$, ref$, len$, results$ = [];
        for (i$ = 0, len$ = (ref$ = this.getEnabledTargets()).length; i$ < len$; ++i$) {
          t = ref$[i$];
          results$.push(t.name);
        }
        return results$;
      }.call(this)).sort().join(', ');
      return "Heliopropa for " + targets + " from " + started_at.format(API_TIME_FORMAT) + " to " + stopped_at.format(API_TIME_FORMAT) + ".";
    };
b60e7acd   Goutte   Rename "source" i...
120
121
    SpaceWeather.prototype.addTarget = function(target){
      this.targets[target.slug] = target;
f75faf5f   Goutte   WIP
122
123
      return this;
    };
cad44b6d   Goutte   Finish adding the...
124
125
126
127
128
129
130
131
132
133
    SpaceWeather.prototype.getEnabledTargets = function(){
      var slug, ref$, target, results$ = [];
      for (slug in ref$ = this.targets) {
        target = ref$[slug];
        if (target.active) {
          results$.push(target);
        }
      }
      return results$;
    };
6bb225d6   Goutte   Link the time ser...
134
    SpaceWeather.prototype.enableTarget = function(target_slug){
17c52617   Goutte   Make the orbits p...
135
      var ref$, this$ = this;
80352490   Goutte   Multi model suppo...
136
      this.time_series.forEach(function(ts){
b60e7acd   Goutte   Rename "source" i...
137
        if (ts.target.slug === target_slug && this$.parameters[ts.parameter].active) {
6bb225d6   Goutte   Link the time ser...
138
          return ts.show();
4cf497e0   Goutte   Make the targets ...
139
140
        }
      });
b60e7acd   Goutte   Rename "source" i...
141
      this.targets[target_slug].active = true;
17c52617   Goutte   Make the orbits p...
142
143
144
      if ((ref$ = this.orbits) != null) {
        ref$.showOrbiter(target_slug);
      }
f75faf5f   Goutte   WIP
145
146
      return this;
    };
6bb225d6   Goutte   Link the time ser...
147
    SpaceWeather.prototype.disableTarget = function(target_slug){
17c52617   Goutte   Make the orbits p...
148
      var ref$;
80352490   Goutte   Multi model suppo...
149
      this.time_series.forEach(function(ts){
b60e7acd   Goutte   Rename "source" i...
150
        if (ts.target.slug === target_slug) {
6bb225d6   Goutte   Link the time ser...
151
          return ts.hide();
4cf497e0   Goutte   Make the targets ...
152
153
        }
      });
b60e7acd   Goutte   Rename "source" i...
154
      this.targets[target_slug].active = false;
17c52617   Goutte   Make the orbits p...
155
156
157
      if ((ref$ = this.orbits) != null) {
        ref$.hideOrbiter(target_slug);
      }
f75faf5f   Goutte   WIP
158
159
      return this;
    };
fe3132dd   Goutte   Refactor even more.
160
    SpaceWeather.prototype.resize = function(){
a21f81d9   Goutte   Enable Venus and ...
161
      var ref$;
d49a163c   Goutte   Fix the resize an...
162
163
164
      if ((ref$ = this.orbits) != null) {
        ref$.resize();
      }
80352490   Goutte   Multi model suppo...
165
      return this.time_series.forEach(function(ts){
d49a163c   Goutte   Fix the resize an...
166
167
        return ts.resize();
      });
fe3132dd   Goutte   Refactor even more.
168
    };
2c0e1515   Goutte   Refactor loading ...
169
    SpaceWeather.prototype.showLoader = function(){
05e269d1   Goutte   Show an error mes...
170
      return $('#plots_loader').show();
2c0e1515   Goutte   Refactor loading ...
171
    };
9c0c4509   Goutte   Add a loader to t...
172
    SpaceWeather.prototype.hideLoader = function(){
05e269d1   Goutte   Show an error mes...
173
      return $('#plots_loader').hide();
9c0c4509   Goutte   Add a loader to t...
174
    };
b60e7acd   Goutte   Rename "source" i...
175
176
    SpaceWeather.prototype.loadData = function(target_slug, started_at, stopped_at){
      "Load the data as CSV for the specified target and interval,\nand return it in a Promise.";
2c0e1515   Goutte   Refactor loading ...
177
      var sw;
f75faf5f   Goutte   WIP
178
      sw = this;
2c0e1515   Goutte   Refactor loading ...
179
      return new Promise(function(resolve, reject){
f75faf5f   Goutte   WIP
180
        var url;
b60e7acd   Goutte   Rename "source" i...
181
        url = sw.buildDataUrlForTarget(target_slug, started_at, stopped_at);
a4a9ef03   Goutte   Cache generated C...
182
        return d3.csv(url, function(csv){
f75faf5f   Goutte   WIP
183
          var timeFormat, data;
9bfa6c42   Goutte   More bug hunting.
184
          console.debug("Requested CSV for " + target_slug + "...", csv);
f75faf5f   Goutte   WIP
185
186
          timeFormat = d3.timeParse('%Y-%m-%dT%H:%M:%S%Z');
          data = {
6491a1f1   Goutte   Fix up the bugs l...
187
            'hee': []
f75faf5f   Goutte   WIP
188
189
190
191
          };
          configuration['parameters'].forEach(function(parameter){
            return data[parameter['id']] = [];
          });
a245c676   Goutte   Commit generated ...
192
          if (!csv) {
80352490   Goutte   Multi model suppo...
193
            reject('invalid');
a245c676   Goutte   Commit generated ...
194
          }
9bfa6c42   Goutte   More bug hunting.
195
          if (!csv.length) {
80352490   Goutte   Multi model suppo...
196
            reject('empty');
9bfa6c42   Goutte   More bug hunting.
197
          }
f75faf5f   Goutte   WIP
198
199
200
201
202
203
204
205
206
207
208
          csv.forEach(function(d){
            var dtime;
            dtime = timeFormat(d['time']);
            configuration['parameters'].forEach(function(parameter){
              var id;
              id = parameter['id'];
              return data[id].push({
                x: dtime,
                y: parseFloat(d[id])
              });
            });
6491a1f1   Goutte   Fix up the bugs l...
209
210
            if (d['xhee'] && d['yhee']) {
              return data['hee'].push({
f75faf5f   Goutte   WIP
211
                t: dtime,
6491a1f1   Goutte   Fix up the bugs l...
212
213
                x: parseFloat(d['xhee']),
                y: parseFloat(d['yhee'])
f75faf5f   Goutte   WIP
214
215
216
217
218
219
              });
            }
          });
          return resolve(data);
        });
      });
2c0e1515   Goutte   Refactor loading ...
220
221
    };
    SpaceWeather.prototype.loadAndCreatePlots = function(started_at, stopped_at){
80352490   Goutte   Multi model suppo...
222
      "started_at: moment(.js) datetime object\nstopped_at: moment(.js) datetime object";
5e099488   Goutte   Fix that loading ...
223
      var k, this$ = this;
2c0e1515   Goutte   Refactor loading ...
224
      this.showLoader();
7994cf1a   Goutte   Hunt bugs.
225
226
227
      this.started_at = started_at;
      this.stopped_at = stopped_at;
      this.orbits = new Orbits(this.configuration.orbits_container, this.configuration);
243cd8a4   Goutte   Timestamp party c...
228
229
      started_at = started_at.format(API_TIME_FORMAT);
      stopped_at = stopped_at.format(API_TIME_FORMAT);
5e099488   Goutte   Fix that loading ...
230
231
232
233
      return (function(){
        var results$ = [];
        for (k in this.targets) {
          results$.push(this.targets[k]);
2c0e1515   Goutte   Refactor loading ...
234
        }
5e099488   Goutte   Fix that loading ...
235
236
        return results$;
      }.call(this)).forEach(function(target){
2c0e1515   Goutte   Refactor loading ...
237
238
        var targetButton;
        console.info("Loading CSV data of " + target.name + "…");
4900d232   Goutte   Add the time inte...
239
        targetButton = $(".targets-filters .target." + target.slug);
2c0e1515   Goutte   Refactor loading ...
240
        targetButton.addClass('loading');
6491a1f1   Goutte   Fix up the bugs l...
241
        targetButton.removeClass('failed empty');
2c0e1515   Goutte   Refactor loading ...
242
        return this$.loadData(target.slug, started_at, stopped_at).then(function(data){
9bfa6c42   Goutte   More bug hunting.
243
          console.info("Loaded CSV data of " + target.name + ".", data);
2c0e1515   Goutte   Refactor loading ...
244
          this$.createTimeSeries(target, data);
6491a1f1   Goutte   Fix up the bugs l...
245
          this$.orbits.initOrbiter(target.slug, target.config, data['hee']);
2c0e1515   Goutte   Refactor loading ...
246
          targetButton.removeClass('loading');
5e099488   Goutte   Fix that loading ...
247
248
249
250
251
          if (target.active) {
            return this$.hideLoader();
          } else {
            return this$.disableTarget(target.slug);
          }
2c0e1515   Goutte   Refactor loading ...
252
        }, function(error){
80352490   Goutte   Multi model suppo...
253
254
255
256
257
258
259
260
261
262
263
264
265
          var msg;
          switch (error) {
          case 'invalid':
            console.error("Failed loading CSV data of " + target.name + ".");
            alert("There was an error with " + target.name + ".\nPlease retry in a few moments.");
            this$.is_invalid = true;
            break;
          case 'empty':
            msg = "No data for " + target.name + "\n during interval from \n" + started_at + " to " + stopped_at + ".";
            console.warn(msg);
            targetButton.addClass('empty');
            break;
          }
27097d87   Goutte   Change the error ...
266
          targetButton.addClass('failed');
9bfa6c42   Goutte   More bug hunting.
267
268
          targetButton.removeClass('loading');
          return this$.hideLoader();
2c0e1515   Goutte   Refactor loading ...
269
270
271
272
        });
      });
    };
    SpaceWeather.prototype.clearPlots = function(){
2c0e1515   Goutte   Refactor loading ...
273
      this.orbits.clear();
80352490   Goutte   Multi model suppo...
274
      this.time_series.forEach(function(ts){
2c0e1515   Goutte   Refactor loading ...
275
276
277
        return ts.clear();
      });
      this.orbits = null;
80352490   Goutte   Multi model suppo...
278
      this.time_series = [];
2c0e1515   Goutte   Refactor loading ...
279
      return this;
f75faf5f   Goutte   WIP
280
    };
b60e7acd   Goutte   Rename "source" i...
281
    SpaceWeather.prototype.createTimeSeries = function(target, data){
7d6dee0f   Goutte   Continue refacto ...
282
      var this$ = this;
4816cef4   Goutte   Refactor some more.
283
284
      this.configuration['parameters'].forEach(function(parameter){
        var container, id, title;
b7fe650c   Goutte   Misc bundle of ol...
285
        container = this$.configuration['time_series_container'];
4816cef4   Goutte   Refactor some more.
286
287
288
289
290
        id = parameter['id'];
        title = parameter['title'];
        if (!(id in data)) {
          console.error("No data for id '" + id + "'.", data);
        }
80352490   Goutte   Multi model suppo...
291
        return this$.time_series.push(new TimeSeries(id, title, target, data[id], this$.parameters[id].active, container));
4816cef4   Goutte   Refactor some more.
292
      });
80352490   Goutte   Multi model suppo...
293
      this.time_series.forEach(function(ts){
4816cef4   Goutte   Refactor some more.
294
        ts.options['onMouseOver'] = function(){
80352490   Goutte   Multi model suppo...
295
          this$.time_series.forEach(function(ts2){
4816cef4   Goutte   Refactor some more.
296
297
            return ts2.showCursor();
          });
9c0c4509   Goutte   Add a loader to t...
298
          return true;
4816cef4   Goutte   Refactor some more.
299
300
        };
        ts.options['onMouseOut'] = function(){
80352490   Goutte   Multi model suppo...
301
          this$.time_series.forEach(function(ts2){
4816cef4   Goutte   Refactor some more.
302
303
            return ts2.hideCursor();
          });
9c0c4509   Goutte   Add a loader to t...
304
          return true;
4816cef4   Goutte   Refactor some more.
305
        };
c3008fb2   Goutte   Clean up and refa...
306
        ts.options['onMouseMove'] = function(t){
fe3132dd   Goutte   Refactor even more.
307
          var ref$;
80352490   Goutte   Multi model suppo...
308
          this$.time_series.forEach(function(ts2){
4816cef4   Goutte   Refactor some more.
309
310
            return ts2.moveCursor(t);
          });
9c0c4509   Goutte   Add a loader to t...
311
312
313
314
          if ((ref$ = this$.orbits) != null) {
            ref$.moveToDate(t);
          }
          return true;
4816cef4   Goutte   Refactor some more.
315
        };
c3008fb2   Goutte   Clean up and refa...
316
        ts.options['onBrushEnd'] = function(sta, sto){
243cd8a4   Goutte   Timestamp party c...
317
          this$.resizeDomain(moment(sta), moment(sto));
9c0c4509   Goutte   Add a loader to t...
318
          return true;
c3008fb2   Goutte   Clean up and refa...
319
320
        };
        return ts.options['onDblClick'] = function(){
9c0c4509   Goutte   Add a loader to t...
321
322
323
324
325
326
          var ref$;
          this$.resetZoom();
          if ((ref$ = $("#zoom_controls_help")) != null) {
            ref$.remove();
          }
          return true;
c3008fb2   Goutte   Clean up and refa...
327
        };
4816cef4   Goutte   Refactor some more.
328
      });
80352490   Goutte   Multi model suppo...
329
      return this.time_series;
4816cef4   Goutte   Refactor some more.
330
    };
cad44b6d   Goutte   Finish adding the...
331
332
333
334
335
336
337
338
339
340
341
    SpaceWeather.prototype.getEnabledParameters = function(){
      var i$, ref$, len$, p, slug, results$ = [];
      for (i$ = 0, len$ = (ref$ = this.parameters).length; i$ < len$; ++i$) {
        p = i$;
        slug = ref$[i$];
        if (p.active) {
          results$.push(p);
        }
      }
      return results$;
    };
b7fe650c   Goutte   Misc bundle of ol...
342
    SpaceWeather.prototype.enableParameter = function(parameter_slug){
4cf497e0   Goutte   Make the targets ...
343
      var this$ = this;
b7fe650c   Goutte   Misc bundle of ol...
344
345
346
      if (!(parameter_slug in this.parameters)) {
        console.error("Unknown parameter " + parameter_slug + ".");
      }
b7fe650c   Goutte   Misc bundle of ol...
347
      this.parameters[parameter_slug].active = true;
80352490   Goutte   Multi model suppo...
348
      this.time_series.forEach(function(ts){
b60e7acd   Goutte   Rename "source" i...
349
        if (ts.parameter === parameter_slug && this$.targets[ts.target.slug].active) {
6bb225d6   Goutte   Link the time ser...
350
          return ts.show();
4cf497e0   Goutte   Make the targets ...
351
352
        }
      });
b7fe650c   Goutte   Misc bundle of ol...
353
354
355
356
357
358
      return this;
    };
    SpaceWeather.prototype.disableParameter = function(parameter_slug){
      if (!(parameter_slug in this.parameters)) {
        console.error("Unknown parameter " + parameter_slug + ".");
      }
b7fe650c   Goutte   Misc bundle of ol...
359
      this.parameters[parameter_slug].active = false;
80352490   Goutte   Multi model suppo...
360
      this.time_series.forEach(function(ts){
4cf497e0   Goutte   Make the targets ...
361
        if (ts.parameter === parameter_slug) {
6bb225d6   Goutte   Link the time ser...
362
          return ts.hide();
4cf497e0   Goutte   Make the targets ...
363
364
        }
      });
b7fe650c   Goutte   Misc bundle of ol...
365
366
      return this;
    };
a06a0a67   Goutte   Prepare the time ...
367
368
369
370
371
372
    SpaceWeather.prototype.getDomain = function(){
      if (this.current_started_at != null && this.current_stopped_at != null) {
        return [this.current_started_at, this.current_stopped_at];
      }
      return [this.started_at, this.stopped_at];
    };
8cb213b9   Goutte   Clean up, and pre...
373
    SpaceWeather.prototype.resizeDomain = function(started_at, stopped_at){
1754789b   Goutte   Decorate and clea...
374
      var ref$, max_stopped_at, formatted_started_at, formatted_stopped_at;
8cb213b9   Goutte   Clean up, and pre...
375
      if (stopped_at < started_at) {
7994cf1a   Goutte   Hunt bugs.
376
        ref$ = [stopped_at, started_at], started_at = ref$[0], stopped_at = ref$[1];
8cb213b9   Goutte   Clean up, and pre...
377
378
      }
      if (started_at === stopped_at) {
6bb225d6   Goutte   Link the time ser...
379
        console.warn("Please provide distinct start and stop dates.");
8cb213b9   Goutte   Clean up, and pre...
380
381
        return;
      }
1754789b   Goutte   Decorate and clea...
382
383
384
385
386
      max_stopped_at = started_at.clone().add(2, 'years');
      if (stopped_at > max_stopped_at) {
        console.warn("The time interval was truncated beacuse it was bigger than two years.");
        stopped_at = max_stopped_at;
      }
243cd8a4   Goutte   Timestamp party c...
387
388
389
      this.setStartAndStop(started_at, stopped_at);
      formatted_started_at = started_at.format();
      formatted_stopped_at = stopped_at.format();
80352490   Goutte   Multi model suppo...
390
      if (!this.is_invalid && (this.started_at <= started_at && started_at <= this.stopped_at) && (this.started_at <= stopped_at && stopped_at <= this.stopped_at)) {
243cd8a4   Goutte   Timestamp party c...
391
        console.info("Resizing the temporal domain from " + formatted_started_at + " to " + formatted_stopped_at + " without fetching new data…");
80352490   Goutte   Multi model suppo...
392
        this.time_series.forEach(function(ts){
6bb225d6   Goutte   Link the time ser...
393
394
395
396
          if (!ts.visible) {
            return ts.zoomIn(started_at, stopped_at);
          }
        });
80352490   Goutte   Multi model suppo...
397
        this.time_series.forEach(function(ts){
6bb225d6   Goutte   Link the time ser...
398
399
400
          if (ts.visible) {
            return ts.zoomIn(started_at, stopped_at);
          }
8cb213b9   Goutte   Clean up, and pre...
401
402
        });
        this.orbits.resizeDomain(started_at, stopped_at);
243cd8a4   Goutte   Timestamp party c...
403
      } else {
80352490   Goutte   Multi model suppo...
404
        this.is_invalid = false;
243cd8a4   Goutte   Timestamp party c...
405
406
407
408
        console.info("Resizing the temporal domain from " + formatted_started_at + " to " + formatted_stopped_at + " and fetching new data…");
        console.warn("This might take a while… Why not see what else we're up to on http://cdpp.eu while you're waiting?");
        this.clearPlots();
        this.loadAndCreatePlots(started_at, stopped_at);
8cb213b9   Goutte   Clean up, and pre...
409
      }
243cd8a4   Goutte   Timestamp party c...
410
      return this;
8cb213b9   Goutte   Clean up, and pre...
411
    };
6bb225d6   Goutte   Link the time ser...
412
    SpaceWeather.prototype.resetZoom = function(){
80352490   Goutte   Multi model suppo...
413
      this.time_series.forEach(function(ts){
6bb225d6   Goutte   Link the time ser...
414
415
        return ts.resetZoom();
      });
243cd8a4   Goutte   Timestamp party c...
416
417
418
419
420
      this.orbits.resetZoom();
      this.setStartAndStop(this.started_at, this.stopped_at);
      return this;
    };
    SpaceWeather.prototype.setStartAndStop = function(started_at, stopped_at){
7994cf1a   Goutte   Hunt bugs.
421
      console.info("Setting time interval from " + started_at + " to " + stopped_at + "…");
243cd8a4   Goutte   Timestamp party c...
422
423
424
425
426
      this.current_started_at = started_at;
      this.current_stopped_at = stopped_at;
      $("#started_at").val(started_at.format(INPUT_TIME_FORMAT));
      $("#stopped_at").val(stopped_at.format(INPUT_TIME_FORMAT));
      return this;
6bb225d6   Goutte   Link the time ser...
427
    };
ae0aa7d2   Goutte   Add an x axis lab...
428
429
    return SpaceWeather;
  }());
438929a4   Goutte   Rewrite the orbit...
430
431
  out$.TimeSeries = TimeSeries = (function(){
    TimeSeries.displayName = 'TimeSeries';
123313cb   Goutte   Clip the paths of...
432
    var RATIO, prototype = TimeSeries.prototype, constructor = TimeSeries;
c3008fb2   Goutte   Clean up and refa...
433
    function TimeSeries(parameter, title, target, data, visible, container, options){
4cf497e0   Goutte   Make the targets ...
434
      this.parameter = parameter;
438929a4   Goutte   Rewrite the orbit...
435
      this.title = title;
b60e7acd   Goutte   Rename "source" i...
436
      this.target = target;
6bb225d6   Goutte   Link the time ser...
437
      this.visible = visible;
438929a4   Goutte   Rewrite the orbit...
438
439
440
441
      this.container = container;
      this.options = options != null
        ? options
        : {};
08569a6b   Goutte   Add a zooming bru...
442
      this.onBrushEnd = bind$(this, 'onBrushEnd', prototype);
2038c9fb   Goutte   Add a zoom reset ...
443
      this.onDoubleClick = bind$(this, 'onDoubleClick', prototype);
541e2936   Goutte   Synchronize the t...
444
445
446
      this.onMouseOut = bind$(this, 'onMouseOut', prototype);
      this.onMouseOver = bind$(this, 'onMouseOver', prototype);
      this.onMouseMove = bind$(this, 'onMouseMove', prototype);
6bb225d6   Goutte   Link the time ser...
447
      this.setData(data);
438929a4   Goutte   Rewrite the orbit...
448
449
      this.init();
    }
2038c9fb   Goutte   Add a zoom reset ...
450
451
452
    TimeSeries.prototype.toString = function(){
      return this.title + " of " + this.target.name;
    };
6bb225d6   Goutte   Link the time ser...
453
454
455
456
457
458
459
460
461
    TimeSeries.prototype.setData = function(data){
      this.data = data;
      this.xDataExtent = d3.extent(this.data, function(d){
        return d.x;
      });
      return this.yDataExtent = d3.extent(this.data, function(d){
        return d.y;
      });
    };
438929a4   Goutte   Rewrite the orbit...
462
    TimeSeries.prototype.init = function(){
6491a1f1   Goutte   Fix up the bugs l...
463
      var formatMillisecond, formatSecond, formatMinute, formatHour, formatDay, formatWeek, formatMonth, formatYear, multiFormat, clipId, dx, this$ = this;
c3008fb2   Goutte   Clean up and refa...
464
      console.info("Initializing plot of " + this + "…");
438929a4   Goutte   Rewrite the orbit...
465
466
467
468
      this.margin = {
        top: 30,
        right: 20,
        bottom: 30,
fe3132dd   Goutte   Refactor even more.
469
        left: 80
438929a4   Goutte   Rewrite the orbit...
470
      };
6bb225d6   Goutte   Link the time ser...
471
472
      this.xScale = d3.scaleTime().domain(this.xDataExtent);
      this.yScale = d3.scaleLinear().domain(this.yDataExtent);
6491a1f1   Goutte   Fix up the bugs l...
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
      formatMillisecond = d3.timeFormat(".%L");
      formatSecond = d3.timeFormat(":%S");
      formatMinute = d3.timeFormat("%I:%M");
      formatHour = d3.timeFormat("%I:%M");
      formatDay = d3.timeFormat("%a %d");
      formatWeek = d3.timeFormat("%b %d");
      formatMonth = d3.timeFormat("%B");
      formatYear = d3.timeFormat("%Y");
      multiFormat = function(date){
        if (date > d3.timeSecond(date)) {
          return formatMillisecond(date);
        }
        if (date > d3.timeMinute(date)) {
          return formatSecond(date);
        }
        if (date > d3.timeHour(date)) {
          return formatMinute(date);
        }
        if (date > d3.timeDay(date)) {
          return formatHour(date);
        }
        if (date > d3.timeMonth(date)) {
          if (date > d3.timeWeek(date)) {
            return formatDay(date);
          } else {
            return formatWeek(date);
          }
        }
        if (date > d3.timeYear(date)) {
          return formatMonth(date);
        }
        return formatYear(date);
      };
      this.xAxis = d3.axisBottom().tickFormat(multiFormat).ticks(7);
438929a4   Goutte   Rewrite the orbit...
507
508
509
510
511
512
513
      this.yAxis = d3.axisLeft().ticks(10);
      this.line = d3.line().x(function(d){
        return this$.xScale(d.x);
      }).y(function(d){
        return this$.yScale(d.y);
      });
      this.svg = d3.select(this.container).append('svg');
b60e7acd   Goutte   Rename "source" i...
514
      this.svg.attr("class", this.parameter + " " + this.target.slug);
438929a4   Goutte   Rewrite the orbit...
515
516
      this.plotWrapper = this.svg.append('g');
      this.plotWrapper.attr('transform', 'translate(' + this.margin.left + ',' + this.margin.top + ')');
123313cb   Goutte   Clip the paths of...
517
518
519
520
521
      clipId = "ts-clip-" + this.parameter + "-" + this.target.slug;
      this.clip = this.svg.append("defs").append("svg:clipPath").attr("id", clipId).append("svg:rect").attr("x", 0).attr("y", 0);
      this.pathWrapper = this.plotWrapper.append('g');
      this.pathWrapper.attr("clip-path", "url(#" + clipId + ")");
      this.path = this.pathWrapper.append('path').datum(this.data).classed('line', true);
08569a6b   Goutte   Add a zooming bru...
522
523
      this.brush = this.plotWrapper.append("g").attr("class", "brush");
      this.mouseCanvas = this.plotWrapper.append("rect").style("fill", "none");
438929a4   Goutte   Rewrite the orbit...
524
525
526
      this.plotWrapper.append('g').classed('x axis', true);
      this.plotWrapper.append('g').classed('y axis', true);
      this.yAxisText = this.plotWrapper.append("text").attr("transform", "rotate(-90)").attr("dy", "1em").style("text-anchor", "middle").text(this.title);
b60e7acd   Goutte   Rename "source" i...
527
      this.yAxisTextTarget = this.plotWrapper.append("text").attr("transform", "rotate(-90)").attr("dy", "1em").style("text-anchor", "middle").style("font-style", "oblique").text(this.target.name);
81c9b2e8   Goutte   Add the values to...
528
529
      this.focus = this.plotWrapper.append('g').style("display", "none");
      this.cursorCircle = this.focus.append("circle").attr("class", "cursor-circle").attr("r", 3);
541e2936   Goutte   Synchronize the t...
530
531
532
533
534
      dx = 8;
      this.cursorValueShadow = this.focus.append("text").attr("class", "cursor-text cursor-text-shadow").attr("dx", dx).attr("dy", "-.3em");
      this.cursorValue = this.focus.append("text").attr("class", "cursor-text cursor-value").attr("dx", dx).attr("dy", "-.3em");
      this.cursorDateShadow = this.focus.append("text").attr("class", "cursor-text cursor-text-shadow").attr("dx", dx).attr("dy", "1em");
      this.cursorDate = this.focus.append("text").attr("class", "cursor-text cursor-date").attr("dx", dx).attr("dy", "1em");
438929a4   Goutte   Rewrite the orbit...
535
536
      return this.resize();
    };
123313cb   Goutte   Clip the paths of...
537
    RATIO = GOLDEN_RATIO * GOLDEN_RATIO * GOLDEN_RATIO * GOLDEN_RATIO;
438929a4   Goutte   Rewrite the orbit...
538
539
    TimeSeries.prototype.resize = function(){
      var width, height;
123313cb   Goutte   Clip the paths of...
540
541
      width = Math.ceil($(this.container).width() - this.margin.left - this.margin.right);
      height = Math.ceil(RATIO * width);
541e2936   Goutte   Synchronize the t...
542
543
      this.plotWidth = width;
      this.plotHeight = height;
123313cb   Goutte   Clip the paths of...
544
      console.debug("Resizing " + this + ": " + width + " x " + height + "…");
438929a4   Goutte   Rewrite the orbit...
545
546
547
      this.xScale.range([0, width]);
      this.yScale.range([height, 0]);
      this.svg.attr('width', width + this.margin.right + this.margin.left).attr('height', height + this.margin.top + this.margin.bottom);
123313cb   Goutte   Clip the paths of...
548
      this.clip.attr("width", width).attr("height", height);
438929a4   Goutte   Rewrite the orbit...
549
550
551
      this.path.attr('d', this.line);
      this.xAxis.scale(this.xScale);
      this.yAxis.scale(this.yScale);
d49a163c   Goutte   Fix the resize an...
552
553
      this.xAxis.ticks(Math.floor(width / 90.0));
      this.yAxis.ticks(Math.floor(height / 18.0));
438929a4   Goutte   Rewrite the orbit...
554
555
      this.svg.select('.x.axis').attr('transform', 'translate(0,' + height + ')').call(this.xAxis);
      this.svg.select('.y.axis').call(this.yAxis);
fe3132dd   Goutte   Refactor even more.
556
      this.yAxisText.attr("y", 20 - this.margin.left).attr("x", 0 - height / 2);
b60e7acd   Goutte   Rename "source" i...
557
      this.yAxisTextTarget.attr("y", 0 - this.margin.left).attr("x", 0 - height / 2);
2463bd16   Goutte   Add a circle foll...
558
      this.mouseCanvas.attr("width", width).attr("height", height);
08569a6b   Goutte   Add a zooming bru...
559
      if (this.brushFunction == null) {
c3008fb2   Goutte   Clean up and refa...
560
        console.debug("Creating the zooming brush for " + this + "…");
08569a6b   Goutte   Add a zooming bru...
561
562
        this.brushFunction = d3.brushX().extent([[0, 0], [width, height]]).handleSize(0).on("end", this.onBrushEnd);
        this.brush.call(this.brushFunction);
c3008fb2   Goutte   Clean up and refa...
563
        this.svg.select(".brush .overlay").on("mouseover.swapp", this.onMouseOver).on("mouseout.swapp", this.onMouseOut).on("mousemove.swapp", this.onMouseMove).on("dblclick.swapp", this.onDoubleClick);
08569a6b   Goutte   Add a zooming bru...
564
      }
6bb225d6   Goutte   Link the time ser...
565
566
      if (!this.visible) {
        this.hide();
b7fe650c   Goutte   Misc bundle of ol...
567
      }
2463bd16   Goutte   Add a circle foll...
568
569
      return this;
    };
2c0e1515   Goutte   Refactor loading ...
570
571
572
573
    TimeSeries.prototype.clear = function(){
      $(this.svg.node()).remove();
      return this.visible = false;
    };
6bb225d6   Goutte   Link the time ser...
574
575
576
577
578
579
580
581
    TimeSeries.prototype.show = function(){
      $(this.svg.node()).show();
      return this.visible = true;
    };
    TimeSeries.prototype.hide = function(){
      $(this.svg.node()).hide();
      return this.visible = false;
    };
541e2936   Goutte   Synchronize the t...
582
583
584
585
    TimeSeries.prototype.onMouseMove = function(){
      var x;
      x = this.xScale.invert(d3.mouse(this.mouseCanvas.node())[0]);
      if (this.options.onMouseMove != null) {
2038c9fb   Goutte   Add a zoom reset ...
586
        return this.options.onMouseMove(x);
541e2936   Goutte   Synchronize the t...
587
      } else {
2038c9fb   Goutte   Add a zoom reset ...
588
        return this.moveCursor(x);
541e2936   Goutte   Synchronize the t...
589
      }
541e2936   Goutte   Synchronize the t...
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
    };
    TimeSeries.prototype.onMouseOver = function(){
      if (this.options.onMouseOver != null) {
        return this.options.onMouseOver();
      } else {
        return this.showCursor();
      }
    };
    TimeSeries.prototype.onMouseOut = function(){
      if (this.options.onMouseOut != null) {
        return this.options.onMouseOut();
      } else {
        return this.hideCursor();
      }
    };
2038c9fb   Goutte   Add a zoom reset ...
605
    TimeSeries.prototype.onDoubleClick = function(){
c3008fb2   Goutte   Clean up and refa...
606
607
608
609
610
      if (this.options.onDblClick != null) {
        return this.options.onDblClick();
      } else {
        return this.resetZoom();
      }
2038c9fb   Goutte   Add a zoom reset ...
611
    };
08569a6b   Goutte   Add a zooming bru...
612
613
614
    TimeSeries.prototype.onBrushEnd = function(){
      var s, minmax;
      s = d3.event.selection;
08569a6b   Goutte   Add a zooming bru...
615
616
      if (s) {
        minmax = [s[0], s[1]].map(this.xScale.invert, this.xScale);
08569a6b   Goutte   Add a zooming bru...
617
        this.brush.call(this.brushFunction.move, null);
c3008fb2   Goutte   Clean up and refa...
618
619
620
621
622
        if (this.options.onBrushEnd != null) {
          return this.options.onBrushEnd(minmax[0], minmax[1]);
        } else {
          return this.zoomIn(minmax[0], minmax[1]);
        }
2038c9fb   Goutte   Add a zoom reset ...
623
624
625
626
627
      }
    };
    TimeSeries.prototype.zoomIn = function(startDate, stopDate){
      var ref$, minDate, maxDate;
      console.debug("Zooming in " + this + " from " + startDate + " to " + stopDate + ".");
6bb225d6   Goutte   Link the time ser...
628
      ref$ = this.xDataExtent, minDate = ref$[0], maxDate = ref$[1];
2038c9fb   Goutte   Add a zoom reset ...
629
630
631
632
633
      if (startDate < minDate) {
        startDate = minDate;
      }
      if (stopDate > maxDate) {
        stopDate = maxDate;
08569a6b   Goutte   Add a zooming bru...
634
      }
2038c9fb   Goutte   Add a zoom reset ...
635
636
637
638
      this.xScale.domain([startDate, stopDate]);
      return this.applyZoom();
    };
    TimeSeries.prototype.resetZoom = function(){
6bb225d6   Goutte   Link the time ser...
639
640
      this.xScale.domain(this.xDataExtent);
      this.yScale.domain(this.yDataExtent);
2038c9fb   Goutte   Add a zoom reset ...
641
      return this.applyZoom();
08569a6b   Goutte   Add a zooming bru...
642
    };
2038c9fb   Goutte   Add a zoom reset ...
643
    TimeSeries.prototype.applyZoom = function(){
08569a6b   Goutte   Add a zooming bru...
644
      var t;
6bb225d6   Goutte   Link the time ser...
645
      if (this.visible) {
c3008fb2   Goutte   Clean up and refa...
646
        console.debug("Applying zoom to visible " + this + "…");
6bb225d6   Goutte   Link the time ser...
647
648
649
650
651
        t = this.svg.transition().duration(750);
        this.svg.select('.x.axis').transition(t).call(this.xAxis);
        this.svg.select('.y.axis').transition(t).call(this.yAxis);
        return this.path.transition(t).attr('d', this.line);
      } else {
c3008fb2   Goutte   Clean up and refa...
652
        console.debug("Applying zoom to hidden " + this + "…");
6bb225d6   Goutte   Link the time ser...
653
654
655
656
        this.svg.select('.x.axis').call(this.xAxis);
        this.svg.select('.y.axis').call(this.yAxis);
        return this.path.attr('d', this.line);
      }
08569a6b   Goutte   Add a zooming bru...
657
    };
541e2936   Goutte   Synchronize the t...
658
659
660
661
662
663
    TimeSeries.prototype.showCursor = function(){
      return this.focus.style("display", null);
    };
    TimeSeries.prototype.hideCursor = function(){
      return this.focus.style("display", "none");
    };
2463bd16   Goutte   Add a circle foll...
664
665
666
    TimeSeries.prototype.bisectDate = d3.bisector(function(d){
      return d.x;
    }).left;
6491a1f1   Goutte   Fix up the bugs l...
667
    TimeSeries.prototype.timeFormat = d3.timeFormat("%Y-%m-%d %H:%M");
541e2936   Goutte   Synchronize the t...
668
    TimeSeries.prototype.moveCursor = function(x0){
8cb213b9   Goutte   Clean up, and pre...
669
      var i, d0, d1, d, xx, yy, mirrored, dx, transform;
2463bd16   Goutte   Add a circle foll...
670
671
672
      i = this.bisectDate(this.data, x0, 1);
      d0 = this.data[i - 1];
      d1 = this.data[i];
541e2936   Goutte   Synchronize the t...
673
674
675
      if (!(d1 && d0)) {
        return;
      }
2463bd16   Goutte   Add a circle foll...
676
677
678
      d = x0 - d0.x > d1.x - x0 ? d1 : d0;
      xx = this.xScale(d.x);
      yy = this.yScale(d.y);
541e2936   Goutte   Synchronize the t...
679
680
681
682
683
      mirrored = this.plotWidth != null && xx > this.plotWidth / 2 ? true : false;
      dx = 8;
      if (mirrored) {
        dx = -1 * dx;
      }
8cb213b9   Goutte   Clean up, and pre...
684
      transform = "translate(" + xx + ", " + yy + ")";
81c9b2e8   Goutte   Add the values to...
685
      this.cursorCircle.attr("transform", transform);
541e2936   Goutte   Synchronize the t...
686
687
688
689
      this.cursorValue.attr("transform", transform).text(d.y).attr('text-anchor', mirrored ? 'end' : 'start').attr("dx", dx);
      this.cursorValueShadow.attr("transform", transform).text(d.y).attr('text-anchor', mirrored ? 'end' : 'start').attr("dx", dx);
      this.cursorDate.attr("transform", transform).text(this.timeFormat(d.x)).attr('text-anchor', mirrored ? 'end' : 'start').attr("dx", dx);
      this.cursorDateShadow.attr("transform", transform).text(this.timeFormat(d.x)).attr('text-anchor', mirrored ? 'end' : 'start').attr("dx", dx);
438929a4   Goutte   Rewrite the orbit...
690
691
692
693
694
      return this;
    };
    return TimeSeries;
  }());
  out$.Orbits = Orbits = (function(){
8cb213b9   Goutte   Clean up, and pre...
695
    "View of the solar system from above, with orbits segments for selected time\ninterval, from real data.";
438929a4   Goutte   Rewrite the orbit...
696
697
    Orbits.displayName = 'Orbits';
    var prototype = Orbits.prototype, constructor = Orbits;
a21f81d9   Goutte   Enable Venus and ...
698
    function Orbits(container, options){
438929a4   Goutte   Rewrite the orbit...
699
700
701
702
      this.container = container;
      this.options = options != null
        ? options
        : {};
438929a4   Goutte   Rewrite the orbit...
703
704
705
      this.init();
    }
    Orbits.prototype.init = function(){
c3008fb2   Goutte   Clean up and refa...
706
      console.log("Initializing plot of orbits…");
438929a4   Goutte   Rewrite the orbit...
707
708
709
      this.margin = {
        top: 30,
        right: 20,
11662eed   Goutte   Add Y axis label ...
710
        bottom: 42,
438929a4   Goutte   Rewrite the orbit...
711
712
        left: 60
      };
a21f81d9   Goutte   Enable Venus and ...
713
714
      this.data = {};
      this.orbiters = {};
7994cf1a   Goutte   Hunt bugs.
715
      this.orbitersElements = {};
17c52617   Goutte   Make the orbits p...
716
717
718
719
      this.orbitersExtrema = {};
      this.lastOrbiterData = {};
      this.xScale = d3.scaleLinear().domain([-1, 1]);
      this.yScale = d3.scaleLinear().domain([1, -1]);
438929a4   Goutte   Rewrite the orbit...
720
721
722
723
724
      this.xAxis = d3.axisBottom().ticks(10);
      this.yAxis = d3.axisLeft().ticks(10);
      this.svg = d3.select(this.container).append('svg');
      this.plotWrapper = this.svg.append('g');
      this.plotWrapper.attr('transform', 'translate(' + this.margin.left + ',' + this.margin.top + ')');
ae0aa7d2   Goutte   Add an x axis lab...
725
726
727
728
      this.xAxisLine = this.plotWrapper.append('g').classed('x axis', true);
      this.yAxisLine = this.plotWrapper.append('g').classed('y axis', true);
      this.xAxisTitle = this.xAxisLine.append('text').attr('fill', '#000');
      this.xAxisTitle.style("text-anchor", "middle");
b500e561   Goutte   Invert the orbits...
729
      this.xAxisTitle.append('tspan').text('Y');
11662eed   Goutte   Add Y axis label ...
730
      this.xAxisTitle.append('tspan').attr('dy', '3px').text('HEE').attr('font-size', '8px');
ae0aa7d2   Goutte   Add an x axis lab...
731
      this.xAxisTitle.append('tspan').attr('dy', '-3px').text('   (AU)');
11662eed   Goutte   Add Y axis label ...
732
733
      this.yAxisTitle = this.yAxisLine.append('text').attr('fill', '#000');
      this.yAxisTitle.style("text-anchor", "middle");
b500e561   Goutte   Invert the orbits...
734
      this.yAxisTitle.append('tspan').text('X');
11662eed   Goutte   Add Y axis label ...
735
736
737
      this.yAxisTitle.append('tspan').attr('dy', '3px').text('HEE').attr('font-size', '8px');
      this.yAxisTitle.append('tspan').attr('dy', '-3px').text('   (AU)');
      this.yAxisTitle.attr('transform', 'rotate(-90)');
8bd715ad   Goutte   Use a pixel art i...
738
      this.sun = this.plotWrapper.append("svg:image").attr('xlink:href', this.options.sun.img).attr('width', '32px').attr('height', '32px');
6491a1f1   Goutte   Fix up the bugs l...
739
      this.sun.append('svg:title').text("Sun");
3ee0b596   Goutte   Fix an annoying b...
740
      $(this.svg.node()).hide();
438929a4   Goutte   Rewrite the orbit...
741
742
      return this.resize();
    };
a21f81d9   Goutte   Enable Venus and ...
743
    Orbits.prototype.initOrbiter = function(slug, config, data){
438929a4   Goutte   Rewrite the orbit...
744
      var orbit_ellipse, orbiter, orbit_line, orbit_section, this$ = this;
dc0be992   Goutte   Support having no...
745
746
747
748
749
750
751
752
      this.data[slug] = data;
      this.orbiters[slug] = config;
      if (data.length) {
        console.info("Initializing orbit of " + config.name + "…");
      } else {
        console.warn("No orbit data for " + config.name + "…");
        return;
      }
438929a4   Goutte   Rewrite the orbit...
753
754
755
      if (slug in this.orbitersElements) {
        throw new Error("Second init of " + slug);
      }
438929a4   Goutte   Rewrite the orbit...
756
757
      orbit_ellipse = this.plotWrapper.append("svg:ellipse").classed('orbit orbit_ellipse', true);
      orbiter = this.plotWrapper.append("svg:image").attr('xlink:href', config['img']).attr('width', '32px').attr('height', '32px');
6491a1f1   Goutte   Fix up the bugs l...
758
      orbiter.append('svg:title').text(config.name);
438929a4   Goutte   Rewrite the orbit...
759
      orbit_line = d3.line().x(function(d){
b500e561   Goutte   Invert the orbits...
760
        return this$.xScale(d.y);
438929a4   Goutte   Rewrite the orbit...
761
      }).y(function(d){
b500e561   Goutte   Invert the orbits...
762
        return this$.yScale(d.x);
438929a4   Goutte   Rewrite the orbit...
763
      });
a21f81d9   Goutte   Enable Venus and ...
764
      orbit_section = this.plotWrapper.append('path').datum(data).classed('orbit orbit_section', true);
438929a4   Goutte   Rewrite the orbit...
765
766
767
768
769
770
      this.orbitersElements[slug] = {
        orbiter: orbiter,
        orbit_ellipse: orbit_ellipse,
        orbit_section: orbit_section,
        orbit_line: orbit_line
      };
17c52617   Goutte   Make the orbits p...
771
772
773
      this.orbitersExtrema[slug] = d3.max(data, function(d){
        return Math.max(Math.abs(d.x), Math.abs(d.y));
      });
3ee0b596   Goutte   Fix an annoying b...
774
      $(this.svg.node()).show();
17c52617   Goutte   Make the orbits p...
775
      this.resize(true);
438929a4   Goutte   Rewrite the orbit...
776
777
      return this;
    };
17c52617   Goutte   Make the orbits p...
778
    Orbits.prototype.showOrbiter = function(slug){
dc0be992   Goutte   Support having no...
779
780
781
      if (!this.data[slug].length) {
        return;
      }
17c52617   Goutte   Make the orbits p...
782
783
784
785
786
787
788
      this.orbiters[slug].hidden = false;
      this.orbitersElements[slug].orbiter.style("display", null);
      this.orbitersElements[slug].orbit_ellipse.style("display", null);
      this.orbitersElements[slug].orbit_section.style("display", null);
      return this.resize(true);
    };
    Orbits.prototype.hideOrbiter = function(slug){
dc0be992   Goutte   Support having no...
789
790
791
      if (!this.data[slug].length) {
        return;
      }
17c52617   Goutte   Make the orbits p...
792
793
794
795
796
797
      this.orbiters[slug].hidden = true;
      this.orbitersElements[slug].orbiter.style("display", "none");
      this.orbitersElements[slug].orbit_ellipse.style("display", "none");
      this.orbitersElements[slug].orbit_section.style("display", "none");
      return this.resize(true);
    };
2c0e1515   Goutte   Refactor loading ...
798
799
800
    Orbits.prototype.clear = function(){
      return $(this.svg.node()).remove();
    };
17c52617   Goutte   Make the orbits p...
801
802
803
    Orbits.prototype.resize = function(animate){
      var width, height, extremum, s, o, slug, ref$, config, t, t1, this$ = this;
      animate == null && (animate = false);
667eeb24   Goutte   Resize the domain...
804
805
806
      width = Math.ceil($(this.container).width() - this.margin.left - this.margin.right);
      height = Math.ceil(1.0 * width);
      console.debug("Resizing orbits : " + width + " × " + height + "…");
17c52617   Goutte   Make the orbits p...
807
808
809
810
811
812
813
814
815
816
817
818
819
820
      extremum = 1.1 * d3.max((function(){
        var ref$, results$ = [];
        for (s in ref$ = this.orbiters) {
          o = ref$[s];
          if (!o.hidden) {
            results$.push(s);
          }
        }
        return results$;
      }.call(this)), function(d){
        return this$.orbitersExtrema[d];
      });
      this.xScale = d3.scaleLinear().domain([-1 * extremum, extremum]);
      this.yScale = d3.scaleLinear().domain([extremum, -1 * extremum]);
438929a4   Goutte   Rewrite the orbit...
821
      this.xScale.range([0, width]);
17c52617   Goutte   Make the orbits p...
822
      this.yScale.range([height, 0]);
438929a4   Goutte   Rewrite the orbit...
823
      this.svg.attr('width', width + this.margin.right + this.margin.left).attr('height', height + this.margin.top + this.margin.bottom);
8bd715ad   Goutte   Use a pixel art i...
824
      this.sun.attr("x", width / 2 - 16).attr("y", height / 2 - 16);
438929a4   Goutte   Rewrite the orbit...
825
826
      for (slug in ref$ = this.orbiters) {
        config = ref$[slug];
17c52617   Goutte   Make the orbits p...
827
        this.resizeOrbiter(slug, config, width, height, animate);
438929a4   Goutte   Rewrite the orbit...
828
829
830
      }
      this.xAxis.scale(this.xScale);
      this.yAxis.scale(this.yScale);
17c52617   Goutte   Make the orbits p...
831
832
833
834
835
836
837
838
839
840
      this.svg.select('.x.axis').attr('transform', 'translate(0,' + height + ')');
      if (animate) {
        t = this.svg.transition().duration(750);
        t1 = this.svg.transition().duration(4750);
        this.svg.select('.x.axis').transition(t).call(this.xAxis);
        this.svg.select('.y.axis').transition(t).call(this.yAxis);
      } else {
        this.svg.select('.x.axis').call(this.xAxis);
        this.svg.select('.y.axis').call(this.yAxis);
      }
11662eed   Goutte   Add Y axis label ...
841
842
      this.xAxisTitle.attr("x", width / 2).attr("y", 37);
      this.yAxisTitle.attr("x", -1 * height / 2).attr("y", -30);
438929a4   Goutte   Rewrite the orbit...
843
844
      return this;
    };
17c52617   Goutte   Make the orbits p...
845
    Orbits.prototype.resizeOrbiter = function(slug, config, width, height, animate){
dc0be992   Goutte   Support having no...
846
      var data, tt, el, orbit_section, t, a, b, c, cx, cy, orbit_ellipse;
17c52617   Goutte   Make the orbits p...
847
      animate == null && (animate = false);
dc0be992   Goutte   Support having no...
848
849
850
851
      data = this.data[slug];
      if (!data.length) {
        return;
      }
667eeb24   Goutte   Resize the domain...
852
      console.debug("Resizing orbit of " + slug + "…");
17c52617   Goutte   Make the orbits p...
853
      tt = this.svg.transition().duration(750);
438929a4   Goutte   Rewrite the orbit...
854
      el = this.orbitersElements[slug];
17c52617   Goutte   Make the orbits p...
855
856
857
858
859
860
      orbit_section = el['orbit_section'];
      if (animate) {
        t = this.svg.transition().duration(750);
        orbit_section = orbit_section.transition(tt);
      }
      orbit_section.attr('d', el['orbit_line']);
438929a4   Goutte   Rewrite the orbit...
861
862
863
864
865
      a = config['orbit']['a'];
      b = config['orbit']['b'];
      c = Math.sqrt(a * a - b * b);
      cx = width / 2 - c;
      cy = height / 2;
17c52617   Goutte   Make the orbits p...
866
867
868
869
870
871
872
      orbit_ellipse = el['orbit_ellipse'];
      if (animate) {
        t = this.svg.transition().duration(750);
        orbit_ellipse = orbit_ellipse.transition(t);
      }
      orbit_ellipse.attr('cx', cx).attr('cy', cy).attr('rx', this.xScale(a) - this.xScale(0)).attr('ry', this.yScale(b) - this.yScale(0));
      this.repositionOrbiter(slug, null, true);
438929a4   Goutte   Rewrite the orbit...
873
874
      return this;
    };
17c52617   Goutte   Make the orbits p...
875
876
877
    Orbits.prototype.repositionOrbiter = function(slug, datum, animate){
      var data, el, t;
      animate == null && (animate = false);
a21f81d9   Goutte   Enable Venus and ...
878
      data = this.data[slug];
dc0be992   Goutte   Support having no...
879
880
881
      if (!data.length) {
        return;
      }
17c52617   Goutte   Make the orbits p...
882
      datum == null && (datum = this.lastOrbiterData[slug]);
ae0aa7d2   Goutte   Add an x axis lab...
883
      datum == null && (datum = data[data.length - 1]);
17c52617   Goutte   Make the orbits p...
884
885
886
887
888
889
890
891
      this.lastOrbiterData[slug] = datum;
      el = this.orbitersElements[slug]['orbiter'];
      if (animate) {
        t = this.svg.transition().duration(750);
        el = el.transition(t);
      }
      el.attr('x', this.xScale(datum.y) - 16);
      el.attr('y', this.yScale(datum.x) - 16);
ae0aa7d2   Goutte   Add an x axis lab...
892
893
894
895
896
897
      return this;
    };
    Orbits.prototype.bisectDate = d3.bisector(function(d){
      return d.t;
    }).left;
    Orbits.prototype.moveToDate = function(t){
a21f81d9   Goutte   Enable Venus and ...
898
899
      var slug, ref$, el, data, i, d0, d1, d;
      if (!t) {
667eeb24   Goutte   Resize the domain...
900
        console.warn("Trying to move to an undefined date !");
a21f81d9   Goutte   Enable Venus and ...
901
      }
ae0aa7d2   Goutte   Add an x axis lab...
902
903
      for (slug in ref$ = this.orbitersElements) {
        el = ref$[slug];
a21f81d9   Goutte   Enable Venus and ...
904
        data = this.data[slug];
ae0aa7d2   Goutte   Add an x axis lab...
905
906
907
908
909
910
911
        i = this.bisectDate(data, t, 1);
        d0 = data[i - 1];
        d1 = data[i];
        if (!(d1 && d0)) {
          continue;
        }
        d = t - d0.t > d1.t - t ? d1 : d0;
a21f81d9   Goutte   Enable Venus and ...
912
        this.repositionOrbiter(slug, d);
ae0aa7d2   Goutte   Add an x axis lab...
913
      }
a21f81d9   Goutte   Enable Venus and ...
914
      return this;
ae0aa7d2   Goutte   Add an x axis lab...
915
    };
667eeb24   Goutte   Resize the domain...
916
    Orbits.prototype.resizeDomain = function(started_at, stopped_at){
dc0be992   Goutte   Support having no...
917
      var slug, ref$, config, el, data;
667eeb24   Goutte   Resize the domain...
918
919
920
921
      for (slug in ref$ = this.orbiters) {
        config = ref$[slug];
        el = this.orbitersElements[slug];
        data = this.data[slug].filter(fn$);
dc0be992   Goutte   Support having no...
922
923
924
        if (!data.length) {
          return;
        }
667eeb24   Goutte   Resize the domain...
925
        el['orbit_section'].datum(data);
dc0be992   Goutte   Support having no...
926
        el['orbit_section'].attr('d', el['orbit_line']);
667eeb24   Goutte   Resize the domain...
927
      }
667eeb24   Goutte   Resize the domain...
928
929
930
931
932
933
      function fn$(d){
        var ref$;
        return started_at <= (ref$ = d.t) && ref$ <= stopped_at;
      }
    };
    Orbits.prototype.resetZoom = function(){
dc0be992   Goutte   Support having no...
934
      var slug, ref$, config, el;
667eeb24   Goutte   Resize the domain...
935
936
937
      for (slug in ref$ = this.orbiters) {
        config = ref$[slug];
        el = this.orbitersElements[slug];
dc0be992   Goutte   Support having no...
938
939
940
        if (!this.data[slug].length) {
          return;
        }
667eeb24   Goutte   Resize the domain...
941
        el['orbit_section'].datum(this.data[slug]);
dc0be992   Goutte   Support having no...
942
        el['orbit_section'].attr('d', el['orbit_line']);
667eeb24   Goutte   Resize the domain...
943
      }
667eeb24   Goutte   Resize the domain...
944
    };
438929a4   Goutte   Rewrite the orbit...
945
946
    return Orbits;
  }());
2463bd16   Goutte   Add a circle foll...
947
948
949
  function bind$(obj, key, target){
    return function(){ return (target || obj)[key].apply(obj, arguments) };
  }
438929a4   Goutte   Rewrite the orbit...
950
}).call(this);