Event delegation auto. handles "new" added childs to parent?

3 views
Skip to first unread message

Rolf -nl

unread,
Nov 23, 2009, 7:10:37 AM11/23/09
to MooTools Users
If I add an event to a collection of elements in a parent using event
delegation that it automatically also adds the event on new elements
created in that parent?
From tests I can say this is true, and I think it's also in the docs
"[..] evaluating your code only when the user actually clicks [..]"
but just to make sure... Correct?!

I used to have attach/detach methods in several classes that I would
run on each element in a collection of elements which aren't needed
anymore if I do one addEvent on a parent container using event
delegation...

One more thought (not tested yet).. if I would do a removeEvent on a
single element in the collection of elements (aka to temporary "lock"
a drag/drop possibility by removing the event), is this going to work
if I earlier added the event with event delegation to the parent?

Aaron Newton

unread,
Nov 23, 2009, 11:48:12 AM11/23/09
to mootool...@googlegroups.com
you have the general concept down. if you had a list element (ul) with a bunch of list items (li) and you added this delegation method:

myUL.addEvent('click:relay(li)', function(event, element) { alert("you clicked " + element.get('id')) });

Then, if you added any new list item to the list it would get this behavior. This is one of the benefits of delegation. If you wanted to prevent this from occurring to some of the list items you might give them all a class and delegate only to those with the class assigned, removing the class from those you don't want to have the behavior.

You can't prevent this behavior by attaching an event or calling removeEvent on the li objects, as they don't have events attached to them.

Perrin Perrin

unread,
Nov 23, 2009, 12:17:41 PM11/23/09
to mootool...@googlegroups.com
In the example drag/drop lock example you could implement a 'lock' on an individual element by adding an event hander directly on the element (say when drag started) and removing it later (when drag completed) that just stops the event from propagating.

An example: http://mooshell.net/mWYZG/1

Aaron Newton

unread,
Nov 23, 2009, 1:19:38 PM11/23/09
to mootool...@googlegroups.com
Mooshell appears to be broken at the moment, so I can't look at the example. But what you say sounds right. 

Rolf -nl

unread,
Nov 23, 2009, 2:48:58 PM11/23/09
to MooTools Users
Ok, so on the startup/initialize side of things event delegation is
(in my case) quite useful. Though when there are exceptions or changes
to elements I would have to work with (css) classes added to elements
to prevent certain behaviour (or make it do something different)

For example, I could use store/retrieve now to determine wether or not
to attach (or detach) an event to some element. With event delegation
I only have Selectors to 'filter', correct?

Generally speaking, would you advise to use event delegation whenever
possible? I mean, if it saves memory compared to when you are
attaching events to a lot of elements for example. If it doesn't save
you memory in the end it is "just" quicker (or a clean way) to program
instead of typing each-loops every time.

To me adding a event to stop propagating and prevent dragging of some
element as soon as you would start to drag sounds a bit like hack.
Using css classes to determine what to do in some part of the
application sometimes also feels like hack (as if you are adding style
bits to an element that you are using just to get some sort of 'state'
value).

Maybe a good example, would you rewrite the Tips class now using
delegation? Or, maybe because the attach/detach methods are too
specific it's better to just leave it like it is...


