delegate.js revision 14017741ef334485c65013d129608513161db7c2
3f3aa287185afb5d48d7ef0717054a154c372dc9Adam Moore * Adds event delegation support to the library.
3f3aa287185afb5d48d7ef0717054a154c372dc9Adam Moore * @module event
3f3aa287185afb5d48d7ef0717054a154c372dc9Adam Moore * @submodule event-delegate
7b4d1363155303b5bfb852e5639b851bbd4dc255Luke Smithvar toArray = Y.Array,
7b4d1363155303b5bfb852e5639b851bbd4dc255Luke Smith Y.log("delegate requires a type, callback function, target, and filter", "warn");
7b4d1363155303b5bfb852e5639b851bbd4dc255Luke Smith container = (query) ? Y.Selector.query(query, null, true) : el;
7b4d1363155303b5bfb852e5639b851bbd4dc255Luke Smith args.splice(2, 2, container); // remove the filter
7b4d1363155303b5bfb852e5639b851bbd4dc255Luke Smithdelegate.notifySub = function (thisObj, args, ce) {
7b4d1363155303b5bfb852e5639b851bbd4dc255Luke Smith // Preserve args for other subscribers
7b4d1363155303b5bfb852e5639b851bbd4dc255Luke Smith // Only notify subs if the event occurred on a targeted element
7b4d1363155303b5bfb852e5639b851bbd4dc255Luke Smith var currentTarget = this.getCurrentTarget.apply(this, args),
14017741ef334485c65013d129608513161db7c2Luke Smith // Support multiple matches up the the container subtree
14017741ef334485c65013d129608513161db7c2Luke Smith for (i = currentTarget.length - 1; i >= 0; --i) {
14017741ef334485c65013d129608513161db7c2Luke Smith // New facade to avoid corrupting facade sent to direct subs
14017741ef334485c65013d129608513161db7c2Luke Smith args[0] = new Y.DOMEventFacade(originalEvent, target, ce);
14017741ef334485c65013d129608513161db7c2Luke Smith if (ret === false) {
14017741ef334485c65013d129608513161db7c2Luke Smith break; // once() callback should only be called once, duh
7b4d1363155303b5bfb852e5639b851bbd4dc255Luke Smithdelegate.compileFilter = Y.cached(function (selector) {
14017741ef334485c65013d129608513161db7c2Luke Smith var descendantOfSelector = selector.replace(/,/g, ' *,') + ' *';
7b4d1363155303b5bfb852e5639b851bbd4dc255Luke Smith return function (e) {
7b4d1363155303b5bfb852e5639b851bbd4dc255Luke Smith if (selectorTest(e.target._node, selector, container)) {
14017741ef334485c65013d129608513161db7c2Luke Smith if (selectorTest(currentTarget, descendantOfSelector)) {
7b4d1363155303b5bfb852e5639b851bbd4dc255Luke Smith if (selectorTest(currentTarget, selector, container)) {
14017741ef334485c65013d129608513161db7c2Luke Smith matches = matches[0]; // single match or undefined
67d8986c26b16b1d9ea6e5b62e753c55af9a4f52Todd Kloots * Sets up event delegation on a container element. The delegated event
7b4d1363155303b5bfb852e5639b851bbd4dc255Luke Smith * will use a supplied filter to test if the callback should be executed.
7b4d1363155303b5bfb852e5639b851bbd4dc255Luke Smith * This filter can be either a selector string or a function that returns
7b4d1363155303b5bfb852e5639b851bbd4dc255Luke Smith * a Node to use as the currentTarget for the event.
67d8986c26b16b1d9ea6e5b62e753c55af9a4f52Todd Kloots * The event object for the delegated event is supplied to the callback
67d8986c26b16b1d9ea6e5b62e753c55af9a4f52Todd Kloots * function. It is modified slightly in order to support all properties
67d8986c26b16b1d9ea6e5b62e753c55af9a4f52Todd Kloots * that may be needed for event delegation. 'currentTarget' is set to
7b4d1363155303b5bfb852e5639b851bbd4dc255Luke Smith * the element that matched the selector string filter or the Node returned
7b4d1363155303b5bfb852e5639b851bbd4dc255Luke Smith * from the filter function. 'container' is set to the element that the
7b4d1363155303b5bfb852e5639b851bbd4dc255Luke Smith * listener is delegated from (this normally would be the 'currentTarget').
7b4d1363155303b5bfb852e5639b851bbd4dc255Luke Smith * Filter functions will be called with the arguments that would be passed to
7b4d1363155303b5bfb852e5639b851bbd4dc255Luke Smith * the callback function, including the event object as the first parameter.
7b4d1363155303b5bfb852e5639b851bbd4dc255Luke Smith * The function should return false (or a falsey value) if the success criteria
7b4d1363155303b5bfb852e5639b851bbd4dc255Luke Smith * aren't met, and the Node to use as the event's currentTarget and 'this'
7b4d1363155303b5bfb852e5639b851bbd4dc255Luke Smith * object if they are.
67d8986c26b16b1d9ea6e5b62e753c55af9a4f52Todd Kloots * @method delegate
67d8986c26b16b1d9ea6e5b62e753c55af9a4f52Todd Kloots * @param type {string} the event type to delegate
67d8986c26b16b1d9ea6e5b62e753c55af9a4f52Todd Kloots * @param fn {function} the callback function to execute. This function
67d8986c26b16b1d9ea6e5b62e753c55af9a4f52Todd Kloots * will be provided the event object for the delegated event.
67d8986c26b16b1d9ea6e5b62e753c55af9a4f52Todd Kloots * @param el {string|node} the element that is the delegation container
7b4d1363155303b5bfb852e5639b851bbd4dc255Luke Smith * @param filter {string|function} a selector that must match the target of the
7b4d1363155303b5bfb852e5639b851bbd4dc255Luke Smith * event or a function that returns a Node or false.
67d8986c26b16b1d9ea6e5b62e753c55af9a4f52Todd Kloots * @param context optional argument that specifies what 'this' refers to.
67d8986c26b16b1d9ea6e5b62e753c55af9a4f52Todd Kloots * @param args* 0..n additional arguments to pass on to the callback function.
67d8986c26b16b1d9ea6e5b62e753c55af9a4f52Todd Kloots * These arguments will be added after the event object.
67d8986c26b16b1d9ea6e5b62e753c55af9a4f52Todd Kloots * @return {EventHandle} the detach handle