|
1 YUI.add('pluginhost-base', function (Y, NAME) { |
|
2 |
|
3 /** |
|
4 * Provides the augmentable PluginHost interface, which can be added to any class. |
|
5 * @module pluginhost |
|
6 */ |
|
7 |
|
8 /** |
|
9 * Provides the augmentable PluginHost interface, which can be added to any class. |
|
10 * @module pluginhost-base |
|
11 */ |
|
12 |
|
13 /** |
|
14 * <p> |
|
15 * An augmentable class, which provides the augmented class with the ability to host plugins. |
|
16 * It adds <a href="#method_plug">plug</a> and <a href="#method_unplug">unplug</a> methods to the augmented class, which can |
|
17 * be used to add or remove plugins from instances of the class. |
|
18 * </p> |
|
19 * |
|
20 * <p>Plugins can also be added through the constructor configuration object passed to the host class' constructor using |
|
21 * the "plugins" property. Supported values for the "plugins" property are those defined by the <a href="#method_plug">plug</a> method. |
|
22 * |
|
23 * For example the following code would add the AnimPlugin and IOPlugin to Overlay (the plugin host): |
|
24 * <xmp> |
|
25 * var o = new Overlay({plugins: [ AnimPlugin, {fn:IOPlugin, cfg:{section:"header"}}]}); |
|
26 * </xmp> |
|
27 * </p> |
|
28 * <p> |
|
29 * Plug.Host's protected <a href="#method_initPlugins">_initPlugins</a> and <a href="#method_destroyPlugins">_destroyPlugins</a> |
|
30 * methods should be invoked by the host class at the appropriate point in the host's lifecyle. |
|
31 * </p> |
|
32 * |
|
33 * @class Plugin.Host |
|
34 */ |
|
35 |
|
36 var L = Y.Lang; |
|
37 |
|
38 function PluginHost() { |
|
39 this._plugins = {}; |
|
40 } |
|
41 |
|
42 PluginHost.prototype = { |
|
43 |
|
44 /** |
|
45 * Adds a plugin to the host object. This will instantiate the |
|
46 * plugin and attach it to the configured namespace on the host object. |
|
47 * |
|
48 * @method plug |
|
49 * @chainable |
|
50 * @param P {Function | Object |Array} Accepts the plugin class, or an |
|
51 * object with a "fn" property specifying the plugin class and |
|
52 * a "cfg" property specifying the configuration for the Plugin. |
|
53 * <p> |
|
54 * Additionally an Array can also be passed in, with the above function or |
|
55 * object values, allowing the user to add multiple plugins in a single call. |
|
56 * </p> |
|
57 * @param config (Optional) If the first argument is the plugin class, the second argument |
|
58 * can be the configuration for the plugin. |
|
59 * @return {Base} A reference to the host object |
|
60 */ |
|
61 plug: function(Plugin, config) { |
|
62 var i, ln, ns; |
|
63 |
|
64 if (L.isArray(Plugin)) { |
|
65 for (i = 0, ln = Plugin.length; i < ln; i++) { |
|
66 this.plug(Plugin[i]); |
|
67 } |
|
68 } else { |
|
69 if (Plugin && !L.isFunction(Plugin)) { |
|
70 config = Plugin.cfg; |
|
71 Plugin = Plugin.fn; |
|
72 } |
|
73 |
|
74 // Plugin should be fn by now |
|
75 if (Plugin && Plugin.NS) { |
|
76 ns = Plugin.NS; |
|
77 |
|
78 config = config || {}; |
|
79 config.host = this; |
|
80 |
|
81 if (this.hasPlugin(ns)) { |
|
82 // Update config |
|
83 if (this[ns].setAttrs) { |
|
84 this[ns].setAttrs(config); |
|
85 } |
|
86 else { Y.log("Attempt to replug an already attached plugin, and we can't setAttrs, because it's not Attribute based: " + ns); } |
|
87 } else { |
|
88 // Create new instance |
|
89 this[ns] = new Plugin(config); |
|
90 this._plugins[ns] = Plugin; |
|
91 } |
|
92 } |
|
93 else { Y.log("Attempt to plug in an invalid plugin. Host:" + this + ", Plugin:" + Plugin); } |
|
94 } |
|
95 return this; |
|
96 }, |
|
97 |
|
98 /** |
|
99 * Removes a plugin from the host object. This will destroy the |
|
100 * plugin instance and delete the namespace from the host object. |
|
101 * |
|
102 * @method unplug |
|
103 * @param {String | Function} plugin The namespace of the plugin, or the plugin class with the static NS namespace property defined. If not provided, |
|
104 * all registered plugins are unplugged. |
|
105 * @return {Base} A reference to the host object |
|
106 * @chainable |
|
107 */ |
|
108 unplug: function(plugin) { |
|
109 var ns = plugin, |
|
110 plugins = this._plugins; |
|
111 |
|
112 if (plugin) { |
|
113 if (L.isFunction(plugin)) { |
|
114 ns = plugin.NS; |
|
115 if (ns && (!plugins[ns] || plugins[ns] !== plugin)) { |
|
116 ns = null; |
|
117 } |
|
118 } |
|
119 |
|
120 if (ns) { |
|
121 if (this[ns]) { |
|
122 if (this[ns].destroy) { |
|
123 this[ns].destroy(); |
|
124 } |
|
125 delete this[ns]; |
|
126 } |
|
127 if (plugins[ns]) { |
|
128 delete plugins[ns]; |
|
129 } |
|
130 } |
|
131 } else { |
|
132 for (ns in this._plugins) { |
|
133 if (this._plugins.hasOwnProperty(ns)) { |
|
134 this.unplug(ns); |
|
135 } |
|
136 } |
|
137 } |
|
138 return this; |
|
139 }, |
|
140 |
|
141 /** |
|
142 * Determines if a plugin has plugged into this host. |
|
143 * |
|
144 * @method hasPlugin |
|
145 * @param {String} ns The plugin's namespace |
|
146 * @return {Plugin} Returns a truthy value (the plugin instance) if present, or undefined if not. |
|
147 */ |
|
148 hasPlugin : function(ns) { |
|
149 return (this._plugins[ns] && this[ns]); |
|
150 }, |
|
151 |
|
152 /** |
|
153 * Initializes static plugins registered on the host (using the |
|
154 * Base.plug static method) and any plugins passed to the |
|
155 * instance through the "plugins" configuration property. |
|
156 * |
|
157 * @method _initPlugins |
|
158 * @param {Object} config The configuration object with property name/value pairs. |
|
159 * @private |
|
160 */ |
|
161 |
|
162 _initPlugins: function(config) { |
|
163 this._plugins = this._plugins || {}; |
|
164 |
|
165 if (this._initConfigPlugins) { |
|
166 this._initConfigPlugins(config); |
|
167 } |
|
168 }, |
|
169 |
|
170 /** |
|
171 * Unplugs and destroys all plugins on the host |
|
172 * @method _destroyPlugins |
|
173 * @private |
|
174 */ |
|
175 _destroyPlugins: function() { |
|
176 this.unplug(); |
|
177 } |
|
178 }; |
|
179 |
|
180 Y.namespace("Plugin").Host = PluginHost; |
|
181 |
|
182 |
|
183 }, '@VERSION@', {"requires": ["yui-base"]}); |