-
-
Save lsmith/895834 to your computer and use it in GitHub Desktop.
Y.Plugin.addHostAttr = function (name, host, plugin) { | |
host.ATTRS[name] = { | |
setter: function (val) { | |
var config = isObject(val) ? val : {}, | |
method = (val) ? 'plug' : 'unplug', | |
widgetProto = Widget.prototype; | |
this[method](plugin, config); | |
if (val && (host.prototype === widgetProto || widgetProto.isPrototypeOf(host.prototype))) { | |
if (!host.HTML_PARSER) { | |
host.HTML_PARSER = {}; | |
} | |
host.HTML_PARSER[name] = function (bb) { | |
var cname = Y.ClassNameManager.getClassName(name); | |
return !!(bb.hasClass(cname) || | |
bb.one('.yui3-widget-content.' + cname)); | |
// Alternate approach would be to look for data-* attribute? | |
} | |
} | |
}, | |
... | |
}; | |
}; |
<div id="yconsole" class="yui3-draggable"> | |
... | |
</div> | |
<script> | |
/* what would appear in plugin-drag module */ | |
YUI.add('plugin-drag', function (Y) { | |
... | |
Y.Plugin.addHostAttr('draggable', Y.Widget, Y.Plugin.Drag); | |
}...); | |
/* then back in the implementation code */ | |
Y.use('console', 'plugin-drag', function () { | |
var yconsole = new Y.Console({ srcNode: '#yconsole' }); // boom, draggable Console | |
... | |
}); |
I think using a data-* attribute would at least be somewhat more specific, and still within HTML5 spec. Would hate for a classname collision or anything like that.
Does addHostAttr blow up any pre-existing attrs on the host? It looks like it would, can't say I like that. Otherwise this seems like fine syntactic sugar, I personally strongly prefer explicitly adding plugins in the constructor though.
@ericf: Yes. The inclusion of 'plugin-drag' would add support for the 'draggable' attribute to trigger the plug/unplug. A more defensive option would be to package addHostAttr consumption/sugar into a separate module, but that quickly complicates downstream dependencies/development. Side effects are possible, but not terribly likely, IMO. Moreso with the HTML_PARSER addition, though.
@tivac: Yeah, the more I think about it, the more data-* makes more sense for this use case. Of course, the plugin may well add a class to the host anyway (e.g. yui3-dd-draggable in http://developer.yahoo.com/yui/3/examples/dd/drag-plugin.html). The real addHostAttr is configured not to clobber existing ATTRS unless passed a 'force' param. Agreed that specifying config of behavior in the JS makes for clearer separation of responsibilities and easier maintainability.
@lsmith can’t I do this right now?
new Y.Console().plug('dd');
Maybe plug
should be overloaded to take more stuff in the signature:
new Y.Console().plug([ 'dd', { filters: {…}} ]);
@ericf: You can't do that now, no. Currently supported syntax is plug(Y.Plugin.Drag[, config]), plug({ fn: Y.Plugin.Drag[, cfg: config]}), and plug([ (either constructor or { fn: , cfg })* ]);
Since the signature is already overloaded to accept one or two args, it can get hairy extending it further to support n args.
It would be valuable to have support for plugging a plugin by its NS (e.g. plug('dd') or plug('dd', { config })), but that's basically what the addHostAttr is doing, excepting that a) it's kept in the context of an existing API (construction/attribute set), and b) I recommend the host attr be a descriptive name or adjective. Sometimes the current NSs aren't intuitive like that.
Ah yes, it's unplug
that can accept just the NS
: foo.unplug('dd')
Yeah I think this idea is very interesting, I do like that YUI has built in the idea of sandboxing (and nested sandboxes ala Y.use(…)
) so if the developer desires for plugins behavior to be sequestered, they could create a nested Y.use('da-plugin', function(){ … })
sandbox to apply it to, instead of their top-level YUI().use(…)
.
So all instances of
Y.Widget
(and subclasses) would be “boom, draggable” inside the:Y.use('console, 'plugin-drag', function () {…
?With this approach there might be unintended side-effects of a
YUI().use()
statement which contains a plugin. In some ways I like it, but it also has me thinking that there’s some lack of expressed intent by the user…