57775f39a19dc392e5882d5217d5a9148688aa4aMatt SweeneyYUI.add('plugin', function(Y) {
57775f39a19dc392e5882d5217d5a9148688aa4aMatt Sweeney
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai /**
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * Provides the base Plugin class, which plugin developers should extend, when creating custom plugins
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai *
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * @module plugin
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai */
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai /**
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * The base class for all Plugin instances.
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai *
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * @class Plugin.Base
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * @extends Base
eaa9719567e2ec55d96f9298077f5fc0effe1ed3Satyen Desai * @param {Object} config Configuration object with property name/value pairs.
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai */
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai function Plugin(config) {
86fa3fa071113dfe732100d1a15cb149f67ffc83Jenny Donnelly if (! (this.hasImpl && this.hasImpl(Y.Plugin.Base)) ) {
86fa3fa071113dfe732100d1a15cb149f67ffc83Jenny Donnelly Plugin.superclass.constructor.apply(this, arguments);
86fa3fa071113dfe732100d1a15cb149f67ffc83Jenny Donnelly } else {
86fa3fa071113dfe732100d1a15cb149f67ffc83Jenny Donnelly Plugin.prototype.initializer.apply(this, arguments);
86fa3fa071113dfe732100d1a15cb149f67ffc83Jenny Donnelly }
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai }
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai /**
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * Object defining the set of attributes supported by the Plugin.Base class
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai *
10d8bafc5c24f3a4285cf6060a1935ba5cfc4b85Luke Smith * @property ATTRS
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * @type Object
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * @static
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai */
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai Plugin.ATTRS = {
57775f39a19dc392e5882d5217d5a9148688aa4aMatt Sweeney
57775f39a19dc392e5882d5217d5a9148688aa4aMatt Sweeney /**
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * The plugin's host object.
feaab31990f7893c59257f33cd9f708a6c0e7ddbSatyen Desai *
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * @attribute host
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * @writeonce
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * @type Plugin.Host
57775f39a19dc392e5882d5217d5a9148688aa4aMatt Sweeney */
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai host : {
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai writeOnce: true
57775f39a19dc392e5882d5217d5a9148688aa4aMatt Sweeney }
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai };
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai /**
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * The string identifying the Plugin.Base class. Plugins extending
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * Plugin.Base should set their own NAME value.
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai *
10d8bafc5c24f3a4285cf6060a1935ba5cfc4b85Luke Smith * @property NAME
eaa9719567e2ec55d96f9298077f5fc0effe1ed3Satyen Desai * @type String
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * @static
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai */
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai Plugin.NAME = 'plugin';
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai /**
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * The name of the property the the plugin will be attached to
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * when plugged into a Plugin Host. Plugins extending Plugin.Base,
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * should set their own NS value.
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai *
10d8bafc5c24f3a4285cf6060a1935ba5cfc4b85Luke Smith * @property NS
eaa9719567e2ec55d96f9298077f5fc0effe1ed3Satyen Desai * @type String
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * @static
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai */
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai Plugin.NS = 'plugin';
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai Y.extend(Plugin, Y.Base, {
57775f39a19dc392e5882d5217d5a9148688aa4aMatt Sweeney
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai /**
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * The list of event handles for event listeners or AOP injected methods
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * applied by the plugin to the host object.
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai *
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * @property _handles
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * @private
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * @type Array
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * @value null
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai */
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai _handles: null,
1233f432158f66c7692b2d4a9ad206d6ca27e4b6Matt Sweeney
57775f39a19dc392e5882d5217d5a9148688aa4aMatt Sweeney /**
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * Initializer lifecycle implementation.
57775f39a19dc392e5882d5217d5a9148688aa4aMatt Sweeney *
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * @method initializer
eaa9719567e2ec55d96f9298077f5fc0effe1ed3Satyen Desai * @param {Object} config Configuration object with property name/value pairs.
57775f39a19dc392e5882d5217d5a9148688aa4aMatt Sweeney */
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai initializer : function(config) {
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai if (!this.get("host")) { Y.log('No host defined for plugin ' + this, 'warn', 'Plugin');}
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai this._handles = [];
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai Y.log('Initializing: ' + this.constructor.NAME, 'info', 'Plugin');
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai },
57775f39a19dc392e5882d5217d5a9148688aa4aMatt Sweeney
57775f39a19dc392e5882d5217d5a9148688aa4aMatt Sweeney /**
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * Destructor lifecycle implementation.
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai *
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * Removes any event listeners or injected methods applied by the Plugin
57775f39a19dc392e5882d5217d5a9148688aa4aMatt Sweeney *
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * @method destructor
57775f39a19dc392e5882d5217d5a9148688aa4aMatt Sweeney */
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai destructor: function() {
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai // remove all handles
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai if (this._handles) {
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai for (var i = 0, l = this._handles.length; i < l; i++) {
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai this._handles[i].detach();
57775f39a19dc392e5882d5217d5a9148688aa4aMatt Sweeney }
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai }
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai },
57775f39a19dc392e5882d5217d5a9148688aa4aMatt Sweeney
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai /**
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * Listens for the "on" moment of events fired by the host,
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * or injects code "before" a given method on the host.
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai *
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * @method doBefore
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai *
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * @param strMethod {String} The event to listen for, or method to inject logic before.
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * @param fn {Function} The handler function. For events, the "on" moment listener. For methods, the function to execute before the given method is executed.
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * @param context {Object} An optional context to call the handler with. The default context is the plugin instance.
982119a5f53b6531610b5d29c631550a6222da1fSatyen Desai * @return handle {EventHandle} The detach handle for the handler.
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai */
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai doBefore: function(strMethod, fn, context) {
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai var host = this.get("host"), handle;
57775f39a19dc392e5882d5217d5a9148688aa4aMatt Sweeney
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai if (strMethod in host) { // method
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai handle = this.beforeHostMethod(strMethod, fn, context);
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai } else if (host.on) { // event
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai handle = this.onHostEvent(strMethod, fn, context);
57775f39a19dc392e5882d5217d5a9148688aa4aMatt Sweeney }
57775f39a19dc392e5882d5217d5a9148688aa4aMatt Sweeney
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai return handle;
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai },
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai /**
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * Listens for the "after" moment of events fired by the host,
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * or injects code "after" a given method on the host.
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai *
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * @method doAfter
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai *
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * @param strMethod {String} The event to listen for, or method to inject logic after.
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * @param fn {Function} The handler function. For events, the "after" moment listener. For methods, the function to execute after the given method is executed.
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai * @param context {Object} An optional context to call the handler with. The default context is the plugin instance.
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * @return handle {EventHandle} The detach handle for the listener.
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai */
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai doAfter: function(strMethod, fn, context) {
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai var host = this.get("host"), handle;
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai if (strMethod in host) { // method
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai handle = this.afterHostMethod(strMethod, fn, context);
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai } else if (host.after) { // event
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai handle = this.afterHostEvent(strMethod, fn, context);
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai }
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai return handle;
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai },
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai /**
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * Listens for the "on" moment of events fired by the host object.
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai *
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * Listeners attached through this method will be detached when the plugin is unplugged.
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai *
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * @method onHostEvent
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * @param {String | Object} type The event type.
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * @param {Function} fn The listener.
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * @param {Object} context The execution context. Defaults to the plugin instance.
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * @return handle {EventHandle} The detach handle for the listener.
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai */
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai onHostEvent : function(type, fn, context) {
14039ac20172671b6c453a0b6571795429fbe3b3Satyen Desai var handle = this.get("host").on(type, fn, context || this);
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai this._handles.push(handle);
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai return handle;
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai },
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai /**
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * Listens for the "after" moment of events fired by the host object.
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai *
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * Listeners attached through this method will be detached when the plugin is unplugged.
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai *
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * @method afterHostEvent
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * @param {String | Object} type The event type.
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * @param {Function} fn The listener.
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * @param {Object} context The execution context. Defaults to the plugin instance.
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * @return handle {EventHandle} The detach handle for the listener.
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai */
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai afterHostEvent : function(type, fn, context) {
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai var handle = this.get("host").after(type, fn, context || this);
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai this._handles.push(handle);
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai return handle;
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai },
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai /**
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * Injects a function to be executed before a given method on host object.
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai *
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * The function will be detached when the plugin is unplugged.
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai *
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * @method beforeHostMethod
ca8fd8dbdf317ed1d8965afc7a2c7cc1ba9df034Luke Smith * @param {String} method The name of the method to inject the function before.
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * @param {Function} fn The function to inject.
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * @param {Object} context The execution context. Defaults to the plugin instance.
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * @return handle {EventHandle} The detach handle for the injected function.
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai */
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai beforeHostMethod : function(strMethod, fn, context) {
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai var handle = Y.Do.before(fn, this.get("host"), strMethod, context || this);
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai this._handles.push(handle);
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai return handle;
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai },
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai /**
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * Injects a function to be executed after a given method on host object.
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai *
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * The function will be detached when the plugin is unplugged.
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai *
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * @method afterHostMethod
ca8fd8dbdf317ed1d8965afc7a2c7cc1ba9df034Luke Smith * @param {String} method The name of the method to inject the function after.
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * @param {Function} fn The function to inject.
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * @param {Object} context The execution context. Defaults to the plugin instance.
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai * @return handle {EventHandle} The detach handle for the injected function.
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai */
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai afterHostMethod : function(strMethod, fn, context) {
75013e52e14f366e77d0a078bc1bfedfa421fe70Satyen Desai var handle = Y.Do.after(fn, this.get("host"), strMethod, context || this);
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai this._handles.push(handle);
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai return handle;
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai },
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai toString: function() {
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai return this.constructor.NAME + '[' + this.constructor.NS + ']';
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai }
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai });
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai
69ce664b1e66d48ae3ae5be08488f38b4855fc8bSatyen Desai Y.namespace("Plugin").Base = Plugin;
57775f39a19dc392e5882d5217d5a9148688aa4aMatt Sweeney
57775f39a19dc392e5882d5217d5a9148688aa4aMatt Sweeney
aca18adfbc860a76fb2e4bee2f2e1d3b89c52b1bSatyen Desai}, '@VERSION@' ,{requires:['base-base']});