2
* @license Highstock JS v1.3.10 (2014-03-10)
4
* Standalone Highcharts Framework
10
/*global Highcharts */
11
var HighchartsAdapter = (function () {
20
Math.easeInOutSine = function (t, b, c, d) {
21
return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;
27
* Extend given object with custom events
29
function augment(obj) {
30
function removeOneEvent(el, type, fn) {
31
el.removeEventListener(type, fn, false);
34
function IERemoveOneEvent(el, type, fn) {
35
fn = el.HCProxiedMethods[fn.toString()];
36
el.detachEvent('on' + type, fn);
39
function removeAllEvents(el, type) {
40
var events = el.HCEvents,
46
if (el.removeEventListener) {
47
remove = removeOneEvent;
48
} else if (el.attachEvent) {
49
remove = IERemoveOneEvent;
51
return; // break on non-DOM events
64
len = events[n].length;
66
remove(el, n, events[n][len]);
72
if (!obj.HCExtended) {
73
Highcharts.extend(obj, {
78
bind: function (name, fn) {
80
events = this.HCEvents,
83
// handle DOM events in modern browsers
84
if (el.addEventListener) {
85
el.addEventListener(name, fn, false);
87
// handle old IE implementation
88
} else if (el.attachEvent) {
90
wrappedFn = function (e) {
94
if (!el.HCProxiedMethods) {
95
el.HCProxiedMethods = {};
98
// link wrapped fn with original fn, so we can get this in removeEvent
99
el.HCProxiedMethods[fn.toString()] = wrappedFn;
101
el.attachEvent('on' + name, wrappedFn);
105
if (events[name] === UNDEFINED) {
109
events[name].push(fn);
112
unbind: function (name, fn) {
117
events = this.HCEvents[name] || [];
119
index = HighchartsAdapter.inArray(fn, events);
121
events.splice(index, 1);
122
this.HCEvents[name] = events;
124
if (this.removeEventListener) {
125
removeOneEvent(this, name, fn);
126
} else if (this.attachEvent) {
127
IERemoveOneEvent(this, name, fn);
130
removeAllEvents(this, name);
131
this.HCEvents[name] = [];
134
removeAllEvents(this);
139
trigger: function (name, args) {
140
var events = this.HCEvents[name] || [],
147
// Attach a simple preventDefault function to skip default handler if called
148
preventDefault = function () {
149
args.defaultPrevented = true;
152
for (i = 0; i < len; i++) {
155
// args is never null here
160
args.preventDefault = preventDefault;
161
args.target = target;
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
172
// If the event handler return false, prevent the default handler from executing
173
if (fn.call(this, args) === false) {
174
args.preventDefault();
187
* Initialize the adapter. This is run once as Highcharts is first run.
189
init: function (pathAnim) {
192
* Compatibility section to add support for legacy IE. This can be removed if old IE
193
* support is not needed.
195
if (!doc.defaultView) {
196
this._getStyle = function (el, prop) {
198
if (el.style[prop]) {
199
return el.style[prop];
201
if (prop === 'opacity') {
204
/*jslint unparam: true*/
205
val = el.currentStyle[prop.replace(/\-(\w)/g, function (a, b) { return b.toUpperCase(); })];
206
if (prop === 'filter') {
208
/alpha\(opacity=([0-9]+)\)/,
214
/*jslint unparam: false*/
215
return val === '' ? 1 : val;
218
this.adapterRun = function (elem, method) {
219
var alias = { width: 'clientWidth', height: 'clientHeight' }[method];
223
return elem[alias] - 2 * parseInt(HighchartsAdapter._getStyle(elem, 'padding'), 10);
228
if (!Array.prototype.forEach) {
229
this.each = function (arr, fn) { // legacy
232
for (; i < len; i++) {
233
if (fn.call(arr[i], arr[i], i, arr) === false) {
240
if (!Array.prototype.indexOf) {
241
this.inArray = function (item, arr) {
248
for (; i < len; i++) {
249
if (arr[i] === item) {
259
if (!Array.prototype.filter) {
260
this.grep = function (elements, callback) {
263
length = elements.length;
265
for (; i < length; i++) {
266
if (!!callback(elements[i], i)) {
267
ret.push(elements[i]);
275
//--- End compatibility section ---
279
* Start of animation specific code
281
Fx = function (elem, options, prop) {
282
this.options = options;
288
update: function () {
292
elemelem = elem.element; // if destroyed, it is null
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));
298
// Other animations on SVGElement
299
} else if (elem.attr) {
301
elem.attr(this.prop, this.now);
307
styles[this.prop] = this.now + this.unit;
308
Highcharts.css(elem, styles);
311
if (this.options.step) {
312
this.options.step.call(this.elem, this.now, this);
316
custom: function (from, to, unit) {
318
t = function (gotoEnd) {
319
return self.step(gotoEnd);
323
this.startTime = +new Date();
327
this.now = this.start;
328
this.pos = this.state = 0;
332
if (t() && timers.push(t) === 1) {
333
timerId = setInterval(function () {
335
for (i = 0; i < timers.length; i++) {
337
timers.splice(i--, 1);
341
if (!timers.length) {
342
clearInterval(timerId);
348
step: function (gotoEnd) {
352
options = this.options,
356
if (elem.stopAnimation || (elem.attr && !elem.element)) { // #2616, element including flag is destroyed
359
} else if (gotoEnd || t >= options.duration + this.startTime) {
361
this.pos = this.state = 1;
364
this.options.curAnim[this.prop] = true;
367
for (i in options.curAnim) {
368
if (options.curAnim[i] !== true) {
374
if (options.complete) {
375
options.complete.call(elem);
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);
393
* The adapter animate method
395
this.animate = function (el, prop, opt) {
403
el.stopAnimation = false; // ready for new
405
if (typeof opt !== 'object' || opt === null) {
413
if (typeof opt.duration !== 'number') {
416
opt.easing = Math[opt.easing] || Math.easeInOutSine;
417
opt.curAnim = Highcharts.extend({}, prop);
420
fx = new Fx(el, opt, name);
424
fx.paths = pathAnim.init(
432
} else if (el.attr) {
433
start = el.attr(name);
435
start = parseFloat(HighchartsAdapter._getStyle(el, name)) || 0;
436
if (name !== 'opacity') {
442
end = parseFloat(prop[name]);
444
fx.custom(start, end, unit);
450
* Internal method to return CSS value for given element and property
452
_getStyle: function (el, prop) {
453
return window.getComputedStyle(el).getPropertyValue(prop);
457
* Downloads a script and executes a callback when done.
458
* @param {String} scriptLocation
459
* @param {Function} callback
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');
466
script.type = 'text/javascript';
467
script.src = scriptLocation;
468
script.onload = callback;
470
head.appendChild(script);
474
* Return the index of an item in an array, or -1 if not found
476
inArray: function (item, arr) {
477
return arr.indexOf ? arr.indexOf(item) : emptyArray.indexOf.call(arr, item);
482
* A direct link to adapter methods
484
adapterRun: function (elem, method) {
485
return parseInt(HighchartsAdapter._getStyle(elem, method), 10);
491
grep: function (elements, callback) {
492
return emptyArray.filter.call(elements, callback);
498
map: function (arr, fn) {
499
var results = [], i = 0, len = arr.length;
501
for (; i < len; i++) {
502
results[i] = fn.call(arr[i], arr[i], i, arr);
509
* Get the element's offset position, corrected by overflow:auto. Loosely based on jQuery's offset method.
511
offset: function (el) {
512
var docElem = document.documentElement,
513
box = el.getBoundingClientRect();
516
top: box.top + (window.pageYOffset || docElem.scrollTop) - (docElem.clientTop || 0),
517
left: box.left + (window.pageXOffset || docElem.scrollLeft) - (docElem.clientLeft || 0)
522
* Add an event listener
524
addEvent: function (el, type, fn) {
525
augment(el).bind(type, fn);
529
* Remove event added with addEvent
531
removeEvent: function (el, type, fn) {
532
augment(el).unbind(type, fn);
536
* Fire an event on a custom object
538
fireEvent: function (el, type, eventArguments, defaultFunction) {
541
if (doc.createEvent && (el.dispatchEvent || el.fireEvent)) {
542
e = doc.createEvent('Events');
543
e.initEvent(type, true, true);
546
Highcharts.extend(e, eventArguments);
548
if (el.dispatchEvent) {
551
el.fireEvent(type, e);
554
} else if (el.HCExtended === true) {
555
eventArguments = eventArguments || {};
556
el.trigger(type, eventArguments);
559
if (eventArguments && eventArguments.defaultPrevented) {
560
defaultFunction = null;
563
if (defaultFunction) {
564
defaultFunction(eventArguments);
568
washMouseEvent: function (e) {
574
* Stop running animation
576
stop: function (el) {
577
el.stopAnimation = true;
581
* Utility for iterating over an array. Parameters are reversed compared to jQuery.
583
* @param {Function} fn
585
each: function (arr, fn) { // modern browsers
586
return Array.prototype.forEach.call(arr, fn);