Blame view

web/static/js/swapp.js 26.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
12
13
14
15
  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;
      this.active = true;
    }
    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';
7d6dee0f   Goutte   Continue refacto ...
19
    var timeSeries, prototype = SpaceWeather.prototype, constructor = SpaceWeather;
ae0aa7d2   Goutte   Add an x axis lab...
20
    function SpaceWeather(configuration){
fe3132dd   Goutte   Refactor even more.
21
      var configs, res$, k, this$ = this;
f75faf5f   Goutte   WIP
22
      this.configuration = configuration;
2038c9fb   Goutte   Add a zoom reset ...
23
      console.info("  _   _      _ _       ____\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...
24
      this.targets = {};
fe3132dd   Goutte   Refactor even more.
25
      res$ = [];
b60e7acd   Goutte   Rename "source" i...
26
27
      for (k in this.configuration.targets) {
        res$.push(this.configuration.targets[k]);
fe3132dd   Goutte   Refactor even more.
28
29
      }
      configs = res$;
b60e7acd   Goutte   Rename "source" i...
30
31
      configs.forEach(function(target_config){
        return this$.targets[target_config.slug] = new Target(target_config.slug, target_config.name, target_config);
fe3132dd   Goutte   Refactor even more.
32
      });
b7fe650c   Goutte   Misc bundle of ol...
33
34
35
36
      this.parameters = {};
      this.configuration['parameters'].forEach(function(p){
        return this$.parameters[p['id']] = p;
      });
ae0aa7d2   Goutte   Add an x axis lab...
37
    }
b60e7acd   Goutte   Rename "source" i...
38
39
40
41
42
43
44
45
46
47
48
    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)";
      var active_targets, res$, k, started_at, stopped_at, this$ = this;
      res$ = [];
      for (k in this.targets) {
        if (this.targets[k].config.active) {
          res$.push(this.targets[k]);
        }
      }
      active_targets = res$;
      this.orbits = new Orbits(this.configuration.orbits_container, this.configuration);
8cb213b9   Goutte   Clean up, and pre...
49
50
51
52
      this.started_at = moment().subtract(1, 'years').hours(0).minutes(0).seconds(0);
      this.stopped_at = moment().add(7, 'days').hours(0).minutes(0).seconds(0);
      started_at = this.started_at.format("YYYY-MM-DDTHH:mm:ss");
      stopped_at = this.stopped_at.format("YYYY-MM-DDTHH:mm:ss");
b60e7acd   Goutte   Rename "source" i...
53
      active_targets.forEach(function(target){
c3008fb2   Goutte   Clean up and refa...
54
        console.info("Loading CSV data of " + target.name + "…");
b60e7acd   Goutte   Rename "source" i...
55
        return this$.loadData(target.slug, started_at, stopped_at).then(function(data){
c3008fb2   Goutte   Clean up and refa...
56
          console.info("Loaded CSV data of " + target.name + ".");
b60e7acd   Goutte   Rename "source" i...
57
58
59
60
61
62
63
64
65
66
67
          this$.createTimeSeries(target, data);
          return this$.orbits.initOrbiter(target.slug, target.config, data['hci']);
        }, function(error){
          return console.error('Failed to load CSV data.', error);
        });
      });
      return window.addEventListener('resize', function(){
        return this$.resize();
      });
    };
    SpaceWeather.prototype.buildDataUrlForTarget = function(target_slug, started_at, stopped_at){
f75faf5f   Goutte   WIP
68
69
      var url;
      url = this.configuration['api']['data_for_interval'];
b60e7acd   Goutte   Rename "source" i...
70
      url = url.replace('<target>', target_slug);
a4a9ef03   Goutte   Cache generated C...
71
72
      url = url.replace('<started_at>', started_at);
      url = url.replace('<stopped_at>', stopped_at);
f75faf5f   Goutte   WIP
73
74
      return url;
    };
b60e7acd   Goutte   Rename "source" i...
75
76
    SpaceWeather.prototype.addTarget = function(target){
      this.targets[target.slug] = target;
f75faf5f   Goutte   WIP
77
78
      return this;
    };