On Nov 23, 7:19 pm, Aaron Newton <aa...@iminta.com> wrote:
> Mooshell appears to be broken at the moment, so I can't look at the example.
> But what you say sounds right.
>
> On Mon, Nov 23, 2009 at 9:17 AM, Perrin Perrin <stardistroye...@gmail.com>wrote:
>
>
>
> > In the example drag/drop lock example you could implement a 'lock' on an
> > individual element by adding an event hander directly on the element (say
> > when drag started) and removing it later (when drag completed) that just
> > stops the event from propagating.
>
> > An example:http://mooshell.net/mWYZG/1
>
> > On Mon, Nov 23, 2009 at 10:48 AM, Aaron Newton <aa...@iminta.com> wrote:
>
> >> you have the general concept down. if you had a list element (ul) with a
> >> bunch of list items (li) and you added this delegation method:
>
> >> myUL.addEvent('click:relay(li)', function(event, element) { alert("you
> >> clicked " + element.get('id')) });
>
> >> Then, if you added any new list item to the list it would get this
> >> behavior. This is one of the benefits of delegation. If you wanted to
> >> prevent this from occurring to some of the list items you might give them
> >> all a class and delegate only to those with the class assigned, removing the
> >> class from those you don't want to have the behavior.
>
> >> You can't prevent this behavior by attaching an event or calling
> >> removeEvent on the li objects, as they don't have events attached to them.
>

Aaron Newton

unread,
Nov 23, 2009, 3:47:53 PM11/23/09
to mootool...@googlegroups.com
I have plans to write a detailed blog post about delegation on the mootools blog, but I've been busy; maybe this week.

Anyway, to answer your questions, delegation is not always better. For example, mouseover/out events are fired whenever you move your mouse across any element's borders, and attaching delegation to, say, a document full of links, divs, lists, and images so that whenever you mouseover an element with 'a.tips' would mean running the selector a LOT. Drag your mouse across the page and you might run the selector dozens of times. Mousemove is even worse.

This isn't to say that mouseover isn't a good candidate, but it's a poor candidate for an element containing a LOT of elements (like document.body). Put it on a list of links, like a menu, and it's fine.

Click events are much better as they don't occur like this.

Delegation pushes the cost of selectors away from startup and removes the looping costs associated with $$().each(..addEvent). They also allow you to alter the DOM and have your behavior apply to any new items that match the selector. But they aren't always a better solution than addEvent. In general, I'd say that maybe 70% of the time they are better. Knowing which one to use is a matter of balancing initialization costs, the event type, the size of the DOM inside the parent that's getting the event attached, and the use case. There's no 100% correct answer, though some solutions are clearly better than others (mousemove for example, is nearly always a poor candidate). 

ibolmo

unread,
Nov 24, 2009, 5:03:16 AM11/24/09
to MooTools Users


On Nov 23, 12:47 pm, Aaron Newton <aa...@iminta.com> wrote:
> I have plans to write a detailed blog post about delegation on the mootools
> blog, but I've been busy; maybe this week.
>
> Anyway, to answer your questions, delegation is not always better. For
> example, mouseover/out events are fired whenever you move your mouse across
> any element's borders, and attaching delegation to, say, a document full of
> links, divs, lists, and images so that whenever you mouseover an element
> with 'a.tips' would mean running the selector a LOT. Drag your mouse across

You could reduce this cost by narrowing the scope of the selector:
#parent a.tips, for example.

Aaron Newton

unread,
Nov 24, 2009, 11:13:04 AM11/24/09
to mootool...@googlegroups.com
You could reduce this cost by narrowing the scope of the selector:
#parent a.tips, for example.

if you added this selector to the document body, it would still be just as expensive as it would be run every time you moused over anything. This is bad:

document.body.addEvent('mouseover:relay('#parent a.tips')', fn);

this is the much, much better thing to do:

$('parent').addEvent('mouseover:relay('a.tips', fn) 

Rolf -nl

unread,
Nov 25, 2009, 2:54:15 PM11/25/09
to MooTools Users
My (current) "biggest" question about when and how to actually use
event delegation in a project is about element selection.
At the moment I've set up my class so (in theory) it could accept a
json object that describes various elements and, for example, if they
are draggable or not.
In the class I can then filter out those elements in with a loop I run
my 'addDraggable' method which in turn runs my attach functions that
adds mousedown/mouseup events to the element.
I can also tell the class it's a file and, for example, run 'addFile'
which in turn attaches a dblclick event that opens a dialog to set a
name, show a preview or whatever.
The html is created for the items and all is put on screen.

For the sake of nice html and of course some styling, I also add css
classes to each element, but in theory I don't need those classes for
the thing to work (css classes like 'draggable', 'file', etc. that in
a way describe the element as well).

If I would re-write part of the classes taking advantage of event
delegation I would have create html first so that I can use css
classes to filter out the elements needed that should receive the
proper events for mousedown/mouseup/dblclick, etc. Correct? The css
classes are required for filtering.

So, that's the crossroad I'm on at the moment... and I wonder how
other more "app" like developers would approach this.

Aaron Newton

unread,
Nov 25, 2009, 4:24:55 PM11/25/09
to mootool...@googlegroups.com
If I would re-write part of the classes taking advantage of event
delegation I would have create html first so that I can use css
classes to filter out the elements needed that should receive the
proper events for mousedown/mouseup/dblclick, etc. Correct? The css
classes are required for filtering.

If you describe all your behavior with delegation, your code is simplified when you need to add elements. You just parse your json into element objects and inject them in the document. All the event delegation logic is written/applied once, when you attach to the container.

Rolf -nl

unread,
Nov 26, 2009, 7:04:00 AM11/26/09
to MooTools Users
:) I see the benefits.
All I'm saying or better: asking myself, is that I then need css
classes for the delegation element selection.
For whatever reason I try to avoid dependancy of css classes for
application logic..

this:

if(element.retrieve('isFolder', false)) this.addFolder(element);

to me looks cleaner than:

if(element.hasClass('folder')) this.addFolder(element);

or maybe it's just me ;)

in the end I will implement delegation probably, because of the
benefits.

Aaron Newton

unread,
Nov 26, 2009, 2:23:03 PM11/26/09
to mootool...@googlegroups.com
you can always do this:

$(myUL).addEvent("click:realy(li)", function(event, element) {
  if (element.retrieve('isFolder', false)) this.addFolder(element);
});

Rolf -nl

unread,
Nov 27, 2009, 10:54:22 AM11/27/09
to MooTools Users
I will play with this over the weekend.. let's close this thread :)
thanks for the insights.


On Nov 26, 8:23 pm, Aaron Newton <aa...@iminta.com> wrote:
> you can always do this:
>
> $(myUL).addEvent("click:realy(li)", function(event, element) {
>   if (element.retrieve('isFolder', false)) this.addFolder(element);
>
> });
Reply all
Reply to author
Forward
0 new messages