~jstys-z/helioviewer.org/timeline

« back to all changes in this revision

Viewing changes to timeline/js/adapters/prototype-adapter.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
 * Prototype adapter
 
4
 *
 
5
 * @author Michael Nelson, Torstein Honsi.
 
6
 *
 
7
 * Feel free to use and modify this script.
 
8
 * Highcharts license: www.highcharts.com/license.
 
9
 */
 
10
 
 
11
// JSLint options:
 
12
/*global Effect, Class, Event, Element, $, $$, $A */
 
13
 
 
14
// Adapter interface between prototype and the Highcharts charting library
 
15
var HighchartsAdapter = (function () {
 
16
 
 
17
var hasEffect = typeof Effect !== 'undefined';
 
18
 
 
19
return {
 
20
 
 
21
        /**
 
22
         * Initialize the adapter. This is run once as Highcharts is first run.
 
23
         * @param {Object} pathAnim The helper object to do animations across adapters.
 
24
         */
 
25
        init: function (pathAnim) {
 
26
                if (hasEffect) {
 
27
                        /**
 
28
                         * Animation for Highcharts SVG element wrappers only
 
29
                         * @param {Object} element
 
30
                         * @param {Object} attribute
 
31
                         * @param {Object} to
 
32
                         * @param {Object} options
 
33
                         */
 
34
                        Effect.HighchartsTransition = Class.create(Effect.Base, {
 
35
                                initialize: function (element, attr, to, options) {
 
36
                                        var from,
 
37
                                                opts;
 
38
 
 
39
                                        this.element = element;
 
40
                                        this.key = attr;
 
41
                                        from = element.attr ? element.attr(attr) : $(element).getStyle(attr);
 
42
 
 
43
                                        // special treatment for paths
 
44
                                        if (attr === 'd') {
 
45
                                                this.paths = pathAnim.init(
 
46
                                                        element,
 
47
                                                        element.d,
 
48
                                                        to
 
49
                                                );
 
50
                                                this.toD = to;
 
51
 
 
52
 
 
53
                                                // fake values in order to read relative position as a float in update
 
54
                                                from = 0;
 
55
                                                to = 1;
 
56
                                        }
 
57
 
 
58
                                        opts = Object.extend((options || {}), {
 
59
                                                from: from,
 
60
                                                to: to,
 
61
                                                attribute: attr
 
62
                                        });
 
63
                                        this.start(opts);
 
64
                                },
 
65
                                setup: function () {
 
66
                                        HighchartsAdapter._extend(this.element);
 
67
                                        // If this is the first animation on this object, create the _highcharts_animation helper that
 
68
                                        // contain pointers to the animation objects.
 
69
                                        if (!this.element._highchart_animation) {
 
70
                                                this.element._highchart_animation = {};
 
71
                                        }
 
72
 
 
73
                                        // Store a reference to this animation instance.
 
74
                                        this.element._highchart_animation[this.key] = this;
 
75
                                },
 
76
                                update: function (position) {
 
77
                                        var paths = this.paths,
 
78
                                                element = this.element,
 
79
                                                obj;
 
80
 
 
81
                                        if (paths) {
 
82
                                                position = pathAnim.step(paths[0], paths[1], position, this.toD);
 
83
                                        }
 
84
 
 
85
                                        if (element.attr) { // SVGElement
 
86
                                                
 
87
                                                if (element.element) { // If not, it has been destroyed (#1405)
 
88
                                                        element.attr(this.options.attribute, position);
 
89
                                                }
 
90
                                        
 
91
                                        } else { // HTML, #409
 
92
                                                obj = {};
 
93
                                                obj[this.options.attribute] = position;
 
94
                                                $(element).setStyle(obj);
 
95
                                        }
 
96
                                        
 
97
                                },
 
98
                                finish: function () {
 
99
                                        // Delete the property that holds this animation now that it is finished.
 
100
                                        // Both canceled animations and complete ones gets a 'finish' call.
 
101
                                        if (this.element && this.element._highchart_animation) { // #1405
 
102
                                                delete this.element._highchart_animation[this.key];
 
103
                                        }
 
104
                                }
 
105
                        });
 
106
                }
 
107
        },
 
108
        
 
109
        /**
 
110
         * Run a general method on the framework, following jQuery syntax
 
111
         * @param {Object} el The HTML element
 
112
         * @param {String} method Which method to run on the wrapped element
 
113
         */
 
114
        adapterRun: function (el, method) {
 
115
                
 
116
                // This currently works for getting inner width and height. If adding
 
117
                // more methods later, we need a conditional implementation for each.
 
118
                return parseInt($(el).getStyle(method), 10);
 
119
                
 
120
        },
 
121
 
 
122
        /**
 
123
         * Downloads a script and executes a callback when done.
 
124
         * @param {String} scriptLocation
 
125
         * @param {Function} callback
 
126
         */
 
127
        getScript: function (scriptLocation, callback) {
 
128
                var head = $$('head')[0]; // Returns an array, so pick the first element.
 
129
                if (head) {
 
130
                        // Append a new 'script' element, set its type and src attributes, add a 'load' handler that calls the callback
 
131
                        head.appendChild(new Element('script', { type: 'text/javascript', src: scriptLocation}).observe('load', callback));
 
132
                }
 
133
        },
 
134
 
 
135
        /**
 
136
         * Custom events in prototype needs to be namespaced. This method adds a namespace 'h:' in front of
 
137
         * events that are not recognized as native.
 
138
         */
 
139
        addNS: function (eventName) {
 
140
                var HTMLEvents = /^(?:load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll)$/,
 
141
                        MouseEvents = /^(?:click|mouse(?:down|up|over|move|out))$/;
 
142
                return (HTMLEvents.test(eventName) || MouseEvents.test(eventName)) ?
 
143
                        eventName :
 
144
                        'h:' + eventName;
 
145
        },
 
146
 
 
147
        // el needs an event to be attached. el is not necessarily a dom element
 
148
        addEvent: function (el, event, fn) {
 
149
                if (el.addEventListener || el.attachEvent) {
 
150
                        Event.observe($(el), HighchartsAdapter.addNS(event), fn);
 
151
 
 
152
                } else {
 
153
                        HighchartsAdapter._extend(el);
 
154
                        el._highcharts_observe(event, fn);
 
155
                }
 
156
        },
 
157
 
 
158
        // motion makes things pretty. use it if effects is loaded, if not... still get to the end result.
 
159
        animate: function (el, params, options) {
 
160
                var key,
 
161
                        fx;
 
162
 
 
163
                // default options
 
164
                options = options || {};
 
165
                options.delay = 0;
 
166
                options.duration = (options.duration || 500) / 1000;
 
167
                options.afterFinish = options.complete;
 
168
 
 
169
                // animate wrappers and DOM elements
 
170
                if (hasEffect) {
 
171
                        for (key in params) {
 
172
                                // The fx variable is seemingly thrown away here, but the Effect.setup will add itself to the _highcharts_animation object
 
173
                                // on the element itself so its not really lost.
 
174
                                fx = new Effect.HighchartsTransition($(el), key, params[key], options);
 
175
                        }
 
176
                } else {
 
177
                        if (el.attr) { // #409 without effects
 
178
                                for (key in params) {
 
179
                                        el.attr(key, params[key]);
 
180
                                }
 
181
                        }
 
182
                        if (options.complete) {
 
183
                                options.complete();
 
184
                        }
 
185
                }
 
186
 
 
187
                if (!el.attr) { // HTML element, #409
 
188
                        $(el).setStyle(params);
 
189
                }
 
190
        },
 
191
 
 
192
        // this only occurs in higcharts 2.0+
 
193
        stop: function (el) {
 
194
                var key;
 
195
                if (el._highcharts_extended && el._highchart_animation) {
 
196
                        for (key in el._highchart_animation) {
 
197
                                // Cancel the animation
 
198
                                // The 'finish' function in the Effect object will remove the reference
 
199
                                el._highchart_animation[key].cancel();
 
200
                        }
 
201
                }
 
202
        },
 
203
 
 
204
        // um.. each
 
205
        each: function (arr, fn) {
 
206
                $A(arr).each(fn);
 
207
        },
 
208
        
 
209
        inArray: function (item, arr, from) {
 
210
                return arr ? arr.indexOf(item, from) : -1;
 
211
        },
 
212
 
 
213
        /**
 
214
         * Get the cumulative offset relative to the top left of the page. This method, unlike its
 
215
         * jQuery and MooTools counterpart, still suffers from issue #208 regarding the position
 
216
         * of a chart within a fixed container.
 
217
         */
 
218
        offset: function (el) {
 
219
                return $(el).cumulativeOffset();
 
220
        },
 
221
 
 
222
        // fire an event based on an event name (event) and an object (el).
 
223
        // again, el may not be a dom element
 
224
        fireEvent: function (el, event, eventArguments, defaultFunction) {
 
225
                if (el.fire) {
 
226
                        el.fire(HighchartsAdapter.addNS(event), eventArguments);
 
227
                } else if (el._highcharts_extended) {
 
228
                        eventArguments = eventArguments || {};
 
229
                        el._highcharts_fire(event, eventArguments);
 
230
                }
 
231
 
 
232
                if (eventArguments && eventArguments.defaultPrevented) {
 
233
                        defaultFunction = null;
 
234
                }
 
235
 
 
236
                if (defaultFunction) {
 
237
                        defaultFunction(eventArguments);
 
238
                }
 
239
        },
 
240
 
 
241
        removeEvent: function (el, event, handler) {
 
242
                if ($(el).stopObserving) {
 
243
                        if (event) {
 
244
                                event = HighchartsAdapter.addNS(event);
 
245
                        }
 
246
                        $(el).stopObserving(event, handler);
 
247
                } if (window === el) {
 
248
                        Event.stopObserving(el, event, handler);
 
249
                } else {
 
250
                        HighchartsAdapter._extend(el);
 
251
                        el._highcharts_stop_observing(event, handler);
 
252
                }
 
253
        },
 
254
        
 
255
        washMouseEvent: function (e) {
 
256
                return e;
 
257
        },
 
258
 
 
259
        // um, grep
 
260
        grep: function (arr, fn) {
 
261
                return arr.findAll(fn);
 
262
        },
 
263
 
 
264
        // um, map
 
265
        map: function (arr, fn) {
 
266
                return arr.map(fn);
 
267
        },
 
268
 
 
269
        // extend an object to handle highchart events (highchart objects, not svg elements).
 
270
        // this is a very simple way of handling events but whatever, it works (i think)
 
271
        _extend: function (object) {
 
272
                if (!object._highcharts_extended) {
 
273
                        Object.extend(object, {
 
274
                                _highchart_events: {},
 
275
                                _highchart_animation: null,
 
276
                                _highcharts_extended: true,
 
277
                                _highcharts_observe: function (name, fn) {
 
278
                                        this._highchart_events[name] = [this._highchart_events[name], fn].compact().flatten();
 
279
                                },
 
280
                                _highcharts_stop_observing: function (name, fn) {
 
281
                                        if (name) {
 
282
                                                if (fn) {
 
283
                                                        this._highchart_events[name] = [this._highchart_events[name]].compact().flatten().without(fn);
 
284
                                                } else {
 
285
                                                        delete this._highchart_events[name];
 
286
                                                }
 
287
                                        } else {
 
288
                                                this._highchart_events = {};
 
289
                                        }
 
290
                                },
 
291
                                _highcharts_fire: function (name, args) {
 
292
                                        var target = this;
 
293
                                        (this._highchart_events[name] || []).each(function (fn) {
 
294
                                                // args is never null here
 
295
                                                if (args.stopped) {
 
296
                                                        return; // "throw $break" wasn't working. i think because of the scope of 'this'.
 
297
                                                }
 
298
 
 
299
                                                // Attach a simple preventDefault function to skip default handler if called
 
300
                                                args.preventDefault = function () {
 
301
                                                        args.defaultPrevented = true;
 
302
                                                };
 
303
                                                args.target = target;
 
304
 
 
305
                                                // If the event handler return false, prevent the default handler from executing
 
306
                                                if (fn.bind(this)(args) === false) {
 
307
                                                        args.preventDefault();
 
308
                                                }
 
309
                                        }
 
310
.bind(this));
 
311
                                }
 
312
                        });
 
313
                }
 
314
        }
 
315
};
 
316
}());