~jstys-z/helioviewer.org/timeline

« back to all changes in this revision

Viewing changes to timeline/js/adapters/standalone-framework.src.js

  • Committer: Jeff Stys
  • Date: 2014-04-21 12:46:26 UTC
  • Revision ID: jstys@sesda3.com-20140421124626-2332pb2dyjc33jxi
Proof-of-concept version of Data Coverage Timeline using Highchart/Highstock javascript library.  Changes to getDataCoverage API in order to feed the necessary data to the Timeline

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * @license Highstock JS v1.3.10 (2014-03-10)
 
3
 *
 
4
 * Standalone Highcharts Framework
 
5
 *
 
6
 * License: MIT License
 
7
 */
 
8
 
 
9
 
 
10
/*global Highcharts */
 
11
var HighchartsAdapter = (function () {
 
12
 
 
13
var UNDEFINED,
 
14
        doc = document,
 
15
        emptyArray = [],
 
16
        timers = [],
 
17
        timerId,
 
18
        Fx;
 
19
 
 
20
Math.easeInOutSine = function (t, b, c, d) {
 
21
        return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;
 
22
};
 
23
 
 
24
 
 
25
 
 
26
/**
 
27
 * Extend given object with custom events
 
28
 */
 
29
function augment(obj) {
 
30
        function removeOneEvent(el, type, fn) {
 
31
                el.removeEventListener(type, fn, false);
 
32
        }
 
33
 
 
34
        function IERemoveOneEvent(el, type, fn) {
 
35
                fn = el.HCProxiedMethods[fn.toString()];
 
36
                el.detachEvent('on' + type, fn);
 
37
        }
 
38
 
 
39
        function removeAllEvents(el, type) {
 
40
                var events = el.HCEvents,
 
41
                        remove,
 
42
                        types,
 
43
                        len,
 
44
                        n;
 
45
 
 
46
                if (el.removeEventListener) {
 
47
                        remove = removeOneEvent;
 
48
                } else if (el.attachEvent) {
 
49
                        remove = IERemoveOneEvent;
 
50
                } else {
 
51
                        return; // break on non-DOM events
 
52
                }
 
53
 
 
54
 
 
55
                if (type) {
 
56
                        types = {};
 
57
                        types[type] = true;
 
58
                } else {
 
59
                        types = events;
 
60
                }
 
61
 
 
62
                for (n in types) {
 
63
                        if (events[n]) {
 
64
                                len = events[n].length;
 
65
                                while (len--) {
 
66
                                        remove(el, n, events[n][len]);
 
67
                                }
 
68
                        }
 
69
                }
 
70
        }
 
71
 
 
72
        if (!obj.HCExtended) {
 
73
                Highcharts.extend(obj, {
 
74
                        HCExtended: true,
 
75
 
 
76
                        HCEvents: {},
 
77
 
 
78
                        bind: function (name, fn) {
 
79
                                var el = this,
 
80
                                        events = this.HCEvents,
 
81
                                        wrappedFn;
 
82
 
 
83
                                // handle DOM events in modern browsers
 
84
                                if (el.addEventListener) {
 
85
                                        el.addEventListener(name, fn, false);
 
86
 
 
87
                                // handle old IE implementation
 
88
                                } else if (el.attachEvent) {
 
89
                                        
 
90
                                        wrappedFn = function (e) {
 
91
                                                fn.call(el, e);
 
92
                                        };
 
93
 
 
94
                                        if (!el.HCProxiedMethods) {
 
95
                                                el.HCProxiedMethods = {};
 
96
                                        }
 
97
 
 
98
                                        // link wrapped fn with original fn, so we can get this in removeEvent
 
99
                                        el.HCProxiedMethods[fn.toString()] = wrappedFn;
 
100
 
 
101
                                        el.attachEvent('on' + name, wrappedFn);
 
102
                                }
 
103
 
 
104
 
 
105
                                if (events[name] === UNDEFINED) {
 
106
                                        events[name] = [];
 
107
                                }
 
108
 
 
109
                                events[name].push(fn);
 
110
                        },
 
111
 
 
112
                        unbind: function (name, fn) {
 
113
                                var events,
 
114
                                        index;
 
115
 
 
116
                                if (name) {
 
117
                                        events = this.HCEvents[name] || [];
 
118
                                        if (fn) {
 
119
                                                index = HighchartsAdapter.inArray(fn, events);
 
120
                                                if (index > -1) {
 
121
                                                        events.splice(index, 1);
 
122
                                                        this.HCEvents[name] = events;
 
123
                                                }
 
124
                                                if (this.removeEventListener) {
 
125
                                                        removeOneEvent(this, name, fn);
 
126
                                                } else if (this.attachEvent) {
 
127
                                                        IERemoveOneEvent(this, name, fn);
 
128
                                                }
 
129
                                        } else {
 
130
                                                removeAllEvents(this, name);
 
131
                                                this.HCEvents[name] = [];
 
132
                                        }
 
133
                                } else {
 
134
                                        removeAllEvents(this);
 
135
                                        this.HCEvents = {};
 
136
                                }
 
137
                        },
 
138
 
 
139
                        trigger: function (name, args) {
 
140
                                var events = this.HCEvents[name] || [],
 
141
                                        target = this,
 
142
                                        len = events.length,
 
143
                                        i,
 
144
                                        preventDefault,
 
145
                                        fn;
 
146
 
 
147
                                // Attach a simple preventDefault function to skip default handler if called
 
148
                                preventDefault = function () {
 
149
                                        args.defaultPrevented = true;
 
150
                                };
 
151
                                
 
152
                                for (i = 0; i < len; i++) {
 
153
                                        fn = events[i];
 
154
 
 
155
                                        // args is never null here
 
156
                                        if (args.stopped) {
 
157
                                                return;
 
158
                                        }
 
159
 
 
160
                                        args.preventDefault = preventDefault;
 
161
                                        args.target = target;
 
162
 
 
163
                                        // If the type is not set, we're running a custom event (#2297). If it is set,
 
164
                                        // we're running a browser event, and setting it will cause en error in
 
165
                                        // IE8 (#2465).
 
166
                                        if (!args.type) {
 
167
                                                args.type = name;
 
168
                                        }
 
169
                                        
 
170
 
 
171
                                        
 
172
                                        // If the event handler return false, prevent the default handler from executing
 
173
                                        if (fn.call(this, args) === false) {
 
174
                                                args.preventDefault();
 
175
                                        }
 
176
                                }
 
177
                        }
 
178
                });
 
179
        }
 
180
 
 
181
        return obj;
 
182
}
 
183
 
 
184
 
 
185
return {
 
186
        /**
 
187
         * Initialize the adapter. This is run once as Highcharts is first run.
 
188
         */
 
189
        init: function (pathAnim) {
 
190
 
 
191
                /**
 
192
                 * Compatibility section to add support for legacy IE. This can be removed if old IE 
 
193
                 * support is not needed.
 
194
                 */
 
195
                if (!doc.defaultView) {
 
196
                        this._getStyle = function (el, prop) {
 
197
                                var val;
 
198
                                if (el.style[prop]) {
 
199
                                        return el.style[prop];
 
200
                                } else {
 
201
                                        if (prop === 'opacity') {
 
202
                                                prop = 'filter';
 
203
                                        }
 
204
                                        /*jslint unparam: true*/
 
205
                                        val = el.currentStyle[prop.replace(/\-(\w)/g, function (a, b) { return b.toUpperCase(); })];
 
206
                                        if (prop === 'filter') {
 
207
                                                val = val.replace(
 
208
                                                        /alpha\(opacity=([0-9]+)\)/, 
 
209
                                                        function (a, b) { 
 
210
                                                                return b / 100; 
 
211
                                                        }
 
212
                                                );
 
213
                                        }
 
214
                                        /*jslint unparam: false*/
 
215
                                        return val === '' ? 1 : val;
 
216
                                } 
 
217
                        };
 
218
                        this.adapterRun = function (elem, method) {
 
219
                                var alias = { width: 'clientWidth', height: 'clientHeight' }[method];
 
220
 
 
221
                                if (alias) {
 
222
                                        elem.style.zoom = 1;
 
223
                                        return elem[alias] - 2 * parseInt(HighchartsAdapter._getStyle(elem, 'padding'), 10);
 
224
                                }
 
225
                        };
 
226
                }
 
227
 
 
228
                if (!Array.prototype.forEach) {
 
229
                        this.each = function (arr, fn) { // legacy
 
230
                                var i = 0, 
 
231
                                        len = arr.length;
 
232
                                for (; i < len; i++) {
 
233
                                        if (fn.call(arr[i], arr[i], i, arr) === false) {
 
234
                                                return i;
 
235
                                        }
 
236
                                }
 
237
                        };
 
238
                }
 
239
 
 
240
                if (!Array.prototype.indexOf) {
 
241
                        this.inArray = function (item, arr) {
 
242
                                var len, 
 
243
                                        i = 0;
 
244
 
 
245
                                if (arr) {
 
246
                                        len = arr.length;
 
247
                                        
 
248
                                        for (; i < len; i++) {
 
249
                                                if (arr[i] === item) {
 
250
                                                        return i;
 
251
                                                }
 
252
                                        }
 
253
                                }
 
254
 
 
255
                                return -1;
 
256
                        };
 
257
                }
 
258
 
 
259
                if (!Array.prototype.filter) {
 
260
                        this.grep = function (elements, callback) {
 
261
                                var ret = [],
 
262
                                        i = 0,
 
263
                                        length = elements.length;
 
264
 
 
265
                                for (; i < length; i++) {
 
266
                                        if (!!callback(elements[i], i)) {
 
267
                                                ret.push(elements[i]);
 
268
                                        }
 
269
                                }
 
270
 
 
271
                                return ret;
 
272
                        };
 
273
                }
 
274
 
 
275
                //--- End compatibility section ---
 
276
 
 
277
 
 
278
                /**
 
279
                 * Start of animation specific code
 
280
                 */
 
281
                Fx = function (elem, options, prop) {
 
282
                        this.options = options;
 
283
                        this.elem = elem;
 
284
                        this.prop = prop;
 
285
                };
 
286
                Fx.prototype = {
 
287
                        
 
288
                        update: function () {
 
289
                                var styles,
 
290
                                        paths = this.paths,
 
291
                                        elem = this.elem,
 
292
                                        elemelem = elem.element; // if destroyed, it is null
 
293
 
 
294
                                // Animating a path definition on SVGElement
 
295
                                if (paths && elemelem) {
 
296
                                        elem.attr('d', pathAnim.step(paths[0], paths[1], this.now, this.toD));
 
297
                                
 
298
                                // Other animations on SVGElement
 
299
                                } else if (elem.attr) {
 
300
                                        if (elemelem) {
 
301
                                                elem.attr(this.prop, this.now);
 
302
                                        }
 
303
 
 
304
                                // HTML styles
 
305
                                } else {
 
306
                                        styles = {};
 
307
                                        styles[this.prop] = this.now + this.unit;
 
308
                                        Highcharts.css(elem, styles);
 
309
                                }
 
310
                                
 
311
                                if (this.options.step) {
 
312
                                        this.options.step.call(this.elem, this.now, this);
 
313
                                }
 
314
 
 
315
                        },
 
316
                        custom: function (from, to, unit) {
 
317
                                var self = this,
 
318
                                        t = function (gotoEnd) {
 
319
                                                return self.step(gotoEnd);
 
320
                                        },
 
321
                                        i;
 
322
 
 
323
                                this.startTime = +new Date();
 
324
                                this.start = from;
 
325
                                this.end = to;
 
326
                                this.unit = unit;
 
327
                                this.now = this.start;
 
328
                                this.pos = this.state = 0;
 
329
 
 
330
                                t.elem = this.elem;
 
331
 
 
332
                                if (t() && timers.push(t) === 1) {
 
333
                                        timerId = setInterval(function () {
 
334
                                                
 
335
                                                for (i = 0; i < timers.length; i++) {
 
336
                                                        if (!timers[i]()) {
 
337
                                                                timers.splice(i--, 1);
 
338
                                                        }
 
339
                                                }
 
340
 
 
341
                                                if (!timers.length) {
 
342
                                                        clearInterval(timerId);
 
343
                                                }
 
344
                                        }, 13);
 
345
                                }
 
346
                        },
 
347
                        
 
348
                        step: function (gotoEnd) {
 
349
                                var t = +new Date(),
 
350
                                        ret,
 
351
                                        done,
 
352
                                        options = this.options,
 
353
                                        elem = this.elem,
 
354
                                        i;
 
355
                                
 
356
                                if (elem.stopAnimation || (elem.attr && !elem.element)) { // #2616, element including flag is destroyed
 
357
                                        ret = false;
 
358
 
 
359
                                } else if (gotoEnd || t >= options.duration + this.startTime) {
 
360
                                        this.now = this.end;
 
361
                                        this.pos = this.state = 1;
 
362
                                        this.update();
 
363
 
 
364
                                        this.options.curAnim[this.prop] = true;
 
365
 
 
366
                                        done = true;
 
367
                                        for (i in options.curAnim) {
 
368
                                                if (options.curAnim[i] !== true) {
 
369
                                                        done = false;
 
370
                                                }
 
371
                                        }
 
372
 
 
373
                                        if (done) {
 
374
                                                if (options.complete) {
 
375
                                                        options.complete.call(elem);
 
376
                                                }
 
377
                                        }
 
378
                                        ret = false;
 
379
 
 
380
                                } else {
 
381
                                        var n = t - this.startTime;
 
382
                                        this.state = n / options.duration;
 
383
                                        this.pos = options.easing(n, 0, 1, options.duration);
 
384
                                        this.now = this.start + ((this.end - this.start) * this.pos);
 
385
                                        this.update();
 
386
                                        ret = true;
 
387
                                }
 
388
                                return ret;
 
389
                        }
 
390
                };
 
391
 
 
392
                /**
 
393
                 * The adapter animate method
 
394
                 */
 
395
                this.animate = function (el, prop, opt) {
 
396
                        var start,
 
397
                                unit = '',
 
398
                                end,
 
399
                                fx,
 
400
                                args,
 
401
                                name;
 
402
 
 
403
                        el.stopAnimation = false; // ready for new
 
404
 
 
405
                        if (typeof opt !== 'object' || opt === null) {
 
406
                                args = arguments;
 
407
                                opt = {
 
408
                                        duration: args[2],
 
409
                                        easing: args[3],
 
410
                                        complete: args[4]
 
411
                                };
 
412
                        }
 
413
                        if (typeof opt.duration !== 'number') {
 
414
                                opt.duration = 400;
 
415
                        }
 
416
                        opt.easing = Math[opt.easing] || Math.easeInOutSine;
 
417
                        opt.curAnim = Highcharts.extend({}, prop);
 
418
                        
 
419
                        for (name in prop) {
 
420
                                fx = new Fx(el, opt, name);
 
421
                                end = null;
 
422
                                
 
423
                                if (name === 'd') {
 
424
                                        fx.paths = pathAnim.init(
 
425
                                                el,
 
426
                                                el.d,
 
427
                                                prop.d
 
428
                                        );
 
429
                                        fx.toD = prop.d;
 
430
                                        start = 0;
 
431
                                        end = 1;
 
432
                                } else if (el.attr) {
 
433
                                        start = el.attr(name);
 
434
                                } else {
 
435
                                        start = parseFloat(HighchartsAdapter._getStyle(el, name)) || 0;
 
436
                                        if (name !== 'opacity') {
 
437
                                                unit = 'px';
 
438
                                        }
 
439
                                }
 
440
        
 
441
                                if (!end) {
 
442
                                        end = parseFloat(prop[name]);
 
443
                                }
 
444
                                fx.custom(start, end, unit);
 
445
                        }       
 
446
                };
 
447
        },
 
448
 
 
449
        /**
 
450
         * Internal method to return CSS value for given element and property
 
451
         */
 
452
        _getStyle: function (el, prop) {
 
453
                return window.getComputedStyle(el).getPropertyValue(prop);
 
454
        },
 
455
 
 
456
        /**
 
457
         * Downloads a script and executes a callback when done.
 
458
         * @param {String} scriptLocation
 
459
         * @param {Function} callback
 
460
         */
 
461
        getScript: function (scriptLocation, callback) {
 
462
                // We cannot assume that Assets class from mootools-more is available so instead insert a script tag to download script.
 
463
                var head = doc.getElementsByTagName('head')[0],
 
464
                        script = doc.createElement('script');
 
465
 
 
466
                script.type = 'text/javascript';
 
467
                script.src = scriptLocation;
 
468
                script.onload = callback;
 
469
 
 
470
                head.appendChild(script);
 
471
        },
 
472
 
 
473
        /**
 
474
         * Return the index of an item in an array, or -1 if not found
 
475
         */
 
476
        inArray: function (item, arr) {
 
477
                return arr.indexOf ? arr.indexOf(item) : emptyArray.indexOf.call(arr, item);
 
478
        },
 
479
 
 
480
 
 
481
        /**
 
482
         * A direct link to adapter methods
 
483
         */
 
484
        adapterRun: function (elem, method) {
 
485
                return parseInt(HighchartsAdapter._getStyle(elem, method), 10);
 
486
        },
 
487
 
 
488
        /**
 
489
         * Filter an array
 
490
         */
 
491
        grep: function (elements, callback) {
 
492
                return emptyArray.filter.call(elements, callback);
 
493
        },
 
494
 
 
495
        /**
 
496
         * Map an array
 
497
         */
 
498
        map: function (arr, fn) {
 
499
                var results = [], i = 0, len = arr.length;
 
500
 
 
501
                for (; i < len; i++) {
 
502
                        results[i] = fn.call(arr[i], arr[i], i, arr);
 
503
                }
 
504
 
 
505
                return results;
 
506
        },
 
507
 
 
508
        /**
 
509
         * Get the element's offset position, corrected by overflow:auto. Loosely based on jQuery's offset method.
 
510
         */
 
511
        offset: function (el) {
 
512
                var docElem = document.documentElement,
 
513
                        box = el.getBoundingClientRect();
 
514
 
 
515
                return {
 
516
                        top: box.top  + (window.pageYOffset || docElem.scrollTop)  - (docElem.clientTop  || 0),
 
517
                        left: box.left + (window.pageXOffset || docElem.scrollLeft) - (docElem.clientLeft || 0)
 
518
                };
 
519
        },
 
520
 
 
521
        /**
 
522
         * Add an event listener
 
523
         */
 
524
        addEvent: function (el, type, fn) {
 
525
                augment(el).bind(type, fn);
 
526
        },
 
527
 
 
528
        /**
 
529
         * Remove event added with addEvent
 
530
         */
 
531
        removeEvent: function (el, type, fn) {
 
532
                augment(el).unbind(type, fn);
 
533
        },
 
534
 
 
535
        /**
 
536
         * Fire an event on a custom object
 
537
         */
 
538
        fireEvent: function (el, type, eventArguments, defaultFunction) {
 
539
                var e;
 
540
 
 
541
                if (doc.createEvent && (el.dispatchEvent || el.fireEvent)) {
 
542
                        e = doc.createEvent('Events');
 
543
                        e.initEvent(type, true, true);
 
544
                        e.target = el;
 
545
 
 
546
                        Highcharts.extend(e, eventArguments);
 
547
 
 
548
                        if (el.dispatchEvent) {
 
549
                                el.dispatchEvent(e);
 
550
                        } else {
 
551
                                el.fireEvent(type, e);
 
552
                        }
 
553
 
 
554
                } else if (el.HCExtended === true) {
 
555
                        eventArguments = eventArguments || {};
 
556
                        el.trigger(type, eventArguments);
 
557
                }
 
558
 
 
559
                if (eventArguments && eventArguments.defaultPrevented) {
 
560
                        defaultFunction = null;
 
561
                }
 
562
 
 
563
                if (defaultFunction) {
 
564
                        defaultFunction(eventArguments);
 
565
                }
 
566
        },
 
567
 
 
568
        washMouseEvent: function (e) {
 
569
                return e;
 
570
        },
 
571
 
 
572
 
 
573
        /**
 
574
         * Stop running animation
 
575
         */
 
576
        stop: function (el) {
 
577
                el.stopAnimation = true;
 
578
        },
 
579
 
 
580
        /**
 
581
         * Utility for iterating over an array. Parameters are reversed compared to jQuery.
 
582
         * @param {Array} arr
 
583
         * @param {Function} fn
 
584
         */
 
585
        each: function (arr, fn) { // modern browsers
 
586
                return Array.prototype.forEach.call(arr, fn);
 
587
        }
 
588
};
 
589
}());