6bb225d6   Goutte   Link the time ser...
79
    SpaceWeather.prototype.enableAllTargets = function(){
b60e7acd   Goutte   Rename "source" i...
80
81
82
83
      var slug, ref$, target;
      for (slug in ref$ = this.targets) {
        target = ref$[slug];
        showTarget(slug);
f75faf5f   Goutte   WIP
84
85
86
      }
      return this;
    };
6bb225d6   Goutte   Link the time ser...
87
    SpaceWeather.prototype.enableTarget = function(target_slug){
4cf497e0   Goutte   Make the targets ...
88
89
      var this$ = this;
      timeSeries.forEach(function(ts){
b60e7acd   Goutte   Rename "source" i...
90
        if (ts.target.slug === target_slug && this$.parameters[ts.parameter].active) {
6bb225d6   Goutte   Link the time ser...
91
          return ts.show();
4cf497e0   Goutte   Make the targets ...
92
93
        }
      });
b60e7acd   Goutte   Rename "source" i...
94
      this.targets[target_slug].active = true;
f75faf5f   Goutte   WIP
95
96
      return this;
    };
6bb225d6   Goutte   Link the time ser...
97
    SpaceWeather.prototype.disableTarget = function(target_slug){
4cf497e0   Goutte   Make the targets ...
98
      timeSeries.forEach(function(ts){
b60e7acd   Goutte   Rename "source" i...
99
        if (ts.target.slug === target_slug) {
6bb225d6   Goutte   Link the time ser...
100
          return ts.hide();
4cf497e0   Goutte   Make the targets ...
101
102
        }
      });
b60e7acd   Goutte   Rename "source" i...
103
      this.targets[target_slug].active = false;
f75faf5f   Goutte   WIP
104
105
      return this;
    };
fe3132dd   Goutte   Refactor even more.
106
    SpaceWeather.prototype.resize = function(){
a21f81d9   Goutte   Enable Venus and ...
107
      var ref$;
d49a163c   Goutte   Fix the resize an...
108
109
110
111
112
113
      if ((ref$ = this.orbits) != null) {
        ref$.resize();
      }
      return timeSeries.forEach(function(ts){
        return ts.resize();
      });
fe3132dd   Goutte   Refactor even more.
114
    };
b60e7acd   Goutte   Rename "source" i...
115
116
    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.";
f75faf5f   Goutte   WIP
117
118
119
120
      var sw, promise;
      sw = this;
      promise = new Promise(function(resolve, reject){
        var url;
b60e7acd   Goutte   Rename "source" i...
121
        url = sw.buildDataUrlForTarget(target_slug, started_at, stopped_at);
a4a9ef03   Goutte   Cache generated C...
122
        return d3.csv(url, function(csv){
f75faf5f   Goutte   WIP
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
          var timeFormat, data;
          timeFormat = d3.timeParse('%Y-%m-%dT%H:%M:%S%Z');
          data = {
            'hci': []
          };
          configuration['parameters'].forEach(function(parameter){
            return data[parameter['id']] = [];
          });
          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])
              });
            });
            if (d['xhci'] && d['yhci']) {
              return data['hci'].push({
                t: dtime,
                x: parseFloat(d['xhci']),
                y: parseFloat(d['yhci'])
              });
            }
          });
          return resolve(data);
        });
      });
      return promise;
    };
7d6dee0f   Goutte   Continue refacto ...
155
    timeSeries = [];
