+/**
+ * Chart.Platform implementation for targeting a web browser
+ */
+
'use strict';
var helpers = require('../helpers/index');
-// Chart.Platform implementation for targeting a web browser
-module.exports = function() {
-
- // DOM event types -> Chart.js event types.
- // Note: only events with different types are mapped.
- // https://developer.mozilla.org/en-US/docs/Web/Events
- var eventTypeMap = {
- // Touch events
- touchstart: 'mousedown',
- touchmove: 'mousemove',
- touchend: 'mouseup',
-
- // Pointer events
- pointerenter: 'mouseenter',
- pointerdown: 'mousedown',
- pointermove: 'mousemove',
- pointerup: 'mouseup',
- pointerleave: 'mouseout',
- pointerout: 'mouseout'
- };
-
- /**
- * The "used" size is the final value of a dimension property after all calculations have
- * been performed. This method uses the computed style of `element` but returns undefined
- * if the computed style is not expressed in pixels. That can happen in some cases where
- * `element` has a size relative to its parent and this last one is not yet displayed,
- * for example because of `display: none` on a parent node.
- * @see https://developer.mozilla.org/en-US/docs/Web/CSS/used_value
- * @returns {Number} Size in pixels or undefined if unknown.
- */
- function readUsedSize(element, property) {
- var value = helpers.getStyle(element, property);
- var matches = value && value.match(/^(\d+)(\.\d+)?px$/);
- return matches? Number(matches[1]) : undefined;
- }
+/**
+ * DOM event types -> Chart.js event types.
+ * Note: only events with different types are mapped.
+ * @see https://developer.mozilla.org/en-US/docs/Web/Events
+ */
+
+var eventTypeMap = {
+ // Touch events
+ touchstart: 'mousedown',
+ touchmove: 'mousemove',
+ touchend: 'mouseup',
+
+ // Pointer events
+ pointerenter: 'mouseenter',
+ pointerdown: 'mousedown',
+ pointermove: 'mousemove',
+ pointerup: 'mouseup',
+ pointerleave: 'mouseout',
+ pointerout: 'mouseout'
+};
- /**
- * Initializes the canvas style and render size without modifying the canvas display size,
- * since responsiveness is handled by the controller.resize() method. The config is used
- * to determine the aspect ratio to apply in case no explicit height has been specified.
- */
- function initCanvas(canvas, config) {
- var style = canvas.style;
-
- // NOTE(SB) canvas.getAttribute('width') !== canvas.width: in the first case it
- // returns null or '' if no explicit value has been set to the canvas attribute.
- var renderHeight = canvas.getAttribute('height');
- var renderWidth = canvas.getAttribute('width');
-
- // Chart.js modifies some canvas values that we want to restore on destroy
- canvas._chartjs = {
- initial: {
- height: renderHeight,
- width: renderWidth,
- style: {
- display: style.display,
- height: style.height,
- width: style.width
- }
+/**
+ * The "used" size is the final value of a dimension property after all calculations have
+ * been performed. This method uses the computed style of `element` but returns undefined
+ * if the computed style is not expressed in pixels. That can happen in some cases where
+ * `element` has a size relative to its parent and this last one is not yet displayed,
+ * for example because of `display: none` on a parent node.
+ * @see https://developer.mozilla.org/en-US/docs/Web/CSS/used_value
+ * @returns {Number} Size in pixels or undefined if unknown.
+ */
+function readUsedSize(element, property) {
+ var value = helpers.getStyle(element, property);
+ var matches = value && value.match(/^(\d+)(\.\d+)?px$/);
+ return matches? Number(matches[1]) : undefined;
+}
+
+/**
+ * Initializes the canvas style and render size without modifying the canvas display size,
+ * since responsiveness is handled by the controller.resize() method. The config is used
+ * to determine the aspect ratio to apply in case no explicit height has been specified.
+ */
+function initCanvas(canvas, config) {
+ var style = canvas.style;
+
+ // NOTE(SB) canvas.getAttribute('width') !== canvas.width: in the first case it
+ // returns null or '' if no explicit value has been set to the canvas attribute.
+ var renderHeight = canvas.getAttribute('height');
+ var renderWidth = canvas.getAttribute('width');
+
+ // Chart.js modifies some canvas values that we want to restore on destroy
+ canvas._chartjs = {
+ initial: {
+ height: renderHeight,
+ width: renderWidth,
+ style: {
+ display: style.display,
+ height: style.height,
+ width: style.width
}
- };
+ }
+ };
- // Force canvas to display as block to avoid extra space caused by inline
- // elements, which would interfere with the responsive resize process.
- // https://github.com/chartjs/Chart.js/issues/2538
- style.display = style.display || 'block';
+ // Force canvas to display as block to avoid extra space caused by inline
+ // elements, which would interfere with the responsive resize process.
+ // https://github.com/chartjs/Chart.js/issues/2538
+ style.display = style.display || 'block';
- if (renderWidth === null || renderWidth === '') {
- var displayWidth = readUsedSize(canvas, 'width');
- if (displayWidth !== undefined) {
- canvas.width = displayWidth;
- }
+ if (renderWidth === null || renderWidth === '') {
+ var displayWidth = readUsedSize(canvas, 'width');
+ if (displayWidth !== undefined) {
+ canvas.width = displayWidth;
}
+ }
- if (renderHeight === null || renderHeight === '') {
- if (canvas.style.height === '') {
- // If no explicit render height and style height, let's apply the aspect ratio,
- // which one can be specified by the user but also by charts as default option
- // (i.e. options.aspectRatio). If not specified, use canvas aspect ratio of 2.
- canvas.height = canvas.width / (config.options.aspectRatio || 2);
- } else {
- var displayHeight = readUsedSize(canvas, 'height');
- if (displayWidth !== undefined) {
- canvas.height = displayHeight;
- }
+ if (renderHeight === null || renderHeight === '') {
+ if (canvas.style.height === '') {
+ // If no explicit render height and style height, let's apply the aspect ratio,
+ // which one can be specified by the user but also by charts as default option
+ // (i.e. options.aspectRatio). If not specified, use canvas aspect ratio of 2.
+ canvas.height = canvas.width / (config.options.aspectRatio || 2);
+ } else {
+ var displayHeight = readUsedSize(canvas, 'height');
+ if (displayWidth !== undefined) {
+ canvas.height = displayHeight;
}
}
-
- return canvas;
}
- /**
- * Detects support for options object argument in addEventListener.
- * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support
- * @private
- */
- var supportsEventListenerOptions = (function() {
- var supports = false;
- try {
- var options = Object.defineProperty({}, 'passive', {
- get: function() {
- supports = true;
- }
- });
- window.addEventListener('e', null, options);
- } catch (e) {
- // continue regardless of error
- }
- return supports;
- }());
-
- // Default passive to true as expected by Chrome for 'touchstart' and 'touchend' events.
- // https://github.com/chartjs/Chart.js/issues/4287
- var eventListenerOptions = supportsEventListenerOptions? {passive: true} : false;
-
- function addEventListener(node, type, listener) {
- node.addEventListener(type, listener, eventListenerOptions);
+ return canvas;
+}
+
+/**
+ * Detects support for options object argument in addEventListener.
+ * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support
+ * @private
+ */
+var supportsEventListenerOptions = (function() {
+ var supports = false;
+ try {
+ var options = Object.defineProperty({}, 'passive', {
+ get: function() {
+ supports = true;
+ }
+ });
+ window.addEventListener('e', null, options);
+ } catch (e) {
+ // continue regardless of error
}
+ return supports;
+}());
- function removeEventListener(node, type, listener) {
- node.removeEventListener(type, listener, eventListenerOptions);
- }
+// Default passive to true as expected by Chrome for 'touchstart' and 'touchend' events.
+// https://github.com/chartjs/Chart.js/issues/4287
+var eventListenerOptions = supportsEventListenerOptions? {passive: true} : false;
- function createEvent(type, chart, x, y, nativeEvent) {
- return {
- type: type,
- chart: chart,
- native: nativeEvent || null,
- x: x !== undefined? x : null,
- y: y !== undefined? y : null,
- };
- }
+function addEventListener(node, type, listener) {
+ node.addEventListener(type, listener, eventListenerOptions);
+}
- function fromNativeEvent(event, chart) {
- var type = eventTypeMap[event.type] || event.type;
- var pos = helpers.getRelativePosition(event, chart);
- return createEvent(type, chart, pos.x, pos.y, event);
- }
+function removeEventListener(node, type, listener) {
+ node.removeEventListener(type, listener, eventListenerOptions);
+}
- function createResizer(handler) {
- var iframe = document.createElement('iframe');
- iframe.className = 'chartjs-hidden-iframe';
- iframe.style.cssText =
- 'display:block;'+
- 'overflow:hidden;'+
- 'border:0;'+
- 'margin:0;'+
- 'top:0;'+
- 'left:0;'+
- 'bottom:0;'+
- 'right:0;'+
- 'height:100%;'+
- 'width:100%;'+
- 'position:absolute;'+
- 'pointer-events:none;'+
- 'z-index:-1;';
-
- // Prevent the iframe to gain focus on tab.
- // https://github.com/chartjs/Chart.js/issues/3090
- iframe.tabIndex = -1;
-
- // Prevent iframe from gaining focus on ItemMode keyboard navigation
- // Accessibility bug fix
- iframe.setAttribute('aria-hidden', 'true');
-
- // If the iframe is re-attached to the DOM, the resize listener is removed because the
- // content is reloaded, so make sure to install the handler after the iframe is loaded.
- // https://github.com/chartjs/Chart.js/issues/3521
- addEventListener(iframe, 'load', function() {
- addEventListener(iframe.contentWindow || iframe, 'resize', handler);
-
- // The iframe size might have changed while loading, which can also
- // happen if the size has been changed while detached from the DOM.
- handler();
- });
+function createEvent(type, chart, x, y, nativeEvent) {
+ return {
+ type: type,
+ chart: chart,
+ native: nativeEvent || null,
+ x: x !== undefined? x : null,
+ y: y !== undefined? y : null,
+ };
+}
+
+function fromNativeEvent(event, chart) {
+ var type = eventTypeMap[event.type] || event.type;
+ var pos = helpers.getRelativePosition(event, chart);
+ return createEvent(type, chart, pos.x, pos.y, event);
+}
+
+function createResizer(handler) {
+ var iframe = document.createElement('iframe');
+ iframe.className = 'chartjs-hidden-iframe';
+ iframe.style.cssText =
+ 'display:block;'+
+ 'overflow:hidden;'+
+ 'border:0;'+
+ 'margin:0;'+
+ 'top:0;'+
+ 'left:0;'+
+ 'bottom:0;'+
+ 'right:0;'+
+ 'height:100%;'+
+ 'width:100%;'+
+ 'position:absolute;'+
+ 'pointer-events:none;'+
+ 'z-index:-1;';
+
+ // Prevent the iframe to gain focus on tab.
+ // https://github.com/chartjs/Chart.js/issues/3090
+ iframe.tabIndex = -1;
+
+ // Prevent iframe from gaining focus on ItemMode keyboard navigation
+ // Accessibility bug fix
+ iframe.setAttribute('aria-hidden', 'true');
+
+ // If the iframe is re-attached to the DOM, the resize listener is removed because the
+ // content is reloaded, so make sure to install the handler after the iframe is loaded.
+ // https://github.com/chartjs/Chart.js/issues/3521
+ addEventListener(iframe, 'load', function() {
+ addEventListener(iframe.contentWindow || iframe, 'resize', handler);
+
+ // The iframe size might have changed while loading, which can also
+ // happen if the size has been changed while detached from the DOM.
+ handler();
+ });
+
+ return iframe;
+}
+
+function addResizeListener(node, listener, chart) {
+ var stub = node._chartjs = {
+ ticking: false
+ };
- return iframe;
- }
+ // Throttle the callback notification until the next animation frame.
+ var notify = function() {
+ if (!stub.ticking) {
+ stub.ticking = true;
+ helpers.requestAnimFrame.call(window, function() {
+ if (stub.resizer) {
+ stub.ticking = false;
+ return listener(createEvent('resize', chart));
+ }
+ });
+ }
+ };
- function addResizeListener(node, listener, chart) {
- var stub = node._chartjs = {
- ticking: false
- };
+ // Let's keep track of this added iframe and thus avoid DOM query when removing it.
+ stub.resizer = createResizer(notify);
- // Throttle the callback notification until the next animation frame.
- var notify = function() {
- if (!stub.ticking) {
- stub.ticking = true;
- helpers.requestAnimFrame.call(window, function() {
- if (stub.resizer) {
- stub.ticking = false;
- return listener(createEvent('resize', chart));
- }
- });
- }
- };
+ node.insertBefore(stub.resizer, node.firstChild);
+}
- // Let's keep track of this added iframe and thus avoid DOM query when removing it.
- stub.resizer = createResizer(notify);
+function removeResizeListener(node) {
+ if (!node || !node._chartjs) {
+ return;
+ }
- node.insertBefore(stub.resizer, node.firstChild);
+ var resizer = node._chartjs.resizer;
+ if (resizer) {
+ resizer.parentNode.removeChild(resizer);
+ node._chartjs.resizer = null;
}
- function removeResizeListener(node) {
- if (!node || !node._chartjs) {
- return;
+ delete node._chartjs;
+}
+
+module.exports = {
+ acquireContext: function(item, config) {
+ if (typeof item === 'string') {
+ item = document.getElementById(item);
+ } else if (item.length) {
+ // Support for array based queries (such as jQuery)
+ item = item[0];
}
- var resizer = node._chartjs.resizer;
- if (resizer) {
- resizer.parentNode.removeChild(resizer);
- node._chartjs.resizer = null;
+ if (item && item.canvas) {
+ // Support for any object associated to a canvas (including a context2d)
+ item = item.canvas;
}
- delete node._chartjs;
- }
+ // To prevent canvas fingerprinting, some add-ons undefine the getContext
+ // method, for example: https://github.com/kkapsner/CanvasBlocker
+ // https://github.com/chartjs/Chart.js/issues/2807
+ var context = item && item.getContext && item.getContext('2d');
+
+ // `instanceof HTMLCanvasElement/CanvasRenderingContext2D` fails when the item is
+ // inside an iframe or when running in a protected environment. We could guess the
+ // types from their toString() value but let's keep things flexible and assume it's
+ // a sufficient condition if the item has a context2D which has item as `canvas`.
+ // https://github.com/chartjs/Chart.js/issues/3887
+ // https://github.com/chartjs/Chart.js/issues/4102
+ // https://github.com/chartjs/Chart.js/issues/4152
+ if (context && context.canvas === item) {
+ initCanvas(item, config);
+ return context;
+ }
- /**
- * Provided for backward compatibility, use EventTarget.addEventListener instead.
- * EventTarget.addEventListener compatibility: Chrome, Opera 7, Safari, FF1.5+, IE9+
- * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
- * @function Chart.helpers.addEvent
- * @deprecated since version 2.7.0
- * @todo remove at version 3
- * @private
- */
- helpers.addEvent = addEventListener;
-
- /**
- * Provided for backward compatibility, use EventTarget.removeEventListener instead.
- * EventTarget.removeEventListener compatibility: Chrome, Opera 7, Safari, FF1.5+, IE9+
- * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener
- * @function Chart.helpers.removeEvent
- * @deprecated since version 2.7.0
- * @todo remove at version 3
- * @private
- */
- helpers.removeEvent = removeEventListener;
+ return null;
+ },
- return {
- acquireContext: function(item, config) {
- if (typeof item === 'string') {
- item = document.getElementById(item);
- } else if (item.length) {
- // Support for array based queries (such as jQuery)
- item = item[0];
- }
+ releaseContext: function(context) {
+ var canvas = context.canvas;
+ if (!canvas._chartjs) {
+ return;
+ }
- if (item && item.canvas) {
- // Support for any object associated to a canvas (including a context2d)
- item = item.canvas;
+ var initial = canvas._chartjs.initial;
+ ['height', 'width'].forEach(function(prop) {
+ var value = initial[prop];
+ if (helpers.isNullOrUndef(value)) {
+ canvas.removeAttribute(prop);
+ } else {
+ canvas.setAttribute(prop, value);
}
+ });
- // To prevent canvas fingerprinting, some add-ons undefine the getContext
- // method, for example: https://github.com/kkapsner/CanvasBlocker
- // https://github.com/chartjs/Chart.js/issues/2807
- var context = item && item.getContext && item.getContext('2d');
-
- // `instanceof HTMLCanvasElement/CanvasRenderingContext2D` fails when the item is
- // inside an iframe or when running in a protected environment. We could guess the
- // types from their toString() value but let's keep things flexible and assume it's
- // a sufficient condition if the item has a context2D which has item as `canvas`.
- // https://github.com/chartjs/Chart.js/issues/3887
- // https://github.com/chartjs/Chart.js/issues/4102
- // https://github.com/chartjs/Chart.js/issues/4152
- if (context && context.canvas === item) {
- initCanvas(item, config);
- return context;
- }
+ helpers.each(initial.style || {}, function(value, key) {
+ canvas.style[key] = value;
+ });
- return null;
- },
+ // The canvas render size might have been changed (and thus the state stack discarded),
+ // we can't use save() and restore() to restore the initial state. So make sure that at
+ // least the canvas context is reset to the default state by setting the canvas width.
+ // https://www.w3.org/TR/2011/WD-html5-20110525/the-canvas-element.html
+ canvas.width = canvas.width;
- releaseContext: function(context) {
- var canvas = context.canvas;
- if (!canvas._chartjs) {
- return;
- }
+ delete canvas._chartjs;
+ },
- var initial = canvas._chartjs.initial;
- ['height', 'width'].forEach(function(prop) {
- var value = initial[prop];
- if (helpers.isNullOrUndef(value)) {
- canvas.removeAttribute(prop);
- } else {
- canvas.setAttribute(prop, value);
- }
- });
-
- helpers.each(initial.style || {}, function(value, key) {
- canvas.style[key] = value;
- });
+ addEventListener: function(chart, type, listener) {
+ var canvas = chart.canvas;
+ if (type === 'resize') {
+ // Note: the resize event is not supported on all browsers.
+ addResizeListener(canvas.parentNode, listener, chart);
+ return;
+ }
- // The canvas render size might have been changed (and thus the state stack discarded),
- // we can't use save() and restore() to restore the initial state. So make sure that at
- // least the canvas context is reset to the default state by setting the canvas width.
- // https://www.w3.org/TR/2011/WD-html5-20110525/the-canvas-element.html
- canvas.width = canvas.width;
-
- delete canvas._chartjs;
- },
-
- addEventListener: function(chart, type, listener) {
- var canvas = chart.canvas;
- if (type === 'resize') {
- // Note: the resize event is not supported on all browsers.
- addResizeListener(canvas.parentNode, listener, chart);
- return;
- }
+ var stub = listener._chartjs || (listener._chartjs = {});
+ var proxies = stub.proxies || (stub.proxies = {});
+ var proxy = proxies[chart.id + '_' + type] = function(event) {
+ listener(fromNativeEvent(event, chart));
+ };
- var stub = listener._chartjs || (listener._chartjs = {});
- var proxies = stub.proxies || (stub.proxies = {});
- var proxy = proxies[chart.id + '_' + type] = function(event) {
- listener(fromNativeEvent(event, chart));
- };
-
- addEventListener(canvas, type, proxy);
- },
-
- removeEventListener: function(chart, type, listener) {
- var canvas = chart.canvas;
- if (type === 'resize') {
- // Note: the resize event is not supported on all browsers.
- removeResizeListener(canvas.parentNode, listener);
- return;
- }
+ addEventListener(canvas, type, proxy);
+ },
- var stub = listener._chartjs || {};
- var proxies = stub.proxies || {};
- var proxy = proxies[chart.id + '_' + type];
- if (!proxy) {
- return;
- }
+ removeEventListener: function(chart, type, listener) {
+ var canvas = chart.canvas;
+ if (type === 'resize') {
+ // Note: the resize event is not supported on all browsers.
+ removeResizeListener(canvas.parentNode, listener);
+ return;
+ }
- removeEventListener(canvas, type, proxy);
+ var stub = listener._chartjs || {};
+ var proxies = stub.proxies || {};
+ var proxy = proxies[chart.id + '_' + type];
+ if (!proxy) {
+ return;
}
- };
+
+ removeEventListener(canvas, type, proxy);
+ }
};
+
+// DEPRECATIONS
+
+/**
+ * Provided for backward compatibility, use EventTarget.addEventListener instead.
+ * EventTarget.addEventListener compatibility: Chrome, Opera 7, Safari, FF1.5+, IE9+
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
+ * @function Chart.helpers.addEvent
+ * @deprecated since version 2.7.0
+ * @todo remove at version 3
+ * @private
+ */
+helpers.addEvent = addEventListener;
+
+/**
+ * Provided for backward compatibility, use EventTarget.removeEventListener instead.
+ * EventTarget.removeEventListener compatibility: Chrome, Opera 7, Safari, FF1.5+, IE9+
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener
+ * @function Chart.helpers.removeEvent
+ * @deprecated since version 2.7.0
+ * @todo remove at version 3
+ * @private
+ */
+helpers.removeEvent = removeEventListener;
// @TODO Make possible to select another platform at build time.
var implementation = require('./platform.dom');
-module.exports = function(Chart) {
+/**
+ * @namespace Chart.platform
+ * @see https://chartjs.gitbooks.io/proposals/content/Platform.html
+ * @since 2.4.0
+ */
+module.exports = helpers.extend({
/**
- * @namespace Chart.platform
- * @see https://chartjs.gitbooks.io/proposals/content/Platform.html
- * @since 2.4.0
+ * Called at chart construction time, returns a context2d instance implementing
+ * the [W3C Canvas 2D Context API standard]{@link https://www.w3.org/TR/2dcontext/}.
+ * @param {*} item - The native item from which to acquire context (platform specific)
+ * @param {Object} options - The chart options
+ * @returns {CanvasRenderingContext2D} context2d instance
*/
- Chart.platform = {
- /**
- * Called at chart construction time, returns a context2d instance implementing
- * the [W3C Canvas 2D Context API standard]{@link https://www.w3.org/TR/2dcontext/}.
- * @param {*} item - The native item from which to acquire context (platform specific)
- * @param {Object} options - The chart options
- * @returns {CanvasRenderingContext2D} context2d instance
- */
- acquireContext: function() {},
+ acquireContext: function() {},
- /**
- * Called at chart destruction time, releases any resources associated to the context
- * previously returned by the acquireContext() method.
- * @param {CanvasRenderingContext2D} context - The context2d instance
- * @returns {Boolean} true if the method succeeded, else false
- */
- releaseContext: function() {},
-
- /**
- * Registers the specified listener on the given chart.
- * @param {Chart} chart - Chart from which to listen for event
- * @param {String} type - The ({@link IEvent}) type to listen for
- * @param {Function} listener - Receives a notification (an object that implements
- * the {@link IEvent} interface) when an event of the specified type occurs.
- */
- addEventListener: function() {},
-
- /**
- * Removes the specified listener previously registered with addEventListener.
- * @param {Chart} chart -Chart from which to remove the listener
- * @param {String} type - The ({@link IEvent}) type to remove
- * @param {Function} listener - The listener function to remove from the event target.
- */
- removeEventListener: function() {}
- };
+ /**
+ * Called at chart destruction time, releases any resources associated to the context
+ * previously returned by the acquireContext() method.
+ * @param {CanvasRenderingContext2D} context - The context2d instance
+ * @returns {Boolean} true if the method succeeded, else false
+ */
+ releaseContext: function() {},
/**
- * @interface IPlatform
- * Allows abstracting platform dependencies away from the chart
- * @borrows Chart.platform.acquireContext as acquireContext
- * @borrows Chart.platform.releaseContext as releaseContext
- * @borrows Chart.platform.addEventListener as addEventListener
- * @borrows Chart.platform.removeEventListener as removeEventListener
+ * Registers the specified listener on the given chart.
+ * @param {Chart} chart - Chart from which to listen for event
+ * @param {String} type - The ({@link IEvent}) type to listen for
+ * @param {Function} listener - Receives a notification (an object that implements
+ * the {@link IEvent} interface) when an event of the specified type occurs.
*/
+ addEventListener: function() {},
/**
- * @interface IEvent
- * @prop {String} type - The event type name, possible values are:
- * 'contextmenu', 'mouseenter', 'mousedown', 'mousemove', 'mouseup', 'mouseout',
- * 'click', 'dblclick', 'keydown', 'keypress', 'keyup' and 'resize'
- * @prop {*} native - The original native event (null for emulated events, e.g. 'resize')
- * @prop {Number} x - The mouse x position, relative to the canvas (null for incompatible events)
- * @prop {Number} y - The mouse y position, relative to the canvas (null for incompatible events)
+ * Removes the specified listener previously registered with addEventListener.
+ * @param {Chart} chart -Chart from which to remove the listener
+ * @param {String} type - The ({@link IEvent}) type to remove
+ * @param {Function} listener - The listener function to remove from the event target.
*/
+ removeEventListener: function() {}
+
+}, implementation);
+
+/**
+ * @interface IPlatform
+ * Allows abstracting platform dependencies away from the chart
+ * @borrows Chart.platform.acquireContext as acquireContext
+ * @borrows Chart.platform.releaseContext as releaseContext
+ * @borrows Chart.platform.addEventListener as addEventListener
+ * @borrows Chart.platform.removeEventListener as removeEventListener
+ */
- helpers.extend(Chart.platform, implementation(Chart));
-};
+/**
+ * @interface IEvent
+ * @prop {String} type - The event type name, possible values are:
+ * 'contextmenu', 'mouseenter', 'mousedown', 'mousemove', 'mouseup', 'mouseout',
+ * 'click', 'dblclick', 'keydown', 'keypress', 'keyup' and 'resize'
+ * @prop {*} native - The original native event (null for emulated events, e.g. 'resize')
+ * @prop {Number} x - The mouse x position, relative to the canvas (null for incompatible events)
+ * @prop {Number} y - The mouse y position, relative to the canvas (null for incompatible events)
+ */