Files
Chart.js/src/core/core.plugin.js
Simon Brunel 3187a788e1 Add support for local plugins and plugin options
Plugins can now be declared in the chart `config.plugins` array and will only be applied to the associated chart(s), after the globally registered plugins. Plugin specific options are now scoped under the `config.options.plugins` options. Hooks now receive the chart instance as first argument and the plugin options as last argument.
2016-12-18 08:46:15 -05:00

200 lines
4.6 KiB
JavaScript

'use strict';
module.exports = function(Chart) {
var helpers = Chart.helpers;
var noop = helpers.noop;
Chart.defaults.global.plugins = {};
/**
* The plugin service singleton
* @namespace Chart.plugins
* @since 2.1.0
*/
Chart.plugins = {
/**
* Globally registered plugins.
* @private
*/
_plugins: [],
/**
* This identifier is used to invalidate the descriptors cache attached to each chart
* when a global plugin is registered or unregistered. In this case, the cache ID is
* incremented and descriptors are regenerated during following API calls.
* @private
*/
_cacheId: 0,
/**
* Registers the given plugin(s) if not already registered.
* @param {Array|Object} plugins plugin instance(s).
*/
register: function(plugins) {
var p = this._plugins;
([]).concat(plugins).forEach(function(plugin) {
if (p.indexOf(plugin) === -1) {
p.push(plugin);
}
});
this._cacheId++;
},
/**
* Unregisters the given plugin(s) only if registered.
* @param {Array|Object} plugins plugin instance(s).
*/
unregister: function(plugins) {
var p = this._plugins;
([]).concat(plugins).forEach(function(plugin) {
var idx = p.indexOf(plugin);
if (idx !== -1) {
p.splice(idx, 1);
}
});
this._cacheId++;
},
/**
* Remove all registered plugins.
* @since 2.1.5
*/
clear: function() {
this._plugins = [];
this._cacheId++;
},
/**
* Returns the number of registered plugins?
* @returns {Number}
* @since 2.1.5
*/
count: function() {
return this._plugins.length;
},
/**
* Returns all registered plugin instances.
* @returns {Array} array of plugin objects.
* @since 2.1.5
*/
getAll: function() {
return this._plugins;
},
/**
* Calls enabled plugins for chart, on the specified extension and with the given args.
* This method immediately returns as soon as a plugin explicitly returns false. The
* returned value can be used, for instance, to interrupt the current action.
* @param {Object} chart chart instance for which plugins should be called.
* @param {String} extension the name of the plugin method to call (e.g. 'beforeUpdate').
* @param {Array} [args] extra arguments to apply to the extension call.
* @returns {Boolean} false if any of the plugins return false, else returns true.
*/
notify: function(chart, extension, args) {
var descriptors = this.descriptors(chart);
var ilen = descriptors.length;
var i, descriptor, plugin, params, method;
for (i=0; i<ilen; ++i) {
descriptor = descriptors[i];
plugin = descriptor.plugin;
method = plugin[extension];
if (typeof method === 'function') {
params = [chart].concat(args || []);
params.push(descriptor.options);
if (method.apply(plugin, params) === false) {
return false;
}
}
}
return true;
},
/**
* Returns descriptors of enabled plugins for the given chart.
* @returns {Array} [{ plugin, options }]
* @private
*/
descriptors: function(chart) {
var cache = chart._plugins || (chart._plugins = {});
if (cache.id === this._cacheId) {
return cache.descriptors;
}
var plugins = [];
var descriptors = [];
var config = (chart && chart.config) || {};
var defaults = Chart.defaults.global.plugins;
var options = (config.options && config.options.plugins) || {};
this._plugins.concat(config.plugins || []).forEach(function(plugin) {
var idx = plugins.indexOf(plugin);
if (idx !== -1) {
return;
}
var id = plugin.id;
var opts = options[id];
if (opts === false) {
return;
}
if (opts === true) {
opts = helpers.clone(defaults[id]);
}
plugins.push(plugin);
descriptors.push({
plugin: plugin,
options: opts || {}
});
});
cache.descriptors = descriptors;
cache.id = this._cacheId;
return descriptors;
}
};
/**
* Plugin extension methods.
* @interface Chart.PluginBase
* @since 2.1.0
*/
Chart.PluginBase = helpers.inherits({
// Called at start of chart init
beforeInit: noop,
// Called at end of chart init
afterInit: noop,
// Called at start of update
beforeUpdate: noop,
// Called at end of update
afterUpdate: noop,
// Called at start of draw
beforeDraw: noop,
// Called at end of draw
afterDraw: noop,
// Called during destroy
destroy: noop
});
/**
* Provided for backward compatibility, use Chart.plugins instead
* @namespace Chart.pluginService
* @deprecated since version 2.1.5
* TODO remove me at version 3
*/
Chart.pluginService = Chart.plugins;
};