b60e7acd   Goutte   Rename "source" i...
156
    SpaceWeather.prototype.createTimeSeries = function(target, data){
7d6dee0f   Goutte   Continue refacto ...
157
      var this$ = this;
4816cef4   Goutte   Refactor some more.
158
159
      this.configuration['parameters'].forEach(function(parameter){
        var container, id, title;
b7fe650c   Goutte   Misc bundle of ol...
160
        container = this$.configuration['time_series_container'];
4816cef4   Goutte   Refactor some more.
161
162
163
164
165
        id = parameter['id'];
        title = parameter['title'];
        if (!(id in data)) {
          console.error("No data for id '" + id + "'.", data);
        }
c3008fb2   Goutte   Clean up and refa...
166
        return timeSeries.push(new TimeSeries(id, title, target, data[id], this$.parameters[id].active, container));
4816cef4   Goutte   Refactor some more.
167
168
169
170
171
172
173
174
175
176
177
178
      });
      return timeSeries.forEach(function(ts){
        ts.options['onMouseOver'] = function(){
          return timeSeries.forEach(function(ts2){
            return ts2.showCursor();
          });
        };
        ts.options['onMouseOut'] = function(){
          return timeSeries.forEach(function(ts2){
            return ts2.hideCursor();
          });
        };
c3008fb2   Goutte   Clean up and refa...
179
        ts.options['onMouseMove'] = function(t){
fe3132dd   Goutte   Refactor even more.
180
          var ref$;
4816cef4   Goutte   Refactor some more.
181
182
183
          timeSeries.forEach(function(ts2){
            return ts2.moveCursor(t);
          });
fe3132dd   Goutte   Refactor even more.
184
          return (ref$ = this$.orbits) != null ? ref$.moveToDate(t) : void 8;
4816cef4   Goutte   Refactor some more.
185
        };
c3008fb2   Goutte   Clean up and refa...
186
187
188
189
190
191
        ts.options['onBrushEnd'] = function(sta, sto){
          return this$.resizeDomain(sta, sto);
        };
        return ts.options['onDblClick'] = function(){
          return this$.resetZoom();
        };
4816cef4   Goutte   Refactor some more.
192
193
      });
    };
b7fe650c   Goutte   Misc bundle of ol...
194
    SpaceWeather.prototype.enableParameter = function(parameter_slug){
4cf497e0   Goutte   Make the targets ...
195
      var this$ = this;
b7fe650c   Goutte   Misc bundle of ol...
196
197
198
      if (!(parameter_slug in this.parameters)) {
        console.error("Unknown parameter " + parameter_slug + ".");
      }
b7fe650c   Goutte   Misc bundle of ol...
199
      this.parameters[parameter_slug].active = true;
4cf497e0   Goutte   Make the targets ...
200
      timeSeries.forEach(function(ts){
b60e7acd   Goutte   Rename "source" i...
201
        if (ts.parameter === parameter_slug && this$.targets[ts.target.slug].active) {
6bb225d6   Goutte   Link the time ser...
202
          return ts.show();
4cf497e0   Goutte   Make the targets ...
203
204
        }
      });
b7fe650c   Goutte   Misc bundle of ol...
205
206
207
208
209
210
      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...
211
      this.parameters[parameter_slug].active = false;
4cf497e0   Goutte   Make the targets ...
212
213
      timeSeries.forEach(function(ts){
        if (ts.parameter === parameter_slug) {
6bb225d6   Goutte   Link the time ser...
214
          return ts.hide();
4cf497e0   Goutte   Make the targets ...
215
216
        }
      });
b7fe650c   Goutte   Misc bundle of ol...
217
218
      return this;
    };
8cb213b9   Goutte   Clean up, and pre...
219
220
221
222
223
224
225
226
    SpaceWeather.prototype.resizeDomain = function(started_at, stopped_at){
      var tmp;
      if (stopped_at < started_at) {
        tmp = started_at;
        started_at = stopped_at;
        stopped_at = started_at;
      }
      if (started_at === stopped_at) {
6bb225d6   Goutte   Link the time ser...
227
        console.warn("Please provide distinct start and stop dates.");
8cb213b9   Goutte   Clean up, and pre...
228
229
230
        return;
      }
      if ((this.started_at <= started_at && started_at <= this.stopped_at) && (this.started_at <= stopped_at && stopped_at <= this.stopped_at)) {
c3008fb2   Goutte   Clean up and refa...
231
        console.info("Resizing the temporal domain from " + started_at + " to " + stopped_at + " without fetching new data…");
8cb213b9   Goutte   Clean up, and pre...
232
        timeSeries.forEach(function(ts){
6bb225d6   Goutte   Link the time ser...
233
234
235
236
237
238
239
240
          if (!ts.visible) {
            return ts.zoomIn(started_at, stopped_at);
          }
        });
        timeSeries.forEach(function(ts){
          if (ts.visible) {
            return ts.zoomIn(started_at, stopped_at);
          }
8cb213b9   Goutte   Clean up, and pre...
241
242
243
244
        });
        this.orbits.resizeDomain(started_at, stopped_at);
      }
    };
