text: /**
   * @license @product.name@ JS v@product.version@ (@product.date@)
   *
   * Standalone Highcharts Framework
   *
   * License: MIT License
   */
  
  
  /*global Highcharts */
  var HighchartsAdapter = (function () {
  
  var UNDEFINED,
    doc = document,
    emptyArray = [],
    timers = [],
    timerId,
    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
  
          // Animating a path definition on SVGElement
          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;
  
        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 = parseFloat(prop[name]);
          }
          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);
    },
  
    /**
     * 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);
    }
  };
  }());
  