jQuery('.myButtton').live('click', function(){ //do stuff });
Performance
Testcases
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>jQuery live tester</title></head><body><div id="result1">waiting for results...</div><div id="result2">waiting for results...</div><div id="result3">waiting for results...</div><div id="result4">waiting for results...</div><div id="result5">waiting for results...</div><div id="result6">waiting for results...</div><div id="result7">waiting for results...</div><div id="button">Button</div><script type="text/javascript" src="jquery.js"></script><script type="text/javascript">/*<![CDATA[*/jQuery(document).ready(function(){function measureClick(output, text) {var target = jQuery('#button');var count = 10;var start = new Date();for(var i=0; i<count; i++) {target.click();}var stop = new Date();output.html(text + ((stop.getTime() - start.getTime())/count));}function addEvents(count, selector, context) {context = context || document;for(var i=0; i<count; i++) {jQuery(selector + i, context).live('click', function() {});}}function removeEvents(count, selector) {for(var i=0; i<count; i++) {jQuery(selector + i).die('click');}}jQuery('#button').bind('click', function() {});measureClick(jQuery('#result1'), 'without live events: ');addEvents(10, '.garbage');measureClick(jQuery('#result2'), 'with 10 live events: ');removeEvents(10, '.garbage');addEvents(100, '.garbage');measureClick(jQuery('#result3'), 'with 100 live events: ');removeEvents(100, '.garbage');addEvents(200, '.garbage');measureClick(jQuery('#result4'), 'with 200 live events: ');//Add large DOM-treefor(var i=0; i<500; i++) {jQuery('<div class="garbage' + i+'">garbage</div>').appendTo('body');}measureClick(jQuery('#result5'), 'with 200 live events and large dom: ');removeEvents(200, '.garbage');addEvents(100, '#garbage');measureClick(jQuery('#result6'), 'with 100 live events with id selector: ');removeEvents(100, '#garbage');addEvents(100, '#something div.garbage td tr div div.test');measureClick(jQuery('#result7'), 'with 100 live events with complex selector: ');removeEvents(100, '#something div.garbage td tr div div.test');});/*]]>*/</script></body></html>
Test results
test | Firefox 3.5 | IE8 | IE7 | Chrome | Safari 4 |
---|---|---|---|---|---|
without live events | 0.3 | 1.6 | 0.5 | 0.2 | 0.3 |
with 10 live events | 4.9 | 9.4 | 15.6 | 2.1 | 3.4 |
with 100 live events | 45 | 93.8 | 143.8 | 21.5 | 20.5 |
with 200 live events | 94.2 | 201.6 | 306.2 | 36.6 | 40.6 |
with 200 live events and large dom | 92.2 | 201.6 | 306.2 | 36.9 | 41.7 |
with 100 live events with id selector | 50.4 | 90.6 | 157.8 | 17.2 | 19.7 |
with 100 live events with complex selector | 109.1 | 231.3 | 373.4 | 46.9 | 48.4 |
Explanation of tests
Conclusion
What could be done to improve this?
jQuery(expression, context)
function. I dont know enough about the internals of jQuery to say how feasible this is.jQuery('<where_to_attach_the_event>').live( '<delegation_selector>', eventType, eventHandler);
jQuery('document').live('<delegation_selector', eventType, eventHandler)
Update:
After a comment from Jonathan Sharp I added some more tests to see how a more nested dom-tree affects the performance. When adding 30 nested divs we can see that a click deep down the tee will be affected more by the live events.
var button = jQuery('<div id="button">button<div>').appendTo('body'); button.bind('click', function() {}); addEvents(100, '.garbage'); //Add nested DOM-tree var element = jQuery('body'); for(var i=0; i<30; i++) { element = jQuery('<div></div>').appendTo(element); } measureClick(jQuery('#result1'), 'click outside of nested elements: '); button.appendTo(element); measureClick(jQuery('#result2'), 'click inside of nested elements: ');
In this test I add 30 nested divs to the dom-tree and I add 100 live events. In firefox the output of this test is:
click outside of nested elements: 27.2
click inside of nested elements: 251.9
This shows that when I click on an element that is a direct child of the body, the performance is ok, but when I click an element deep down the nested divs the performance impact is much worse.
This makes it even more desirable to be able to define the context when registering a live event.
Update 2 – jQuery 1.4a1
On request I have run the same tests as above on the same machine but with the new alpha release of jQuery 1.4. The results are as follows:
test | Firefox 3.5 | IE8 | Chrome | Safari 4 |
---|---|---|---|---|
without live events | 0.3 | 1.6 | 0.2 | 0.3 |
with 10 live events | 4.5 | 9.4 | 2.1 | 2.7 |
with 100 live events | 38.5 | 79.8 | 19.6 | 19.9 |
with 200 live events | 73.9 | 162.7 | 40.8 | 39.6 |
with 200 live events and large dom | 79.5 | 167.3 | 42.2 | 39.9 |
with 100 live events with id selector | 37.7 | 90.7 | 18.9 | 20.1 |
with 100 live events with complex selector | 91.2 | 172 | 31.8 | 45.7 |
The test are not very precise. Running the tests twice will not produce the exact same results. It is clear though that the performance has been improved slightly.