onClick vs Element.observe

25 views
Skip to first unread message

phegaro

unread,
Nov 16, 2009, 6:27:30 PM11/16/09
to Prototype & script.aculo.us
Hi all,
I have an app that is going to put out a list of items onto a page
and each one has a number of click targets. Now i could setup the
event handler in one of two ways.

1. add it into the template that is rendered with the following code

<div onclick="doIt()" id="item_1" class="item">Item Name 1</div>

or i could do the following

2. Add it using a selector and a script

$$(".item").each(function(element){element.observe('click', doIt);});

Are there any issues with option 1 or 2 and which is more performant
and cross browser compatible. I think 1 is more performant but not
sure it works in all browsers.

ColinFine

unread,
Nov 17, 2009, 7:58:55 AM11/17/09
to Prototype & script.aculo.us
Generally, the recommendation is not to use the old 'onClick=' method
of event handling: I don't know how it compares for performance, but
it's certainly less flexible.

You can simplify your 2) slightly:

$$(".item").invoke('observe', 'click', doIt);

A third alternative is to use delegation:

$(document).observe('click', doIt);

and then make doIt determine what was clicked:
function doIt(e) {
var item = e.findElement('.item');
...
}

This is particularly good if you are going to be adding items
dynamically when the page has already been loaded.

Colin Fine

david

unread,
Nov 17, 2009, 8:06:35 AM11/17/09
to Prototype & script.aculo.us
Hi phegaro,

the difference is not about cross browser, because both method is
cross browser.
first method come the DOM0 specification and the second one is DOM2.

The big difference is that the DOM0 event could only have ONE
definition. But for the DOM2 event, you'll have the possibility to
accept more than one definition.

What I would recommend is to use the DOM2 event and I much more
recommend using event delegation:
instead of observing each element, just observe the parent and get the
element on the the click is done. So you will have only one event, and
you could remove or insert element, it will always handle event for
all elements.

--
david

phegaro

unread,
Nov 17, 2009, 5:17:24 PM11/17/09
to Prototype & script.aculo.us
Delegation sounds like a good model for doing this although if i want
to pass parameters that are custom to each node like which id did it
click on then i assume i have store it as a property on the node and
pass arguments to the delgated function?

In the above example if doIt took a paramter of the id to work on,

doIt(id) {
// do something to the object with id X
...
}

Then with the delegation model i would have to retreive the node using
findelement and then have an attribute on the node that held the id?
Is that right?

Kiran

ColinFine

unread,
Nov 18, 2009, 7:47:36 AM11/18/09
to Prototype & script.aculo.us


On Nov 17, 10:17 pm, phegaro <pheg...@gmail.com> wrote:
> Delegation sounds like a good model for doing this although if i want
> to pass parameters that are custom to each node like which id did it
> click on then i assume i have store it as a property on the node and
> pass arguments to the delgated function?
>
> In the above example if doIt took a paramter of the id to work on,
>
> doIt(id)  {
> // do something to the object with id X
> ...
>
> }
>
> Then with the delegation model i would have to retreive the node using
> findelement and then have an attribute on the node that held the id?
> Is that right?
>

Yes, clearly; if the processing is different for different element
then a delegation model requires you to determine which element you
are processing and choose your processing accordingly.

If each item is distinct, give them all an HTML 'id', and just use
that:

function doIt(e) {
var element = e.findElement('.item');
var id = element.id;

If there are classes of them, it's easiest to use CSS classes:

<span class='item click_class_1'> ...

function doIt(e) {
var element = e.findElement('.item');
var class_1 = element.hasClassName('click_class_1');

or more generally

function doIt(e) {
var element = e.findElement('.item');
if (var matches = element.className.match(/click_class_(\n+)/) {
var clickclass = matches[1]);

Eric

unread,
Nov 18, 2009, 9:00:45 AM11/18/09
to Prototype & script.aculo.us
Hi,

I also think delegation is the better approach.
However, I did notice that none of the examples was dealing with the
case where the user click on something that is not a '.item'.

You may want to do something like this:

function doIt(e) {
var element = e.findElement('.item');
if(element != document)
{
var id = element.id;
// Do your stuffs here
}
}

Eric

ColinFine

unread,
Nov 19, 2009, 4:24:29 AM11/19/09
to Prototype & script.aculo.us


On Nov 18, 2:00 pm, Eric <lefauv...@gmail.com> wrote:
> Hi,
>
> I also think delegation is the better approach.
> However, I did notice that none of the examples was dealing with the
> case where the user click on something that is not a '.item'.
>
> You may want to do something like this:
>
> function doIt(e) {
>   var element = e.findElement('.item');
>   if(element != document)
>   {
>     var id = element.id;
>     // Do your stuffs here
>   }
>
> }
>

You're right - in fact, my example was wrong. I believed that
Event.findElement took a CSS selector, but it actually takes a
tagname, so e.findElement('.item') won't work.

Instead I would use

var element = e.element().up('.item').

which I think is easier than your suggestion.

Reply all
Reply to author
Forward
0 new messages