Ok, after working with the syntax I proposed above all day, I'm
inclined to believe a LowPro-esque helper might not be such a bad
thing. Here's the code I'm working with at this point:
Object.extend(Event, (function(){
return {
delegate: function(element, eventName, targetSelector, handler)
{
var element = $(element);
function createDelegation(_delegatedEvent) {
var origin = _delegatedEvent.element();
if ( origin.match(targetSelector) ){ return
handler(_delegatedEvent); }
};
element.observe(eventName, createDelegation);
return element;
},
delegators: function(element, eventName, rules) {
var element = $(element);
function delegateRule(rule) {
element.delegate(eventName, rule.key, rule.value)
}
$H(rules).each(delegateRule)
return element;
}
}
})())
Element.addMethods({
delegate: Event.delegate,
delegators: Event.delegators
})
Object.extend(document, {
delegate: Event.delegate,
delegators: Event.delegators
})
Event.delegate works in the same way as the syntax I proposed above.
Event.delegators (I'm not too keen on that name) works with the same
syntax that you proposed above. I've also added the the two methods to
document.
I'm also working on a way to simulate bubbling for events that don't
natively do so. For example, a form submission would fire the
'form:submitted' custom event. I add the original event that triggered
the custom event as an attribute of the custom event's memo object,
which gives me the liberty to halt the original event down the line if
I choose to do so like this:
event.memo['originalEvent'].stop();
I don't really think this sort of thing is fit for core, though it's
interesting, and it works very well with the Event delegation code I
proposed above.
On Feb 8, 6:44 pm, Pat Nakajima [EMAIL PROTECTED] wrote:
That LowPro post was actually what sparked the idea for me. As for the
syntax you proposed, I prefer my own (though I'm obviously biased),
because I like how closely it matches Element.observe. This has a
couple advantages. First, users will be more inclined to make use of
it since the syntax will be familiar. Second, the current behavior of
Event.observe specifies one behavior for one event name, on any number
of elements (through the use of the following pattern:
$$('.close').invoke('observe', 'click', Behaviors.close)
I've been using Event.delegate as a replacement for this pattern, so
rather than include a totally new paradigm (which is already provided
through the LowPro library, which will probably have delegation
support soon anyway), I think that the Prototype way would be:
$('all').delegate('click', Behaviors.close)
What do you think?
On Feb 8, 6:19 pm, Nicolás Sanguinetti [EMAIL PROTECTED] wrote:
I'd normally respond that since adding this feature is only 5 lines
away, it'd serve well as a plugin. *But*, event delegation is usually
such a good practice that adding this to core could be a nice
incentive for all those people that come into #prototype asking why do
my 51238 cells in the table take so much to observe an event :)
I'm not sure if I like the syntax yet, maybe something more LowPro-ish
as artemy suggested could be nicer
element.delegate(click, {
.close: Behaviors.close,
.send_friend: Behaviors.sendToFriend,
...
});
(and probably a global document.delegate or Event.delegate that used
the body as the target element)
BTW, and speaking about LowPro, Dan blogged earlier today about this
same thing, but in
jquery:http://www.danwebb.net/2008/2/8/event-delegation-made-easy-in-jquery
Thoughts?
-Nicolas
On Feb 8, 2008 9:02 PM, Pat Nakajima [EMAIL PROTECTED] wrote:
I guess I'll have to simulate non-bubbling events (though that
shouldn't be too painful due to Prototype's custom events). In the
meantime, I've submitted a patch containing pretty much the code I've
included above, as well as unit
tests:http://dev.rubyonrails.org/ticket/11060
On Feb 8, 4:07 pm, artemy tregoubenko [EMAIL PROTECTED]
wrote:
On Fri, 08 Feb 2008 23:48:10 +0300, Pat Nakajima [EMAIL PROTECTED]
wrote:
Ah, good point. I've updated my code to reflect your advice:
Object.extend(Event, {
delegate: function(element, eventName, targetSelector, handler) {
var element = $(element);
element.observe(eventName, function(_delegatedEvent) {
var origin = _delegatedEvent.element();
if ( origin.match(targetSelector) ){
return handler(_delegatedEvent);
}
})
}
})
I've looked into the Behaviour library, and used LowPro quite
extensively. The trouble is that these libraries (correct me if I'm
wrong) is that they require some sort of refresh if elements are added
to the page dynamically,