123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 |
- /**
- * @license Highcharts JS v3.0.6 (2013-10-04)
- * Prototype adapter
- *
- * @author Michael Nelson, Torstein Hønsi.
- *
- * Feel free to use and modify this script.
- * Highcharts license: www.highcharts.com/license.
- */
- // JSLint options:
- /*global Effect, Class, Event, Element, $, $$, $A */
- // Adapter interface between prototype and the Highcharts charting library
- var HighchartsAdapter = (function () {
- var hasEffect = typeof Effect !== 'undefined';
- return {
- /**
- * 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) {
- if (hasEffect) {
- /**
- * Animation for Highcharts SVG element wrappers only
- * @param {Object} element
- * @param {Object} attribute
- * @param {Object} to
- * @param {Object} options
- */
- Effect.HighchartsTransition = Class.create(Effect.Base, {
- initialize: function (element, attr, to, options) {
- var from,
- opts;
- this.element = element;
- this.key = attr;
- from = element.attr ? element.attr(attr) : $(element).getStyle(attr);
- // special treatment for paths
- if (attr === 'd') {
- this.paths = pathAnim.init(
- element,
- element.d,
- to
- );
- this.toD = to;
- // fake values in order to read relative position as a float in update
- from = 0;
- to = 1;
- }
- opts = Object.extend((options || {}), {
- from: from,
- to: to,
- attribute: attr
- });
- this.start(opts);
- },
- setup: function () {
- HighchartsAdapter._extend(this.element);
- // If this is the first animation on this object, create the _highcharts_animation helper that
- // contain pointers to the animation objects.
- if (!this.element._highchart_animation) {
- this.element._highchart_animation = {};
- }
- // Store a reference to this animation instance.
- this.element._highchart_animation[this.key] = this;
- },
- update: function (position) {
- var paths = this.paths,
- element = this.element,
- obj;
- if (paths) {
- position = pathAnim.step(paths[0], paths[1], position, this.toD);
- }
- if (element.attr) { // SVGElement
-
- if (element.element) { // If not, it has been destroyed (#1405)
- element.attr(this.options.attribute, position);
- }
-
- } else { // HTML, #409
- obj = {};
- obj[this.options.attribute] = position;
- $(element).setStyle(obj);
- }
-
- },
- finish: function () {
- // Delete the property that holds this animation now that it is finished.
- // Both canceled animations and complete ones gets a 'finish' call.
- if (this.element && this.element._highchart_animation) { // #1405
- delete this.element._highchart_animation[this.key];
- }
- }
- });
- }
- },
-
- /**
- * 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.
- 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) {
- var head = $$('head')[0]; // Returns an array, so pick the first element.
- if (head) {
- // Append a new 'script' element, set its type and src attributes, add a 'load' handler that calls the callback
- head.appendChild(new Element('script', { type: 'text/javascript', src: scriptLocation}).observe('load', callback));
- }
- },
- /**
- * Custom events in prototype needs to be namespaced. This method adds a namespace 'h:' in front of
- * events that are not recognized as native.
- */
- addNS: function (eventName) {
- var HTMLEvents = /^(?:load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll)$/,
- MouseEvents = /^(?:click|mouse(?:down|up|over|move|out))$/;
- return (HTMLEvents.test(eventName) || MouseEvents.test(eventName)) ?
- eventName :
- 'h:' + eventName;
- },
- // el needs an event to be attached. el is not necessarily a dom element
- addEvent: function (el, event, fn) {
- if (el.addEventListener || el.attachEvent) {
- Event.observe($(el), HighchartsAdapter.addNS(event), fn);
- } else {
- HighchartsAdapter._extend(el);
- el._highcharts_observe(event, fn);
- }
- },
- // motion makes things pretty. use it if effects is loaded, if not... still get to the end result.
- animate: function (el, params, options) {
- var key,
- fx;
- // default options
- options = options || {};
- options.delay = 0;
- options.duration = (options.duration || 500) / 1000;
- options.afterFinish = options.complete;
- // animate wrappers and DOM elements
- if (hasEffect) {
- for (key in params) {
- // The fx variable is seemingly thrown away here, but the Effect.setup will add itself to the _highcharts_animation object
- // on the element itself so its not really lost.
- fx = new Effect.HighchartsTransition($(el), key, params[key], options);
- }
- } else {
- if (el.attr) { // #409 without effects
- for (key in params) {
- el.attr(key, params[key]);
- }
- }
- if (options.complete) {
- options.complete();
- }
- }
- if (!el.attr) { // HTML element, #409
- $(el).setStyle(params);
- }
- },
- // this only occurs in higcharts 2.0+
- stop: function (el) {
- var key;
- if (el._highcharts_extended && el._highchart_animation) {
- for (key in el._highchart_animation) {
- // Cancel the animation
- // The 'finish' function in the Effect object will remove the reference
- el._highchart_animation[key].cancel();
- }
- }
- },
- // um.. each
- each: function (arr, fn) {
- $A(arr).each(fn);
- },
-
- inArray: function (item, arr, from) {
- return arr ? arr.indexOf(item, from) : -1;
- },
- /**
- * Get the cumulative offset relative to the top left of the page. This method, unlike its
- * jQuery and MooTools counterpart, still suffers from issue #208 regarding the position
- * of a chart within a fixed container.
- */
- offset: function (el) {
- return $(el).cumulativeOffset();
- },
- // fire an event based on an event name (event) and an object (el).
- // again, el may not be a dom element
- fireEvent: function (el, event, eventArguments, defaultFunction) {
- if (el.fire) {
- el.fire(HighchartsAdapter.addNS(event), eventArguments);
- } else if (el._highcharts_extended) {
- eventArguments = eventArguments || {};
- el._highcharts_fire(event, eventArguments);
- }
- if (eventArguments && eventArguments.defaultPrevented) {
- defaultFunction = null;
- }
- if (defaultFunction) {
- defaultFunction(eventArguments);
- }
- },
- removeEvent: function (el, event, handler) {
- if ($(el).stopObserving) {
- if (event) {
- event = HighchartsAdapter.addNS(event);
- }
- $(el).stopObserving(event, handler);
- } if (window === el) {
- Event.stopObserving(el, event, handler);
- } else {
- HighchartsAdapter._extend(el);
- el._highcharts_stop_observing(event, handler);
- }
- },
-
- washMouseEvent: function (e) {
- return e;
- },
- // um, grep
- grep: function (arr, fn) {
- return arr.findAll(fn);
- },
- // um, map
- map: function (arr, fn) {
- return arr.map(fn);
- },
- // extend an object to handle highchart events (highchart objects, not svg elements).
- // this is a very simple way of handling events but whatever, it works (i think)
- _extend: function (object) {
- if (!object._highcharts_extended) {
- Object.extend(object, {
- _highchart_events: {},
- _highchart_animation: null,
- _highcharts_extended: true,
- _highcharts_observe: function (name, fn) {
- this._highchart_events[name] = [this._highchart_events[name], fn].compact().flatten();
- },
- _highcharts_stop_observing: function (name, fn) {
- if (name) {
- if (fn) {
- this._highchart_events[name] = [this._highchart_events[name]].compact().flatten().without(fn);
- } else {
- delete this._highchart_events[name];
- }
- } else {
- this._highchart_events = {};
- }
- },
- _highcharts_fire: function (name, args) {
- var target = this;
- (this._highchart_events[name] || []).each(function (fn) {
- // args is never null here
- if (args.stopped) {
- return; // "throw $break" wasn't working. i think because of the scope of 'this'.
- }
- // Attach a simple preventDefault function to skip default handler if called
- args.preventDefault = function () {
- args.defaultPrevented = true;
- };
- args.target = target;
- // If the event handler return false, prevent the default handler from executing
- if (fn.bind(this)(args) === false) {
- args.preventDefault();
- }
- }
- .bind(this));
- }
- });
- }
- }
- };
- }());
|