The other day I've started a discussion on the jQuery dev list about event delegates and how the live() function can be improved with a few little tweaks from Zach Leatherman Blog - Performance Caveat with jQuery Selectors and Live Events

After reading at Zach's Blog I've was able to create a little plugin that I think will also be useful to those who are looking for an alternative way to bind live events to an element without first querying the document.

Example:


    $('#sidebar').delegate('li :click',callback); 

From my test in FF 3.5 and IE7 I was able to bind an event to a ul element with over 800 li elements with excellent performance!

Here's how to use the plugin:


    $(context).delegate('click',callback)  // same as live()

    $(context).delegate('li:even, li:odd :click',callback)  // supports multiple selectors

    $(context).delegate('li :click.namespace',callback)  // supports event namespace

    $(context).delegate('li:first a :click',callback)  // supports pseudo classes 

    $(context).delegate('li a :click mouseover',callback) // support future multiple event format 

The delegate method will use the same rules as that of the live() method.

Note: jQuery live() only supports single events: Unlike .bind(), only a single event can be bound in each call to the .live() method.

Here's the plugin code:


    <script type="text/javascript">
        jQuery.fn.delegate = function(event,fn) {
            var e,p,s;
            if (event.indexOf(':')) {
                s = event.substr(0,event.lastIndexOf(':'));
                event = event.replace(s+':','');
            }
            if (!s) e = this;
            else {
                p = this.selector + ' ';
                if (!s.indexOf(',')) s = p + s;
                else s = p+(s.split(/,/)).join(','+p);
                e = jQuery(document); e.selector = s
            }
            e.live(event,fn);
            return this;
        }
    </script>        

Working example:


    <script type="text/javascript">
        $(function(){
            $('#sidebar').delegate('li :mouseover',cb);
            $('#sidebar').delegate('li :mouseout',cb);
            //$('#sidebar').delegate('li:first, li:last :click',cb);
        });

        function cb (e){
            var c = (e.type=='mouseout') ? '#fff':'#ffcc00';
            $(e.target).css('background',c);
        }  
    </script>        

    <div id="sidebar">
        <ul>
            <li>item 1</li>
            <li>item 2</li>
            <li>item 3</li>
            <li>item 4</li>
            <!-- copy and paste more li elements here -->
        </ul>
    </div>        
Kevin J Pepperman
Posts: 2
Comment
live()s
Reply #2 on : Wed November 18, 2009, 00:47:24
Very nice. I have been watching that thread a lot and have tried every code sample.

This is definitely a good way to do this.

Hopefully a similar method ends up in the next jQuery core.

Thanks for sharing!
Zach Leatherman
Posts: 2
Comment
Re: jQuery Event Delegation
Reply #1 on : Wed November 25, 2009, 08:18:41
Are you sure this doesn't query the document? You're creating a jQuery object when you call the selector $(content), which by definition queries the document to fetch a result set.

Leave a Comment

Required fields are marked with *.
If you have trouble reading the code, click on the code itself to generate a new random code.