6bb225d6   Goutte   Link the time ser...
245
246
247
248
249
    SpaceWeather.prototype.resetZoom = function(){
      return timeSeries.forEach(function(ts){
        return ts.resetZoom();
      });
    };
ae0aa7d2   Goutte   Add an x axis lab...
250
251
    return SpaceWeather;
  }());
438929a4   Goutte   Rewrite the orbit...
252
253
  out$.TimeSeries = TimeSeries = (function(){
    TimeSeries.displayName = 'TimeSeries';
123313cb   Goutte   Clip the paths of...
254
    var RATIO, prototype = TimeSeries.prototype, constructor = TimeSeries;
c3008fb2   Goutte   Clean up and refa...
255
    function TimeSeries(parameter, title, target, data, visible, container, options){
4cf497e0   Goutte   Make the targets ...
256
      this.parameter = parameter;
438929a4   Goutte   Rewrite the orbit...
257
      this.title = title;
b60e7acd   Goutte   Rename "source" i...
258
      this.target = target;
6bb225d6   Goutte   Link the time ser...
259
      this.visible = visible;
438929a4   Goutte   Rewrite the orbit...
260
261
262
263
      this.container = container;
      this.options = options != null
        ? options
        : {};
08569a6b   Goutte   Add a zooming bru...
264
      this.onBrushEnd = bind$(this, 'onBrushEnd', prototype);
2038c9fb   Goutte   Add a zoom reset ...
265
      this.onDoubleClick = bind$(this, 'onDoubleClick', prototype);
541e2936   Goutte   Synchronize the t...
266
267
268
      this.onMouseOut = bind$(this, 'onMouseOut', prototype);
      this.onMouseOver = bind$(this, 'onMouseOver', prototype);
      this.onMouseMove = bind$(this, 'onMouseMove', prototype);
6bb225d6   Goutte   Link the time ser...
269
      this.setData(data);
438929a4   Goutte   Rewrite the orbit...
270
271
      this.init();
    }
2038c9fb   Goutte   Add a zoom reset ...
272
273
274
    TimeSeries.prototype.toString = function(){
      return this.title + " of " + this.target.name;
    };
6bb225d6   Goutte   Link the time ser...
275
276
277
278
279
280
281
282
283
    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...
284
    TimeSeries.prototype.init = function(){
123313cb   Goutte   Clip the paths of...
285
      var clipId, dx, this$ = this;
c3008fb2   Goutte   Clean up and refa...
286
      console.info("Initializing plot of " + this + "…");
438929a4   Goutte   Rewrite the orbit...
287
288
289
290
      this.margin = {
        top: 30,
        right: 20,
        bottom: 30,
fe3132dd   Goutte   Refactor even more.
291
        left: 80
438929a4   Goutte   Rewrite the orbit...
292
      };
6bb225d6   Goutte   Link the time ser...
293
294
      this.xScale = d3.scaleTime().domain(this.xDataExtent);
      this.yScale = d3.scaleLinear().domain(this.yDataExtent);
08569a6b   Goutte   Add a zooming bru...
295
      this.xAxis = d3.axisBottom().ticks(7);
438929a4   Goutte   Rewrite the orbit...
296
297
298
299
300
301
302
      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...
303
      this.svg.attr("class", this.parameter + " " + this.target.slug);
438929a4   Goutte   Rewrite the orbit...
304
305
      this.plotWrapper = this.svg.append('g');
      this.plotWrapper.attr('transform', 'translate(' + this.margin.left + ',' + this.margin.top + ')');
123313cb   Goutte   Clip the paths of...
306
307
308
309
310
      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...
311
312
      this.brush = this.plotWrapper.append("g").attr("class", "brush");
      this.mouseCanvas = this.plotWrapper.append("rect").style("fill", "none");
438929a4   Goutte   Rewrite the orbit...
313
314
315
      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...
316
      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...
317
318
      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...
319
320
321
322
323
      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...
324
325
      return this.resize();
    };
123313cb   Goutte   Clip the paths of...
326
    RATIO = GOLDEN_RATIO * GOLDEN_RATIO * GOLDEN_RATIO * GOLDEN_RATIO;
438929a4   Goutte   Rewrite the orbit...
327
328
    TimeSeries.prototype.resize = function(){
      var width, height;
123313cb   Goutte   Clip the paths of...
329
330
      width = Math.ceil($(this.container).width() - this.margin.left - this.margin.right);
      height = Math.ceil(RATIO * width);
541e2936   Goutte   Synchronize the t...
331
332
      this.plotWidth = width;
      this.plotHeight = height;
123313cb   Goutte   Clip the paths of...
333
      console.debug("Resizing " + this + ": " + width + " x " + height + "…");
438929a4   Goutte   Rewrite the orbit...
334
335
336
      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...
337
      this.clip.attr("width", width).attr("height", height);
438929a4   Goutte   Rewrite the orbit...
338
339
340
      this.path.attr('d', this.line);
      this.xAxis.scale(this.xScale);
      this.yAxis.scale(this.yScale);
d49a163c   Goutte   Fix the resize an...
341
342
      this.xAxis.ticks(Math.floor(width / 90.0));
      this.yAxis.ticks(Math.floor(height / 18.0));
438929a4   Goutte   Rewrite the orbit...
343
344
      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.
345
      this.yAxisText.attr("y", 20 - this.margin.left).attr("x", 0 - height / 2);
b60e7acd   Goutte   Rename "source" i...
346
      this.yAxisTextTarget.attr("y", 0 - this.margin.left).attr("x", 0 - height / 2);
2463bd16   Goutte   Add a circle foll...
347
      this.mouseCanvas.attr("width", width).attr("height", height);
08569a6b   Goutte   Add a zooming bru...
348
      if (this.brushFunction == null) {
c3008fb2   Goutte   Clean up and refa...
349
        console.debug("Creating the zooming brush for " + this + "…");
08569a6b   Goutte   Add a zooming bru...
350
351
        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...
352
        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...
353
      }
6bb225d6   Goutte   Link the time ser...
354
355
      if (!this.visible) {
        this.hide();
b7fe650c   Goutte   Misc bundle of ol...
356
      }
2463bd16   Goutte   Add a circle foll...
357
358
      return this;
    };
6bb225d6   Goutte   Link the time ser...
359
360
361
362
363
364
365
366
    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...
367
368
369
370
    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 ...
371
        return this.options.onMouseMove(x);
541e2936   Goutte   Synchronize the t...
372
      } else {
2038c9fb   Goutte   Add a zoom reset ...
373
        return this.moveCursor(x);
541e2936   Goutte   Synchronize the t...
374
      }
541e2936   Goutte   Synchronize the t...
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
    };
    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 ...
