Blame view

web/static/js/swapp.js 37.5 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);
97d6cb96   Goutte   Change default ti...
46
      stopped_at = moment().add(1, '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;
ebe77ce4   Goutte   Clean up.
745
      console.info("Initializing orbit of " + config.name + "…");
438929a4   Goutte   Rewrite the orbit...
746
747
748
      if (slug in this.orbitersElements) {
        throw new Error("Second init of " + slug);
      }
438929a4   Goutte   Rewrite the orbit...
749
750
      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...
751
      orbiter.append('svg:title').text(config.name);
438929a4   Goutte   Rewrite the orbit...
752
      orbit_line = d3.line().x(function(d){
b500e561   Goutte   Invert the orbits...
753
        return this$.xScale(d.y);
438929a4   Goutte   Rewrite the orbit...
754
      }).y(function(d){
b500e561   Goutte   Invert the orbits...
755
        return this$.yScale(d.x);
438929a4   Goutte   Rewrite the orbit...
756
      });
a21f81d9   Goutte   Enable Venus and ...
757
      orbit_section = this.plotWrapper.append('path').datum(data).classed('orbit orbit_section', true);
a21f81d9   Goutte   Enable Venus and ...
758
      this.data[slug] = data;
17c52617   Goutte   Make the orbits p...
759
      this.orbiters[slug] = config;
438929a4   Goutte   Rewrite the orbit...
760
761
762
763
764
765
      this.orbitersElements[slug] = {
        orbiter: orbiter,
        orbit_ellipse: orbit_ellipse,
        orbit_section: orbit_section,
        orbit_line: orbit_line
      };
17c52617   Goutte   Make the orbits p...
766
767
768
      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...
769
      $(this.svg.node()).show();
17c52617   Goutte   Make the orbits p...
770
      this.resize(true);
438929a4   Goutte   Rewrite the orbit...
771
772
      return this;
    };
17c52617   Goutte   Make the orbits p...
773
774
775
776
777
778
779
780
781
782
783
784
785
786
    Orbits.prototype.showOrbiter = function(slug){
      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){
      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 ...
787
788
789
    Orbits.prototype.clear = function(){
      return $(this.svg.node()).remove();
    };
17c52617   Goutte   Make the orbits p...
790
791
792
    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...
793
794
795
      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...
796
797
798
799
800
801
802
803
804
805
806
807
808
809
      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...
810
      this.xScale.range([0, width]);
17c52617   Goutte   Make the orbits p...
811
      this.yScale.range([height, 0]);
438929a4   Goutte   Rewrite the orbit...
812
      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...
813
      this.sun.attr("x", width / 2 - 16).attr("y", height / 2 - 16);
438929a4   Goutte   Rewrite the orbit...
814
815
      for (slug in ref$ = this.orbiters) {
        config = ref$[slug];
17c52617   Goutte   Make the orbits p...
816
        this.resizeOrbiter(slug, config, width, height, animate);
438929a4   Goutte   Rewrite the orbit...
817
818
819
      }
      this.xAxis.scale(this.xScale);
      this.yAxis.scale(this.yScale);
17c52617   Goutte   Make the orbits p...
820
821
822
823
824
825
826
827
828
829
      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 ...
830
831
      this.xAxisTitle.attr("x", width / 2).attr("y", 37);
      this.yAxisTitle.attr("x", -1 * height / 2).attr("y", -30);
438929a4   Goutte   Rewrite the orbit...
832
833
      return this;
    };
17c52617   Goutte   Make the orbits p...
834
835
836
    Orbits.prototype.resizeOrbiter = function(slug, config, width, height, animate){
      var tt, el, orbit_section, t, a, b, c, cx, cy, orbit_ellipse;
      animate == null && (animate = false);
667eeb24   Goutte   Resize the domain...
837
      console.debug("Resizing orbit of " + slug + "…");
17c52617   Goutte   Make the orbits p...
838
      tt = this.svg.transition().duration(750);
438929a4   Goutte   Rewrite the orbit...
839
      el = this.orbitersElements[slug];
17c52617   Goutte   Make the orbits p...
840
841
842
843
844
845
      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...
846
847
848
849
850
      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...
851
852
853
854
855
856
857
      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...
858
859
      return this;
    };
17c52617   Goutte   Make the orbits p...
860
861
862
    Orbits.prototype.repositionOrbiter = function(slug, datum, animate){
      var data, el, t;
      animate == null && (animate = false);
a21f81d9   Goutte   Enable Venus and ...
863
      data = this.data[slug];
17c52617   Goutte   Make the orbits p...
864
      datum == null && (datum = this.lastOrbiterData[slug]);
ae0aa7d2   Goutte   Add an x axis lab...
865
      datum == null && (datum = data[data.length - 1]);
17c52617   Goutte   Make the orbits p...
866
867
868
869
870
871
872
873
      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...
874
875
876
877
878
879
      return this;
    };
    Orbits.prototype.bisectDate = d3.bisector(function(d){
      return d.t;
    }).left;
    Orbits.prototype.moveToDate = function(t){
a21f81d9   Goutte   Enable Venus and ...
880
881
      var slug, ref$, el, data, i, d0, d1, d;
      if (!t) {
667eeb24   Goutte   Resize the domain...
882
        console.warn("Trying to move to an undefined date !");
a21f81d9   Goutte   Enable Venus and ...
883
      }
ae0aa7d2   Goutte   Add an x axis lab...
884
885
      for (slug in ref$ = this.orbitersElements) {
        el = ref$[slug];
a21f81d9   Goutte   Enable Venus and ...
886
        data = this.data[slug];
ae0aa7d2   Goutte   Add an x axis lab...
887
888
889
890
891
892
893
        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 ...
894
        this.repositionOrbiter(slug, d);
ae0aa7d2   Goutte   Add an x axis lab...
895
      }
a21f81d9   Goutte   Enable Venus and ...
896
      return this;
ae0aa7d2   Goutte   Add an x axis lab...
897
    };
667eeb24   Goutte   Resize the domain...
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
    Orbits.prototype.resizeDomain = function(started_at, stopped_at){
      var slug, ref$, config, el, data, results$ = [];
      for (slug in ref$ = this.orbiters) {
        config = ref$[slug];
        el = this.orbitersElements[slug];
        data = this.data[slug].filter(fn$);
        el['orbit_section'].datum(data);
        results$.push(el['orbit_section'].attr('d', el['orbit_line']));
      }
      return results$;
      function fn$(d){
        var ref$;
        return started_at <= (ref$ = d.t) && ref$ <= stopped_at;
      }
    };
    Orbits.prototype.resetZoom = function(){
      var slug, ref$, config, el, results$ = [];
      for (slug in ref$ = this.orbiters) {
        config = ref$[slug];
        el = this.orbitersElements[slug];
        el['orbit_section'].datum(this.data[slug]);
        results$.push(el['orbit_section'].attr('d', el['orbit_line']));
      }
      return results$;
    };
438929a4   Goutte   Rewrite the orbit...
923
924
    return Orbits;
  }());
2463bd16   Goutte   Add a circle foll...
925
926
927
  function bind$(obj, key, target){
    return function(){ return (target || obj)[key].apply(obj, arguments) };
  }
438929a4   Goutte   Rewrite the orbit...
928
}).call(this);