Following code has been tested with jQuery 1.3.2 version .
All the JavaScript code mentioned in this blog should be tried on firebug.
The super popular live method was added to jQuery 1.3 . It works just great. Except when it does not work. As per the documentation this method does not work in following cases: blur, focus, mouseenter, mouseleave, change, submit .
How binding events work in jQuery
1 2 3 | |
In above case click event is bound to all the links in the document. jQuery stores such binding information as data attribute of the bound element. This is how I can access the list of all functions bound to an element.
1
| |
If a new link is dynamically added then that new link will not get this click behavior. Tosolve this problem I can use live method.
Trying out live event
1 2 3 | |
If I add a new a tag dynamically then that tag will automatically get the new click behavior. That’s great.
Just like the previous section, now I am going to find the events bound to a element. However when I execute following code I get undefined .
1
| |
Why is that. In the previous section I showed that all the events bound to an element are stored as the data attribute of that element. Well, live is different. live events are not bound to the element directly. They are bound to the top level ‘document’. I can verify this by trying out this code
1
| |
How does live method work
live methods do not set anything on elements directly. All the event handlers are set at the document level. It means that in order for live methods to work, event bubbling is required. If you don’t know what event bubbling is then read her . It also means that event should not be stopped while it is propagating to document. If event propagation is stopped then event handlers bound at the document level will never know about that event and live method will fail.
The strategy to let someone else deal with the event is called event delegation. You can read more about event delegation here .
When live method is called then a binding is done at the document level. Loosely translated this is what is basically happening.
1 2 3 4 5 6 | |
As you can see when a click on p event bubbles all the way to the top then that event is captured by document and necessary action is taken if the target element matches.
It is clear that if the click event is stopped before it reaches document then live method will not work. I will show you an example.
1 2 3 4 5 6 7 8 9 | |
If I click on Java or Javascript I get a message on console. live is working great. Now I’ll stop the event propagation when event reaches to div.
1 2 3 4 5 6 7 8 | |
Now you will notice that live is no more working.
live does not work when event bubbling is not supported
In the previous section I showed that when event does not bubble up to document then live fails. It means that all the events that do not bubble will not work. Which means that events like blur, focus, mouseenter, mouseleave, change and submit which do bubble in IE will not work in IE. However note that these events will continue to work in Firefox.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
Above code will work in firefox but it will not work in IE.
Here is an example of an event that does not work in IE: onchange event.
DOM models suggest that onchange event should bubble . However msdn documentation clearly says that onchange event does not bubble .
Make all the live method problems go away
To recap live method will not work in following cases:
- live method works on event propagation, if an event is stopped while it is bubbling then live will not work.
- IE does not support bubbling for certain events. live method on those events will not work in IE.
There is a way to get around to both the problems.
Brandon Aaron developed livequery plugin which was finally merged into jQuery as live method. livequery plugin solves both the problems listed above and the code works in IE too.
First step is to include this plugin
1
| |
Now try this code.
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 | |
If I click on ‘Java’ or ‘Javascript’ I will get proper response even though event propagation is being stopped. Also even though change event does not bubble in IE, above code works in IE.
livequery works because livequery ,unlike live, method does not do binding at the document level. livequery does binding at the element level. You can find that out by running following code.
1
| |
Above code will produce result if I am using livequery. Above code will not produce any result if I am using live method.
The key piece of code in the plugin that makes all this work is
1 2 | |
Every 20 milliseconds livequery runs all the bindings defined in livequery and then binds the matched element with the event.
By understanding the internals of how live and livequery are implemented, now you can choose to use livequery in certain cases where live will not work. Also it helps to understand how live actually works.
Live method finds elements and then throws it away. Not very efficient.
A typical use of live method is something like this.
1 2 3 | |
As it has already been discussed a live method registers events at document level.
However when $('p').live(...) is evaluated then jQuery first goes and finds all the p elements. And then what does it do with those elements. Nothing. That’s right. jQuery throws away all those p elements which were just found without using them. What a waste.
If your application has a lot of live methods and this might slow down the performance of the application.
A better solution would have been to design an API like this one:
1
| |
jQuery is flexible and I can create my own live method but it will add to the confusion. Another solution would be to make the call to live method without first finding all those p element. Here is how it can be done.
1 2 3 4 5 | |
In the above case no element will be selected only to be thrown away. This is much better.
Seeing is believing
In the previous section, I showed how live method can be made to work without first selecting the elements. However a friend of mine asked me if I could conclusively prove that in the real live method a find is actually done. And in my solution a find call is not done.
Here I am showing you the overriding find method. In this method I am overriding the original find method. I will put a log message before passing the find method to the original method.
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
In the above case you will get message on firebug console confirming that find is indeed invoked when live method is called.
Here is revised version of live. Try this one.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
Above version does not print ‘find was called’.