390
    TimeSeries.prototype.onDoubleClick = function(){
c3008fb2   Goutte   Clean up and refa...
391
392
393
394
395
      if (this.options.onDblClick != null) {
        return this.options.onDblClick();
      } else {
        return this.resetZoom();
      }
2038c9fb   Goutte   Add a zoom reset ...
396
    };
08569a6b   Goutte   Add a zooming bru...
397
398
399
    TimeSeries.prototype.onBrushEnd = function(){
      var s, minmax;
      s = d3.event.selection;
08569a6b   Goutte   Add a zooming bru...
400
401
      if (s) {
        minmax = [s[0], s[1]].map(this.xScale.invert, this.xScale);
08569a6b   Goutte   Add a zooming bru...
402
        this.brush.call(this.brushFunction.move, null);
c3008fb2   Goutte   Clean up and refa...
403
404
405
406
407
        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 ...
408
409
410
411
412
      }
    };
    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...
413
      ref$ = this.xDataExtent, minDate = ref$[0], maxDate = ref$[1];
2038c9fb   Goutte   Add a zoom reset ...
414
415
416
417
418
      if (startDate < minDate) {
        startDate = minDate;
      }
      if (stopDate > maxDate) {
        stopDate = maxDate;
08569a6b   Goutte   Add a zooming bru...
419
      }
