Subversion-Projekte lars-tiefland.cienc

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

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