懒羊羊
2023-08-30 71e81ed1d12e4d69f53c8ad9e066650ad4186293
提交 | 用户 | 时间
71e81e 1 /**
2  * @license Highcharts JS v3.0.6 (2013-10-04)
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                     args.type = name; // #2297    
163                     
164                     // If the event handler return false, prevent the default handler from executing
165                     if (fn.call(this, args) === false) {
166                         args.preventDefault();
167                     }
168                 }
169             }
170         });
171     }
172
173     return obj;
174 }
175
176
177 return {
178     /**
179      * Initialize the adapter. This is run once as Highcharts is first run.
180      */
181     init: function (pathAnim) {
182
183         /**
184          * Compatibility section to add support for legacy IE. This can be removed if old IE 
185          * support is not needed.
186          */
187         if (!doc.defaultView) {
188             this._getStyle = function (el, prop) {
189                 var val;
190                 if (el.style[prop]) {
191                     return el.style[prop];
192                 } else {
193                     if (prop === 'opacity') {
194                         prop = 'filter';
195                     }
196                     /*jslint unparam: true*/
197                     val = el.currentStyle[prop.replace(/\-(\w)/g, function (a, b) { return b.toUpperCase(); })];
198                     if (prop === 'filter') {
199                         val = val.replace(
200                             /alpha\(opacity=([0-9]+)\)/, 
201                             function (a, b) { 
202                                 return b / 100; 
203                             }
204                         );
205                     }
206                     /*jslint unparam: false*/
207                     return val === '' ? 1 : val;
208                 } 
209             };
210             this.adapterRun = function (elem, method) {
211                 var alias = { width: 'clientWidth', height: 'clientHeight' }[method];
212
213                 if (alias) {
214                     elem.style.zoom = 1;
215                     return elem[alias] - 2 * parseInt(HighchartsAdapter._getStyle(elem, 'padding'), 10);
216                 }
217             };
218         }
219
220         if (!Array.prototype.forEach) {
221             this.each = function (arr, fn) { // legacy
222                 var i = 0, 
223                     len = arr.length;
224                 for (; i < len; i++) {
225                     if (fn.call(arr[i], arr[i], i, arr) === false) {
226                         return i;
227                     }
228                 }
229             };
230         }
231
232         if (!Array.prototype.indexOf) {
233             this.inArray = function (item, arr) {
234                 var len, 
235                     i = 0;
236
237                 if (arr) {
238                     len = arr.length;
239                     
240                     for (; i < len; i++) {
241                         if (arr[i] === item) {
242                             return i;
243                         }
244                     }
245                 }
246
247                 return -1;
248             };
249         }
250
251         if (!Array.prototype.filter) {
252             this.grep = function (elements, callback) {
253                 var ret = [],
254                     i = 0,
255                     length = elements.length;
256
257                 for (; i < length; i++) {
258                     if (!!callback(elements[i], i)) {
259                         ret.push(elements[i]);
260                     }
261                 }
262
263                 return ret;
264             };
265         }
266
267         //--- End compatibility section ---
268
269
270         /**
271          * Start of animation specific code
272          */
273         Fx = function (elem, options, prop) {
274             this.options = options;
275             this.elem = elem;
276             this.prop = prop;
277         };
278         Fx.prototype = {
279             
280             update: function () {
281                 var styles,
282                     paths = this.paths,
283                     elem = this.elem,
284                     elemelem = elem.element; // if destroyed, it is null
285
286                 // Animating a path definition on SVGElement
287                 if (paths && elemelem) {
288                     elem.attr('d', pathAnim.step(paths[0], paths[1], this.now, this.toD));
289                 
290                 // Other animations on SVGElement
291                 } else if (elem.attr) {
292                     if (elemelem) {
293                         elem.attr(this.prop, this.now);
294                     }
295
296                 // HTML styles
297                 } else {
298                     styles = {};
299                     styles[elem] = this.now + this.unit;
300                     Highcharts.css(elem, styles);
301                 }
302                 
303                 if (this.options.step) {
304                     this.options.step.call(this.elem, this.now, this);
305                 }
306
307             },
308             custom: function (from, to, unit) {
309                 var self = this,
310                     t = function (gotoEnd) {
311                         return self.step(gotoEnd);
312                     },
313                     i;
314
315                 this.startTime = +new Date();
316                 this.start = from;
317                 this.end = to;
318                 this.unit = unit;
319                 this.now = this.start;
320                 this.pos = this.state = 0;
321
322                 t.elem = this.elem;
323
324                 if (t() && timers.push(t) === 1) {
325                     timerId = setInterval(function () {
326                         
327                         for (i = 0; i < timers.length; i++) {
328                             if (!timers[i]()) {
329                                 timers.splice(i--, 1);
330                             }
331                         }
332
333                         if (!timers.length) {
334                             clearInterval(timerId);
335                         }
336                     }, 13);
337                 }
338             },
339             
340             step: function (gotoEnd) {
341                 var t = +new Date(),
342                     ret,
343                     done,
344                     options = this.options,
345                     i;
346
347                 if (this.elem.stopAnimation) {
348                     ret = false;
349
350                 } else if (gotoEnd || t >= options.duration + this.startTime) {
351                     this.now = this.end;
352                     this.pos = this.state = 1;
353                     this.update();
354
355                     this.options.curAnim[this.prop] = true;
356
357                     done = true;
358                     for (i in options.curAnim) {
359                         if (options.curAnim[i] !== true) {
360                             done = false;
361                         }
362                     }
363
364                     if (done) {
365                         if (options.complete) {
366                             options.complete.call(this.elem);
367                         }
368                     }
369                     ret = false;
370
371                 } else {
372                     var n = t - this.startTime;
373                     this.state = n / options.duration;
374                     this.pos = options.easing(n, 0, 1, options.duration);
375                     this.now = this.start + ((this.end - this.start) * this.pos);
376                     this.update();
377                     ret = true;
378                 }
379                 return ret;
380             }
381         };
382
383         /**
384          * The adapter animate method
385          */
386         this.animate = function (el, prop, opt) {
387             var start,
388                 unit = '',
389                 end,
390                 fx,
391                 args,
392                 name;
393
394             el.stopAnimation = false; // ready for new
395
396             if (typeof opt !== 'object' || opt === null) {
397                 args = arguments;
398                 opt = {
399                     duration: args[2],
400                     easing: args[3],
401                     complete: args[4]
402                 };
403             }
404             if (typeof opt.duration !== 'number') {
405                 opt.duration = 400;
406             }
407             opt.easing = Math[opt.easing] || Math.easeInOutSine;
408             opt.curAnim = Highcharts.extend({}, prop);
409             
410             for (name in prop) {
411                 fx = new Fx(el, opt, name);
412                 end = null;
413                 
414                 if (name === 'd') {
415                     fx.paths = pathAnim.init(
416                         el,
417                         el.d,
418                         prop.d
419                     );
420                     fx.toD = prop.d;
421                     start = 0;
422                     end = 1;
423                 } else if (el.attr) {
424                     start = el.attr(name);
425                 } else {
426                     start = parseFloat(HighchartsAdapter._getStyle(el, name)) || 0;
427                     if (name !== 'opacity') {
428                         unit = 'px';
429                     }
430                 }
431     
432                 if (!end) {
433                     end = parseFloat(prop[name]);
434                 }
435                 fx.custom(start, end, unit);
436             }    
437         };
438     },
439
440     /**
441      * Internal method to return CSS value for given element and property
442      */
443     _getStyle: function (el, prop) {
444         return window.getComputedStyle(el).getPropertyValue(prop);
445     },
446
447     /**
448      * Downloads a script and executes a callback when done.
449      * @param {String} scriptLocation
450      * @param {Function} callback
451      */
452     getScript: function (scriptLocation, callback) {
453         // We cannot assume that Assets class from mootools-more is available so instead insert a script tag to download script.
454         var head = doc.getElementsByTagName('head')[0],
455             script = doc.createElement('script');
456
457         script.type = 'text/javascript';
458         script.src = scriptLocation;
459         script.onload = callback;
460
461         head.appendChild(script);
462     },
463
464     /**
465      * Return the index of an item in an array, or -1 if not found
466      */
467     inArray: function (item, arr) {
468         return arr.indexOf ? arr.indexOf(item) : emptyArray.indexOf.call(arr, item);
469     },
470
471
472     /**
473      * A direct link to adapter methods
474      */
475     adapterRun: function (elem, method) {
476         return parseInt(HighchartsAdapter._getStyle(elem, method), 10);
477     },
478
479     /**
480      * Filter an array
481      */
482     grep: function (elements, callback) {
483         return emptyArray.filter.call(elements, callback);
484     },
485
486     /**
487      * Map an array
488      */
489     map: function (arr, fn) {
490         var results = [], i = 0, len = arr.length;
491
492         for (; i < len; i++) {
493             results[i] = fn.call(arr[i], arr[i], i, arr);
494         }
495
496         return results;
497     },
498
499     offset: function (el) {
500         var left = 0,
501             top = 0;
502
503         while (el) {
504             left += el.offsetLeft;
505             top += el.offsetTop;
506             el = el.offsetParent;
507         }
508
509         return {
510             left: left,
511             top: top
512         };
513     },
514
515     /**
516      * Add an event listener
517      */
518     addEvent: function (el, type, fn) {
519         augment(el).bind(type, fn);
520     },
521
522     /**
523      * Remove event added with addEvent
524      */
525     removeEvent: function (el, type, fn) {
526         augment(el).unbind(type, fn);
527     },
528
529     /**
530      * Fire an event on a custom object
531      */
532     fireEvent: function (el, type, eventArguments, defaultFunction) {
533         var e;
534
535         if (doc.createEvent && (el.dispatchEvent || el.fireEvent)) {
536             e = doc.createEvent('Events');
537             e.initEvent(type, true, true);
538             e.target = el;
539
540             Highcharts.extend(e, eventArguments);
541
542             if (el.dispatchEvent) {
543                 el.dispatchEvent(e);
544             } else {
545                 el.fireEvent(type, e);
546             }
547
548         } else if (el.HCExtended === true) {
549             eventArguments = eventArguments || {};
550             el.trigger(type, eventArguments);
551         }
552
553         if (eventArguments && eventArguments.defaultPrevented) {
554             defaultFunction = null;
555         }
556
557         if (defaultFunction) {
558             defaultFunction(eventArguments);
559         }
560     },
561
562     washMouseEvent: function (e) {
563         return e;
564     },
565
566
567     /**
568      * Stop running animation
569      */
570     stop: function (el) {
571         el.stopAnimation = true;
572     },
573
574     /**
575      * Utility for iterating over an array. Parameters are reversed compared to jQuery.
576      * @param {Array} arr
577      * @param {Function} fn
578      */
579     each: function (arr, fn) { // modern browsers
580         return Array.prototype.forEach.call(arr, fn);
581     }
582 };
583 }());