2038c9fb   Goutte   Add a zoom reset ...
420
421
422
423
      this.xScale.domain([startDate, stopDate]);
      return this.applyZoom();
    };
    TimeSeries.prototype.resetZoom = function(){
6bb225d6   Goutte   Link the time ser...
424
425
      this.xScale.domain(this.xDataExtent);
      this.yScale.domain(this.yDataExtent);
2038c9fb   Goutte   Add a zoom reset ...
426
      return this.applyZoom();
08569a6b   Goutte   Add a zooming bru...
427
    };
2038c9fb   Goutte   Add a zoom reset ...
428
    TimeSeries.prototype.applyZoom = function(){
08569a6b   Goutte   Add a zooming bru...
429
      var t;
6bb225d6   Goutte   Link the time ser...
430
      if (this.visible) {
c3008fb2   Goutte   Clean up and refa...
431
        console.debug("Applying zoom to visible " + this + "…");
6bb225d6   Goutte   Link the time ser...
432
433
434
435
436
        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...
437
        console.debug("Applying zoom to hidden " + this + "…");
6bb225d6   Goutte   Link the time ser...
438
439
440
441
        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...
442
    };
541e2936   Goutte   Synchronize the t...
443
444
445
446
447
448
    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...
449
450
451
    TimeSeries.prototype.bisectDate = d3.bisector(function(d){
      return d.x;
    }).left;
81c9b2e8   Goutte   Add the values to...
452
    TimeSeries.prototype.timeFormat = d3.timeFormat("%Y-%m-%d %Hh");
541e2936   Goutte   Synchronize the t...
453
    TimeSeries.prototype.moveCursor = function(x0){
8cb213b9   Goutte   Clean up, and pre...
454
      var i, d0, d1, d, xx, yy, mirrored, dx, transform;
2463bd16   Goutte   Add a circle foll...
455
456
457
      i = this.bisectDate(this.data, x0, 1);
      d0 = this.data[i - 1];
      d1 = this.data[i];
541e2936   Goutte   Synchronize the t...
458
459
460
      if (!(d1 && d0)) {
        return;
      }
2463bd16   Goutte   Add a circle foll...
461
462
463
      d = x0 - d0.x > d1.x - x0 ? d1 : d0;
      xx = this.xScale(d.x);
      yy = this.yScale(d.y);
541e2936   Goutte   Synchronize the t...
464
465
466
467
468
      mirrored = this.plotWidth != null && xx > this.plotWidth / 2 ? true : false;
      dx = 8;
      if (mirrored) {
        dx = -1 * dx;
      }
8cb213b9   Goutte   Clean up, and pre...
469
      transform = "translate(" + xx + ", " + yy + ")";
81c9b2e8   Goutte   Add the values to...
470
      this.cursorCircle.attr("transform", transform);
541e2936   Goutte   Synchronize the t...
471
472
473
474
      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...
475
476
477
478
479
      return this;
    };
    return TimeSeries;
  }());
  out$.Orbits = Orbits = (function(){
8cb213b9   Goutte   Clean up, and pre...
480
    "View of the solar system from above, with orbits segments for selected time\ninterval, from real data.";
438929a4   Goutte   Rewrite the orbit...
481
482
    Orbits.displayName = 'Orbits';
    var prototype = Orbits.prototype, constructor = Orbits;
a21f81d9   Goutte   Enable Venus and ...
483
    function Orbits(container, options){
438929a4   Goutte   Rewrite the orbit...
484
485
486
487
      this.container = container;
      this.options = options != null
        ? options
        : {};
438929a4   Goutte   Rewrite the orbit...
488
489
490
      this.init();
    }
    Orbits.prototype.init = function(){
c3008fb2   Goutte   Clean up and refa...
491
      console.log("Initializing plot of orbits…");
438929a4   Goutte   Rewrite the orbit...
492
493
494
      this.margin = {
        top: 30,
        right: 20,
11662eed   Goutte   Add Y axis label ...
495
        bottom: 42,
438929a4   Goutte   Rewrite the orbit...
496
497
        left: 60
      };
a21f81d9   Goutte   Enable Venus and ...
498
499
500
      this.data = {};
      this.orbiters = {};
      this.extremum = 1;
438929a4   Goutte   Rewrite the orbit...
501
502
503
504
505
506
507
      this.xScale = d3.scaleLinear().domain([-1 * this.extremum, this.extremum]);
      this.yScale = d3.scaleLinear().domain([-1 * this.extremum, this.extremum]);
      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...
508
509
510
511
512
      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");
      this.xAxisTitle.append('tspan').text('X');
11662eed   Goutte   Add Y axis label ...
513
      this.xAxisTitle.append('tspan').attr('dy', '3px').text('HEE').attr('font-size', '8px');
ae0aa7d2   Goutte   Add an x axis lab...
514
      this.xAxisTitle.append('tspan').attr('dy', '-3px').text('   (AU)');
11662eed   Goutte   Add Y axis label ...
515
516
517
518
519
520
      this.yAxisTitle = this.yAxisLine.append('text').attr('fill', '#000');
      this.yAxisTitle.style("text-anchor", "middle");
      this.yAxisTitle.append('tspan').text('Y');
      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...
521
      this.sun = this.plotWrapper.append("svg:image").attr('xlink:href', this.options.sun.img).attr('width', '32px').attr('height', '32px');
438929a4   Goutte   Rewrite the orbit...
522
      this.sun.append('svg:title').text("Sol");
3ee0b596   Goutte   Fix an annoying b...
523
      $(this.svg.node()).hide();
438929a4   Goutte   Rewrite the orbit...
524
525
526
      return this.resize();
    };
    Orbits.prototype.orbitersElements = {};
a21f81d9   Goutte   Enable Venus and ...
527
    Orbits.prototype.initOrbiter = function(slug, config, data){
438929a4   Goutte   Rewrite the orbit...
528
      var orbit_ellipse, orbiter, orbit_line, orbit_section, this$ = this;
c3008fb2   Goutte   Clean up and refa...
529
      console.log("Initializing target " + slug + "'s orbit…", config, data);
438929a4   Goutte   Rewrite the orbit...
530
531
532
      if (slug in this.orbitersElements) {
        throw new Error("Second init of " + slug);
      }
a21f81d9   Goutte   Enable Venus and ...
533
534
535
536
537
      this.extremum = Math.max(this.extremum, 1.11 * d3.max(data, function(d){
        return Math.max(Math.abs(d.x), Math.abs(d.y));
      }));
      this.xScale = d3.scaleLinear().domain([-1 * this.extremum, this.extremum]);
      this.yScale = d3.scaleLinear().domain([-1 * this.extremum, this.extremum]);
438929a4   Goutte   Rewrite the orbit...
538
539
540
541
542
543
544
      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');
      orbit_line = d3.line().x(function(d){
        return this$.xScale(d.x);
      }).y(function(d){
        return this$.yScale(d.y);
      });
a21f81d9   Goutte   Enable Venus and ...
545
546
547
      orbit_section = this.plotWrapper.append('path').datum(data).classed('orbit orbit_section', true);
      this.orbiters[slug] = config;
      this.data[slug] = data;
438929a4   Goutte   Rewrite the orbit...
548
549
550
551
552
553
      this.orbitersElements[slug] = {
        orbiter: orbiter,
        orbit_ellipse: orbit_ellipse,
        orbit_section: orbit_section,
        orbit_line: orbit_line
      };
a21f81d9   Goutte   Enable Venus and ...
554
      this.resize();
3ee0b596   Goutte   Fix an annoying b...
555
      $(this.svg.node()).show();
438929a4   Goutte   Rewrite the orbit...
556
557
558
559
560
561
      return this;
    };
    Orbits.prototype.resize = function(){
      var width, height, slug, ref$, config;
      width = jQuery(this.container).width() - this.margin.left - this.margin.right;
      height = 1.0 * width;
438929a4   Goutte   Rewrite the orbit...
562
563
564
      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);
8bd715ad   Goutte   Use a pixel art i...
565
      this.sun.attr("x", width / 2 - 16).attr("y", height / 2 - 16);
438929a4   Goutte   Rewrite the orbit...
566
567
568
569
570
571
572
573
      for (slug in ref$ = this.orbiters) {
        config = ref$[slug];
        this.resizeOrbiter(slug, config);
      }
      this.xAxis.scale(this.xScale);
      this.yAxis.scale(this.yScale);
      this.svg.select('.x.axis').attr('transform', 'translate(0,' + height + ')').call(this.xAxis);
      this.svg.select('.y.axis').call(this.yAxis);
11662eed   Goutte   Add Y axis label ...
574
575
      this.xAxisTitle.attr("x", width / 2).attr("y", 37);
      this.yAxisTitle.attr("x", -1 * height / 2).attr("y", -30);
438929a4   Goutte   Rewrite the orbit...
576
577
578
579
      return this;
    };
    Orbits.prototype.resizeOrbiter = function(slug, config){
      var width, height, el, a, b, c, cx, cy, data;
c3008fb2   Goutte   Clean up and refa...
580
581
582
      width = Math.floor(jQuery(this.container).width() - this.margin.left - this.margin.right);
      height = Math.floor(1.0 * width);
      console.debug("Resizing orbiter of " + slug + " to " + width + " × " + height + "…");
438929a4   Goutte   Rewrite the orbit...
583
584
585
586
587
588
589
590
      el = this.orbitersElements[slug];
      el['orbit_section'].attr('d', el['orbit_line']);
      a = config['orbit']['a'];
      b = config['orbit']['b'];
      c = Math.sqrt(a * a - b * b);
      cx = width / 2 - c;
      cy = height / 2;
      this.yScale.range([0, height]);
a21f81d9   Goutte   Enable Venus and ...
591
      el['orbit_ellipse'].attr('cx', cx).attr('cy', cy).attr('rx', this.xScale(a) - this.xScale(0)).attr('ry', this.yScale(b) - this.yScale(0));
438929a4   Goutte   Rewrite the orbit...
592
      this.yScale.range([height, 0]);
a21f81d9   Goutte   Enable Venus and ...
593
      data = this.data[slug];
438929a4   Goutte   Rewrite the orbit...
594
595
596
597
      el['orbiter'].attr('x', this.xScale(data[data.length - 1].x) - 16);
      el['orbiter'].attr('y', this.yScale(data[data.length - 1].y) - 16);
      return this;
    };
ae0aa7d2   Goutte   Add an x axis lab...
598
599
    Orbits.prototype.repositionOrbiter = function(slug, datum){
      var data, el;
a21f81d9   Goutte   Enable Venus and ...
600
      data = this.data[slug];
ae0aa7d2   Goutte   Add an x axis lab...
601
602
603
604
605
606
607
608
609
610
      datum == null && (datum = data[data.length - 1]);
      el = this.orbitersElements[slug];
      el['orbiter'].attr('x', this.xScale(datum.x) - 16);
      el['orbiter'].attr('y', this.yScale(datum.y) - 16);
      return this;
    };
    Orbits.prototype.bisectDate = d3.bisector(function(d){
      return d.t;
    }).left;
    Orbits.prototype.moveToDate = function(t){
a21f81d9   Goutte   Enable Venus and ...
611
612
613
614
      var slug, ref$, el, data, i, d0, d1, d;
      if (!t) {
        console.log("Trying to move to an undefined date");
      }
ae0aa7d2   Goutte   Add an x axis lab...
615
616
      for (slug in ref$ = this.orbitersElements) {
        el = ref$[slug];
a21f81d9   Goutte   Enable Venus and ...
617
        data = this.data[slug];
ae0aa7d2   Goutte   Add an x axis lab...
618
619
620
621
622
623
624
        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 ...
625
        this.repositionOrbiter(slug, d);
ae0aa7d2   Goutte   Add an x axis lab...
626
      }
a21f81d9   Goutte   Enable Venus and ...
627
      return this;
ae0aa7d2   Goutte   Add an x axis lab...
628
    };
8cb213b9   Goutte   Clean up, and pre...
629
    Orbits.prototype.resizeDomain = function(started_at, stopped_at){};
438929a4   Goutte   Rewrite the orbit...
630
631
    return Orbits;
  }());
2463bd16   Goutte   Add a circle foll...
632
633
634
  function bind$(obj, key, target){
    return function(){ return (target || obj)[key].apply(obj, arguments) };
  }
438929a4   Goutte   Rewrite the orbit...
635
}).call(this);