text: /**
   * @license Highcharts JS v2.3.3 (2012-10-04)
   * MooTools adapter
   *
   * (c) 2010-2011 Torstein Hønsi
   *
   * License: www.highcharts.com/license
   */
  
  // JSLint options:
  /*global Fx, $, $extend, $each, $merge, Events, Event, DOMEvent */
  
  (function () {
  
      var win = window,
          doc = document,
          mooVersion = win.MooTools.version.substring(0, 3), // Get the first three characters of the version number
          legacy = mooVersion === '1.2' || mooVersion === '1.1', // 1.1 && 1.2 considered legacy, 1.3 is not.
          legacyEvent = legacy || mooVersion === '1.3', // In versions 1.1 - 1.3 the event class is named Event, in newer versions it is named DOMEvent.
          $extend = win.$extend || function () {
              return Object.append.apply(Object, arguments);
          };
  
      win.HighchartsAdapter = {
          /**
           * Initialize the adapter. This is run once as Highcharts is first run.
           * @param {Object} pathAnim The helper object to do animations across adapters.
           */
          init:function (pathAnim) {
              var fxProto = Fx.prototype,
                  fxStart = fxProto.start,
                  morphProto = Fx.Morph.prototype,
                  morphCompute = morphProto.compute;
  
              // override Fx.start to allow animation of SVG element wrappers
              /*jslint unparam: true*/
              /* allow unused parameters in fx functions */
              fxProto.start = function (from, to) {
                  var fx = this,
                      elem = fx.element;
  
                  // special for animating paths
                  if (from.d) {
                      //this.fromD = this.element.d.split(' ');
                      fx.paths = pathAnim.init(
                          elem,
                          elem.d,
                          fx.toD
                      );
                  }
                  fxStart.apply(fx, arguments);
  
                  return this; // chainable
              };
  
              // override Fx.step to allow animation of SVG element wrappers
              morphProto.compute = function (from, to, delta) {
                  var fx = this,
                      paths = fx.paths;
  
                  if (paths) {
                      fx.element.attr(
                          'd',
                          pathAnim.step(paths[0], paths[1], delta, fx.toD)
                      );
                  } else {
                      return morphCompute.apply(fx, arguments);
                  }
              };
              /*jslint unparam: false*/
          },
  
          /**
           * Run a general method on the framework, following jQuery syntax
           * @param {Object} el The HTML element
           * @param {String} method Which method to run on the wrapped element
           */
          adapterRun:function (el, method) {
  
              // This currently works for getting inner width and height. If adding
              // more methods later, we need a conditional implementation for each.
              if (method === 'width' || method === 'height') {
                  return parseInt($(el).getStyle(method), 10);
              }
          },
  
          /**
           * 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];
              var script = doc.createElement('script');
  
              script.type = 'text/javascript';
              script.src = scriptLocation;
              script.onload = callback;
  
              head.appendChild(script);
          },
  
          /**
           * Animate a HTML element or SVG element wrapper
           * @param {Object} el
           * @param {Object} params
           * @param {Object} options jQuery-like animation options: duration, easing, callback
           */
          animate:function (el, params, options) {
              var isSVGElement = el.attr,
                  effect,
                  complete = options && options.complete;
  
              if (isSVGElement && !el.setStyle) {
                  // add setStyle and getStyle methods for internal use in Moo
                  el.getStyle = el.attr;
                  el.setStyle = function () { // property value is given as array in Moo - break it down
                      var args = arguments;
                      el.attr.call(el, args[0], args[1][0]);
                  };
                  // dirty hack to trick Moo into handling el as an element wrapper
                  el.$family = function () {
                      return true;
                  };
              }
  
              // stop running animations
              win.HighchartsAdapter.stop(el);
  
              // define and run the effect
              effect = new Fx.Morph(
                  isSVGElement ? el : $(el),
                  $extend({
                              transition:Fx.Transitions.Quad.easeInOut
                          }, options)
              );
  
              // Make sure that the element reference is set when animating svg elements
              if (isSVGElement) {
                  effect.element = el;
              }
  
              // special treatment for paths
              if (params.d) {
                  effect.toD = params.d;
              }
  
              // jQuery-like events
              if (complete) {
                  effect.addEvent('complete', complete);
              }
  
              // run
              effect.start(params);
  
              // record for use in stop method
              el.fx = effect;
          },
  
          /**
           * MooTool's each function
           *
           */
          each:function (arr, fn) {
              return legacy ?
                  $each(arr, fn) :
                  Array.each(arr, fn);
          },
  
          /**
           * Map an array
           * @param {Array} arr
           * @param {Function} fn
           */
          map:function (arr, fn) {
              return arr.map(fn);
          },
  
          /**
           * Grep or filter an array
           * @param {Array} arr
           * @param {Function} fn
           */
          grep:function (arr, fn) {
              return arr.filter(fn);
          },
  
          /**
           * Return the index of an item in an array, or -1 if not matched
           */
          inArray:function (item, arr, from) {
              return arr.indexOf(item, from);
          },
  
          /**
           * Deep merge two objects and return a third
           */
          merge:function () {
              var args = arguments,
                  args13 = [
                      {}
                  ], // MooTools 1.3+
                  i = args.length,
                  ret;
  
              if (legacy) {
                  ret = $merge.apply(null, args);
              } else {
                  while (i--) {
                      // Boolean argumens should not be merged.
                      // JQuery explicitly skips this, so we do it here as well.
                      if (typeof args[i] !== 'boolean') {
                          args13[i + 1] = args[i];
                      }
                  }
                  ret = Object.merge.apply(Object, args13);
              }
  
              return ret;
          },
  
          /**
           * Get the offset of an element relative to the top left corner of the web page
           */
          offset:function (el) {
              var offsets = $(el).getOffsets();
              return {
                  left:offsets.x,
                  top:offsets.y
              };
          },
  
          /**
           * Extends an object with Events, if its not done
           */
          extendWithEvents:function (el) {
              // if the addEvent method is not defined, el is a custom Highcharts object
              // like series or point
              if (!el.addEvent) {
                  if (el.nodeName) {
                      el = $(el); // a dynamically generated node
                  } else {
                      $extend(el, new Events()); // a custom object
                  }
              }
          },
  
          /**
           * Add an event listener
           * @param {Object} el HTML element or custom object
           * @param {String} type Event type
           * @param {Function} fn Event handler
           */
          addEvent:function (el, type, fn) {
              if (typeof type === 'string') { // chart broke due to el being string, type function
  
                  if (type === 'unload') { // Moo self destructs before custom unload events
                      type = 'beforeunload';
                  }
  
                  win.HighchartsAdapter.extendWithEvents(el);
  
                  el.addEvent(type, fn);
              }
          },
  
          removeEvent:function (el, type, fn) {
              if (typeof el === 'string') {
                  // el.removeEvents below apperantly calls this method again. Do not quite understand why, so for now just bail out.
                  return;
              }
  
              win.HighchartsAdapter.extendWithEvents(el);
              if (type) {
                  if (type === 'unload') { // Moo self destructs before custom unload events
                      type = 'beforeunload';
                  }
  
                  if (fn) {
                      el.removeEvent(type, fn);
                  } else if (el.removeEvents) { // #958
                      el.removeEvents(type);
                  }
              } else {
                  el.removeEvents();
              }
          },
  
          fireEvent:function (el, event, eventArguments, defaultFunction) {
              var eventArgs = {
                  type:event,
                  target:el
              };
              // create an event object that keeps all functions
              event = legacyEvent ? new Event(eventArgs) : new DOMEvent(eventArgs);
              event = $extend(event, eventArguments);
              // override the preventDefault function to be able to use
              // this for custom events
              event.preventDefault = function () {
                  defaultFunction = null;
              };
              // if fireEvent is not available on the object, there hasn't been added
              // any events to it above
              if (el.fireEvent) {
                  el.fireEvent(event.type, event);
              }
  
              // fire the default if it is passed and it is not prevented above
              if (defaultFunction) {
                  defaultFunction(event);
              }
          },
  
          /**
           * Set back e.pageX and e.pageY that MooTools has abstracted away
           */
          washMouseEvent:function (e) {
              return e.event || e;
          },
  
          /**
           * Stop running animations on the object
           */
          stop:function (el) {
              if (el.fx) {
                  el.fx.cancel();
              }
          }
      };
  
  }());
  