Subversion-Projekte lars-tiefland.cienc

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

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