This afternoon I caught a question posted in phpvietnam group:
Source (in Vietnamese): http://groups.google.com/group/phpvietnam/browse_thread/thread/c7a8688875a320c3
1. Inline Event Registration Model
Now working with event object and this keyword. We have the event handler function:
1 2 3 4
In this case, when the link element is clicked, the
doSomething handler function will be called
evt will get
undefined (null) value and
this will refer to
window object. This is not my
intention, I want the event has to be event object and this has to refer to the link element. So I
have to modify the code a little bit:
With above code, the event object is passed to
doSomething handler function. In my assumption,
when link element is clicked, the
onclick event is triggered from the browser native code:
1 2 3 4 5
Remember that we pass
event as parameter to
doSomething function but not any other name. If we
evt for example, the exception occurs:
1 2 3 4 5
Because this is the browser native code, it does not allow to use
undefined (null) value there.
However, we can pass any
there is no exception in this case. Note that the above code is tested with chrome and it just
works (?). No exception at all but not the case for IE, Firefox, Opera, Safari. Well, in this case
I don’t know if google chrome is good or bad?
By using the event parameter passed to
doSomething function, now we can get the event object to
get many useful properties there. For example, event type, cursor location, charCode, etc.,
Now we have to make sure
doSomething function has to refer to link element, not
window object with the following code:
From the browser native code will trigger the
onclick event as follows:
1 2 3 4
The above inline event registration code now works as my intention. I just explain in details in this part only.
2. Traditional Event Registration Model
Make sure after the dom is loaded, this code will execute:
1 2 3 4
This way of event registration is compatible with all major browsers. In this model, event object
is passed as the only parameter to the handler function and
this in the handler function block
refer to linkEl.
Code this way to make sure
doSomething function still has access to event object and
to element triggering the event.
1 2 3
In case the
doSomething function has more than 1 arguments:
1 2 3 4 5 6 7 8 9
And then we come up with 3rd and 4th event registration model: W3C model and Microsof (IE) model. By combining these 2 models, we got the solution for event registration compatible with all major browsers:
3. W3C Event Registration Model
This is the specification of W3C to register event listener (handler). By using it, we can register as many listeners as possible.
eventType: click, mouseover, mouseout, etc.,
listener: event handler function, it will be called when the element triggered eventType event.
useCapture: you should always pass false to make it compatible with IE. This relates to event
phases which I will make another blog post about.
We can apply as:
1 2 3 4 5 6 7 8 9 10 11 12 13
By using this approach, you can add as many listeners as possible. When an eventType triggered, all registered listeners will be executed. Note that W3C DOM specification does not require that the first listener registered will be executed first, these listeners can be executed by random. And till now, there is no way to check how many listeners registered in an element.
How about removing an event listener?
I rarely use
removeEventListener. You can not remove an anonymous function. From the above code,
I use anonymous function as listener, as the result, I can not find the way to remove it. Assigning
it a name and the problem solved:
1 2 3 4 5 6 7
This is the W3C way and M$ follows an other way.
4. Microsoft Event Registration Model
IE does not use
1 2 3 4 5 6
Wanna remove a handler (listener)? Use
1 2 3 4 5
Note that IE does not have 2 event phases (capture and bubble) but bubble phase only. So when using
W3C, you should always use
useCapture for safety purpose :d. If you fully understand
these 2 event phases, you can pass true for
useCapture but intentionally.
5. At last, combine these 2 models for simple and compatible api:
1 2 3
My intention is that event object has to be passed as 1st parameter to listener and this has to refer to the element in the block code. Here we come the solution:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
Use this api as simple as:
1 2 3 4
Hope that you find this post interesting, I will blog about 2 event phases soon. Happy coding :D