Enhance plugin notification system

Change the plugin notification behavior: this method now returns false as soon as a plugin *explicitly* returns false, else returns true. Also, plugins are now called in their own scope (so remove the never used `scope` parameter).
This commit is contained in:
Simon Brunel 2016-06-10 22:26:55 +02:00
parent 7a419af4c2
commit a55c17d73f
2 changed files with 50 additions and 20 deletions

View File

@ -2,8 +2,7 @@
module.exports = function(Chart) { module.exports = function(Chart) {
var helpers = Chart.helpers; var noop = Chart.helpers.noop;
var noop = helpers.noop;
/** /**
* The plugin service singleton * The plugin service singleton
@ -30,21 +29,33 @@ module.exports = function(Chart) {
}, },
/** /**
* Calls registered plugins on the specified method, with the given args. This * Calls registered plugins on the specified extension, with the given args. This
* method immediately returns as soon as a plugin explicitly returns false. * 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 {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. * @returns {Boolean} false if any of the plugins return false, else returns true.
*/ */
notify: function(method, args, scope) { notify: function(extension, args) {
helpers.each(this._plugins, function(plugin) { var plugins = this._plugins;
if (plugin[method] && typeof plugin[method] === 'function') { var ilen = plugins.length;
plugin[method].apply(scope, args); var i, plugin;
for (i=0; i<ilen; ++i) {
plugin = plugins[i];
if (typeof plugin[extension] === 'function') {
if (plugin[extension].apply(plugin, args || []) === false) {
return false;
}
} }
}, scope); }
return true;
} }
}; };
Chart.PluginBase = Chart.Element.extend({ Chart.PluginBase = Chart.Element.extend({
// Plugin methods. All functions are passed the chart instance // Plugin extensions. All functions are passed the chart instance
// Called at start of chart init // Called at start of chart init
beforeInit: noop, beforeInit: noop,

View File

@ -37,17 +37,36 @@ describe('Test the plugin system', function() {
Chart.plugins.remove(myplugin); Chart.plugins.remove(myplugin);
}); });
it ('Should allow notifying plugins', function() { describe('Chart.plugins.notify', function() {
var myplugin = { it ('should call plugins with arguments', function() {
count: 0, var myplugin = {
trigger: function(chart) { count: 0,
myplugin.count = chart.count; trigger: function(chart) {
} myplugin.count = chart.count;
}; }
Chart.plugins.register(myplugin); };
Chart.plugins.notify('trigger', [{ count: 10 }]); Chart.plugins.register(myplugin);
Chart.plugins.notify('trigger', [{ count: 10 }]);
expect(myplugin.count).toBe(10);
});
expect(myplugin.count).toBe(10); it('should return TRUE if no plugin explicitly returns FALSE', function() {
Chart.plugins.register({ check: function() {} });
Chart.plugins.register({ check: function() { return; } });
Chart.plugins.register({ check: function() { return null; } });
Chart.plugins.register({ check: function() { return 42 } });
var res = Chart.plugins.notify('check');
expect(res).toBeTruthy();
});
it('should return FALSE if no plugin explicitly returns FALSE', function() {
Chart.plugins.register({ check: function() {} });
Chart.plugins.register({ check: function() { return; } });
Chart.plugins.register({ check: function() { return false; } });
Chart.plugins.register({ check: function() { return 42 } });
var res = Chart.plugins.notify('check');
expect(res).toBeFalsy();
});
}); });
}); });