Subversion-Projekte lars-tiefland.cienc

Revision

Blame | Letzte Änderung | Log anzeigen | RSS feed

/**
 * @license Highstock JS v2.1.8 (2015-08-20)
 *
 * Standalone Highcharts Framework
 *
 * License: MIT License
 */


/*global Highcharts */
var HighchartsAdapter = (function () {

var UNDEFINED,
        doc = document,
        emptyArray = [],
        timers = [],
        timerId,
        animSetters = {},
        Fx;

Math.easeInOutSine = function (t, b, c, d) {
        return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;
};



/**
 * Extend given object with custom events
 */
function augment(obj) {
        function removeOneEvent(el, type, fn) {
                el.removeEventListener(type, fn, false);
        }

        function IERemoveOneEvent(el, type, fn) {
                fn = el.HCProxiedMethods[fn.toString()];
                el.detachEvent('on' + type, fn);
        }

        function removeAllEvents(el, type) {
                var events = el.HCEvents,
                        remove,
                        types,
                        len,
                        n;

                if (el.removeEventListener) {
                        remove = removeOneEvent;
                } else if (el.attachEvent) {
                        remove = IERemoveOneEvent;
                } else {
                        return; // break on non-DOM events
                }


                if (type) {
                        types = {};
                        types[type] = true;
                } else {
                        types = events;
                }

                for (n in types) {
                        if (events[n]) {
                                len = events[n].length;
                                while (len--) {
                                        remove(el, n, events[n][len]);
                                }
                        }
                }
        }

        if (!obj.HCExtended) {
                Highcharts.extend(obj, {
                        HCExtended: true,

                        HCEvents: {},

                        bind: function (name, fn) {
                                var el = this,
                                        events = this.HCEvents,
                                        wrappedFn;

                                // handle DOM events in modern browsers
                                if (el.addEventListener) {
                                        el.addEventListener(name, fn, false);

                                // handle old IE implementation
                                } else if (el.attachEvent) {
                                        
                                        wrappedFn = function (e) {
                                                e.target = e.srcElement || window; // #2820
                                                fn.call(el, e);
                                        };

                                        if (!el.HCProxiedMethods) {
                                                el.HCProxiedMethods = {};
                                        }

                                        // link wrapped fn with original fn, so we can get this in removeEvent
                                        el.HCProxiedMethods[fn.toString()] = wrappedFn;

                                        el.attachEvent('on' + name, wrappedFn);
                                }


                                if (events[name] === UNDEFINED) {
                                        events[name] = [];
                                }

                                events[name].push(fn);
                        },

                        unbind: function (name, fn) {
                                var events,
                                        index;

                                if (name) {
                                        events = this.HCEvents[name] || [];
                                        if (fn) {
                                                index = HighchartsAdapter.inArray(fn, events);
                                                if (index > -1) {
                                                        events.splice(index, 1);
                                                        this.HCEvents[name] = events;
                                                }
                                                if (this.removeEventListener) {
                                                        removeOneEvent(this, name, fn);
                                                } else if (this.attachEvent) {
                                                        IERemoveOneEvent(this, name, fn);
                                                }
                                        } else {
                                                removeAllEvents(this, name);
                                                this.HCEvents[name] = [];
                                        }
                                } else {
                                        removeAllEvents(this);
                                        this.HCEvents = {};
                                }
                        },

                        trigger: function (name, args) {
                                var events = this.HCEvents[name] || [],
                                        target = this,
                                        len = events.length,
                                        i,
                                        preventDefault,
                                        fn;

                                // Attach a simple preventDefault function to skip default handler if called
                                preventDefault = function () {
                                        args.defaultPrevented = true;
                                };
                                
                                for (i = 0; i < len; i++) {
                                        fn = events[i];

                                        // args is never null here
                                        if (args.stopped) {
                                                return;
                                        }

                                        args.preventDefault = preventDefault;
                                        args.target = target;

                                        // If the type is not set, we're running a custom event (#2297). If it is set,
                                        // we're running a browser event, and setting it will cause en error in
                                        // IE8 (#2465).
                                        if (!args.type) {
                                                args.type = name;
                                        }
                                        

                                        
                                        // If the event handler return false, prevent the default handler from executing
                                        if (fn.call(this, args) === false) {
                                                args.preventDefault();
                                        }
                                }
                        }
                });
        }

        return obj;
}


return {

        /**
         * Initialize the adapter. This is run once as Highcharts is first run.
         */
        init: function (pathAnim) {

                /**
                 * Compatibility section to add support for legacy IE. This can be removed if old IE 
                 * support is not needed.
                 */
                if (!doc.defaultView) {
                        this._getStyle = function (el, prop) {
                                var val;
                                if (el.style[prop]) {
                                        return el.style[prop];
                                } else {
                                        if (prop === 'opacity') {
                                                prop = 'filter';
                                        }
                                        /*jslint unparam: true*/
                                        val = el.currentStyle[prop.replace(/\-(\w)/g, function (a, b) { return b.toUpperCase(); })];
                                        if (prop === 'filter') {
                                                val = val.replace(
                                                        /alpha\(opacity=([0-9]+)\)/, 
                                                        function (a, b) { 
                                                                return b / 100; 
                                                        }
                                                );
                                        }
                                        /*jslint unparam: false*/
                                        return val === '' ? 1 : val;
                                } 
                        };
                        this.adapterRun = function (elem, method) {
                                var alias = { width: 'clientWidth', height: 'clientHeight' }[method];

                                if (alias) {
                                        elem.style.zoom = 1;
                                        return elem[alias] - 2 * parseInt(HighchartsAdapter._getStyle(elem, 'padding'), 10);
                                }
                        };
                }

                if (!Array.prototype.forEach) {
                        this.each = function (arr, fn) { // legacy
                                var i = 0, 
                                        len = arr.length;
                                for (; i < len; i++) {
                                        if (fn.call(arr[i], arr[i], i, arr) === false) {
                                                return i;
                                        }
                                }
                        };
                }

                if (!Array.prototype.indexOf) {
                        this.inArray = function (item, arr) {
                                var len, 
                                        i = 0;

                                if (arr) {
                                        len = arr.length;
                                        
                                        for (; i < len; i++) {
                                                if (arr[i] === item) {
                                                        return i;
                                                }
                                        }
                                }

                                return -1;
                        };
                }

                if (!Array.prototype.filter) {
                        this.grep = function (elements, callback) {
                                var ret = [],
                                        i = 0,
                                        length = elements.length;

                                for (; i < length; i++) {
                                        if (!!callback(elements[i], i)) {
                                                ret.push(elements[i]);
                                        }
                                }

                                return ret;
                        };
                }

                //--- End compatibility section ---


                /**
                 * Start of animation specific code
                 */
                Fx = function (elem, options, prop) {
                        this.options = options;
                        this.elem = elem;
                        this.prop = prop;
                };
                Fx.prototype = {
                        
                        update: function () {
                                var styles,
                                        paths = this.paths,
                                        elem = this.elem,
                                        elemelem = elem.element; // if destroyed, it is null

                                // Animation setter defined from outside
                                if (animSetters[this.prop]) {
                                        animSetters[this.prop](this);

                                // Animating a path definition on SVGElement
                                } else if (paths && elemelem) {
                                        elem.attr('d', pathAnim.step(paths[0], paths[1], this.now, this.toD));

                                // Other animations on SVGElement
                                } else if (elem.attr) {
                                        if (elemelem) {
                                                elem.attr(this.prop, this.now);
                                        }

                                // HTML styles
                                } else {
                                        styles = {};
                                        styles[this.prop] = this.now + this.unit;
                                        Highcharts.css(elem, styles);
                                }
                                
                                if (this.options.step) {
                                        this.options.step.call(this.elem, this.now, this);
                                }

                        },
                        custom: function (from, to, unit) {
                                var self = this,
                                        t = function (gotoEnd) {
                                                return self.step(gotoEnd);
                                        },
                                        i;

                                this.startTime = +new Date();
                                this.start = from;
                                this.end = to;
                                this.unit = unit;
                                this.now = this.start;
                                this.pos = this.state = 0;

                                t.elem = this.elem;

                                if (t() && timers.push(t) === 1) {
                                        timerId = setInterval(function () {
                                                
                                                for (i = 0; i < timers.length; i++) {
                                                        if (!timers[i]()) {
                                                                timers.splice(i--, 1);
                                                        }
                                                }

                                                if (!timers.length) {
                                                        clearInterval(timerId);
                                                }
                                        }, 13);
                                }
                        },
                        
                        step: function (gotoEnd) {
                                var t = +new Date(),
                                        ret,
                                        done,
                                        options = this.options,
                                        elem = this.elem,
                                        i;
                                
                                if (elem.stopAnimation || (elem.attr && !elem.element)) { // #2616, element including flag is destroyed
                                        ret = false;

                                } else if (gotoEnd || t >= options.duration + this.startTime) {
                                        this.now = this.end;
                                        this.pos = this.state = 1;
                                        this.update();

                                        this.options.curAnim[this.prop] = true;

                                        done = true;
                                        for (i in options.curAnim) {
                                                if (options.curAnim[i] !== true) {
                                                        done = false;
                                                }
                                        }

                                        if (done) {
                                                if (options.complete) {
                                                        options.complete.call(elem);
                                                }
                                        }
                                        ret = false;

                                } else {
                                        var n = t - this.startTime;
                                        this.state = n / options.duration;
                                        this.pos = options.easing(n, 0, 1, options.duration);
                                        this.now = this.start + ((this.end - this.start) * this.pos);
                                        this.update();
                                        ret = true;
                                }
                                return ret;
                        }
                };

                /**
                 * The adapter animate method
                 */
                this.animate = function (el, prop, opt) {
                        var start,
                                unit = '',
                                end,
                                fx,
                                args,
                                name,
                                PX = 'px';

                        el.stopAnimation = false; // ready for new

                        if (typeof opt !== 'object' || opt === null) {
                                args = arguments;
                                opt = {
                                        duration: args[2],
                                        easing: args[3],
                                        complete: args[4]
                                };
                        }
                        if (typeof opt.duration !== 'number') {
                                opt.duration = 400;
                        }
                        opt.easing = Math[opt.easing] || Math.easeInOutSine;
                        opt.curAnim = Highcharts.extend({}, prop);
                        
                        for (name in prop) {
                                fx = new Fx(el, opt, name);
                                end = null;
                                
                                if (name === 'd') {
                                        fx.paths = pathAnim.init(
                                                el,
                                                el.d,
                                                prop.d
                                        );
                                        fx.toD = prop.d;
                                        start = 0;
                                        end = 1;
                                } else if (el.attr) {
                                        start = el.attr(name);
                                } else {
                                        start = parseFloat(HighchartsAdapter._getStyle(el, name)) || 0;
                                        if (name !== 'opacity') {
                                                unit = PX;
                                        }
                                }
        
                                if (!end) {
                                        end = prop[name];
                                }
                                if (end.match && end.match(PX)) {
                                        end = end.replace(/px/g, ''); // #4351
                                }
                                fx.custom(start, end, unit);
                        }       
                };
        },

        /**
         * Internal method to return CSS value for given element and property
         */
        _getStyle: function (el, prop) {
                return window.getComputedStyle(el, undefined).getPropertyValue(prop);
        },

        /**
         * Add an animation setter for a specific property
         */
        addAnimSetter: function (prop, fn) {
                animSetters[prop] = fn;
        },

        /**
         * Downloads a script and executes a callback when done.
         * @param {String} scriptLocation
         * @param {Function} callback
         */
        getScript: function (scriptLocation, callback) {
                // We cannot assume that Assets class from mootools-more is available so instead insert a script tag to download script.
                var head = doc.getElementsByTagName('head')[0],
                        script = doc.createElement('script');

                script.type = 'text/javascript';
                script.src = scriptLocation;
                script.onload = callback;

                head.appendChild(script);
        },

        /**
         * Return the index of an item in an array, or -1 if not found
         */
        inArray: function (item, arr) {
                return arr.indexOf ? arr.indexOf(item) : emptyArray.indexOf.call(arr, item);
        },


        /**
         * A direct link to adapter methods
         */
        adapterRun: function (elem, method) {
                return parseInt(HighchartsAdapter._getStyle(elem, method), 10);
        },

        /**
         * Filter an array
         */
        grep: function (elements, callback) {
                return emptyArray.filter.call(elements, callback);
        },

        /**
         * Map an array
         */
        map: function (arr, fn) {
                var results = [], i = 0, len = arr.length;

                for (; i < len; i++) {
                        results[i] = fn.call(arr[i], arr[i], i, arr);
                }

                return results;
        },

        /**
         * Get the element's offset position, corrected by overflow:auto. Loosely based on jQuery's offset method.
         */
        offset: function (el) {
                var docElem = document.documentElement,
                        box = el.getBoundingClientRect();

                return {
                        top: box.top  + (window.pageYOffset || docElem.scrollTop)  - (docElem.clientTop  || 0),
                        left: box.left + (window.pageXOffset || docElem.scrollLeft) - (docElem.clientLeft || 0)
                };
        },

        /**
         * Add an event listener
         */
        addEvent: function (el, type, fn) {
                augment(el).bind(type, fn);
        },

        /**
         * Remove event added with addEvent
         */
        removeEvent: function (el, type, fn) {
                augment(el).unbind(type, fn);
        },

        /**
         * Fire an event on a custom object
         */
        fireEvent: function (el, type, eventArguments, defaultFunction) {
                var e;

                if (doc.createEvent && (el.dispatchEvent || el.fireEvent)) {
                        e = doc.createEvent('Events');
                        e.initEvent(type, true, true);
                        e.target = el;

                        Highcharts.extend(e, eventArguments);

                        if (el.dispatchEvent) {
                                el.dispatchEvent(e);
                        } else {
                                el.fireEvent(type, e);
                        }

                } else if (el.HCExtended === true) {
                        eventArguments = eventArguments || {};
                        el.trigger(type, eventArguments);
                }

                if (eventArguments && eventArguments.defaultPrevented) {
                        defaultFunction = null;
                }

                if (defaultFunction) {
                        defaultFunction(eventArguments);
                }
        },

        washMouseEvent: function (e) {
                return e;
        },


        /**
         * Stop running animation
         */
        stop: function (el) {
                el.stopAnimation = true;
        },

        /**
         * Utility for iterating over an array. Parameters are reversed compared to jQuery.
         * @param {Array} arr
         * @param {Function} fn
         */
        each: function (arr, fn) { // modern browsers
                return Array.prototype.forEach.call(arr, fn);
        }
};
}());