This project is archived and is in readonly mode.

Better event delegation
Reported by Chris the Developer | November 17th, 2009 @ 08:45 AM | in 2.0 (closed)
The current :relay(selector) method has some drawbacks,
namely:
* You have to add an event for each selector that has a delegate, *
both direct event attachment and event delegation are currently in
the same method, * the :relay pseudo-selector is somewhat confusing
to people new to event delegation, * while all delegates added with
:relay may be for the same event, each requires that you add a new
event to the container
I propose the (separate) method below as a replacement to the current event delegation:
Element.implement({
delegateEvent: function(type, delegates, prevent, propagate) {
//get stored delegates
var key = type + '-delegates',
stored = this.retrieve(key) || false;
// if stored delegates; extend with
// new delegates and return self.
if (stored) {
var delegates = $extend(stored, delegates);
this.store(key, delegates);
return this;
}
else {
this.store(key, delegates);
}
return this.addEvent(type, function(e) {
// Get target and set defaults
var target = document.id(e.target),
prevent = prevent || true,
propagate = propagate || false
delegates = this.retrieve(key);
// Cycle through delegates
for (var selector in delegates) {
if (target.match(selector)) {
// If a selector matches then fiddle with the natural flow as required
if (prevent) e.preventDefault();
if (!propagate) e.stopPropagation();
// Fire the method up...
if (delegates[selector].apply) return delegates[selector].apply(target, $A(arguments));
}
}
});
}
});
With this new method you can:
* Attach apply any delegate to any selector within the same call, *
normal event attachment and event delegation are logically split, *
only the first call for an event will attach an event and any
subsequent additions of delegates will simply be placed in a simple
delegate registry - many delegates, many selectors, many calls to
the delegateEvent method but still only 1 event!
Small use-case:
window.addEvent('domready', function() {
document.body.delegateEvent('click', {
'#clickme1': function() {
console.log('clickme1 clicked');
},
'#clickme2': function() {
console.log('clickme2 clicked');
document.body.delegateEvent('click', {
'#clickme1': function() {
console.log('new delegate!');
}
});
},
'#clickme3': function() {
console.log('clickme3 clicked');
}
});
});
While 2 calls were made to delevateEvent, only 1 event was fired. The second delegation simply overwrote delegate in the registry.
Comments and changes to this ticket
-
Christoph Pojer December 18th, 2009 @ 12:28 AM
- State changed from new to invalid
I think our decision is to go with the implementation we use currently in MooTools-More. However, feel free to release this as a plugin on the MooTools Forge ( http://mootools.net/forge ). If users like this solution more, we will most likely rethink our approach.
-
Chris the Developer December 18th, 2009 @ 12:47 AM
But the critical flaw in the current implementation is that for multiple children you still have multiple events, which can't be right! You suggestion is a good one (I am currently trying to get it in the right shape for Forge), but you have to agree that the current implementation isn't the best way of going about things (whether you like my implementation or not); Multiple events for multiple children, additional events for the same delegate on separate attachments, unintuitive pseudos-selector attachment...
I'm not saying 'pick me!' - just putting forward a case that illustrates the shortcomings of the current implementation with suggestions on how to overcome those limitations...If you're going to take the time to implement this useful feature (event delegation in general) then I think it should be done right, and open to improvement where improvement is due.
-
Christoph Pojer December 18th, 2009 @ 12:53 AM
- State changed from invalid to open
- Assigned user set to Valerio
I'll assign it to Valerio, please post the link to your plugin once its up, we'll discuss it :)
-
-
-
Arieh February 10th, 2010 @ 11:14 AM
The only flaw i see in this implementation is that i can't delegate 2 different events to the same selector. this would seem like a small deal for small usage, but if the same element (eg:Document) is used by more than 1 plugin it might create a collision between neighboring widgets.
That being said, I also find that using the delegate method (as suggested here), passing it a list of selectors and functions is much more intuitive and also Mootools-like than the current implementation (using :relay(selector).
though i suppose the 2 syntax could easily live side-by-side -
Chris the Developer February 10th, 2010 @ 11:22 AM
@Arieh - Good points, though I think the '2 different events to the same selector' is antithetical to event delegation... You can add different event types to the same selector, with a call to delegateEvent for each event type, but more than 1 of the same kind of event to the same selector doesn't strike me as an efficient use of event delegation.
All that being said - my goal for this plugin is be promote the use of event delegation by making it easy, and plugging as many holes in the current implementation as possible. If I were new to MooTools, I would sooner use elem.delegateEvent({...}); than elem.addEvent('click:relay(...)', fn() {...}); but if others find it easier to make use of delegation with modifications to the plugin then I would be happy to support those modifications. :)
-
Chris the Developer February 11th, 2010 @ 12:43 PM
I have added a delegateEvents method to the mix. Check it out here.
-
Chris the Developer March 9th, 2010 @ 11:36 AM
Just an update on the plugin I posted on Forge; about 220 downloads in the month it's been there. Perhaps the demand might prompt an addition to core, or something... :)
-
csuwldcat January 26th, 2011 @ 08:03 PM
- Milestone order changed from 0 to 0
Hey Chris,
In my opinion, the drawbacks from having to do multiple events do not out weigh the benefits that you have with the events being separated. With the pseudo method we get a few things for free:
- separation and event encapsulation
- gives users experience and a living example of what our pseudos
are all about
- separate events are crucial for streamlining multi-event custom events
I do agree that delegation should be in Core. I use it in 99% of projects and it is a huge win for performance. Swiff out, Delegation in. Period.
-
ibolmo January 19th, 2012 @ 08:34 AM
- State changed from open to wontfix
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
People watching this ticket
Referenced by
-
55 Event Delegation method for Element implemented and kind of duplicate of #789