calumbrodie
calumbrodie

Reputation: 4792

$.live() and $.die() binding and unbinding

I am having some trouble with jquery's live and die methods.

http://jsfiddle.net/fC5Nr/4/

//bind above function to clicking a
$('a').live('click', functionThatWaitsFiveSeconds)

I need to attach an event handler to clicking a link - and I want to unbind the handler while the function is running to prevent the function running over and over before it is complete (function is performing a ajax request then handling the response.

I can do all of the above just fine.

However, because the above handler is attached to a (a) tag I need to return false (to prevent the link from being followed). To do this I need to bind a different function to handle clicks and return false.

I need to know how to unbind my complicated function - while keeping my simple (return false) bound at all times.

The above fiddle should work, but after unbinding the event handler, it doesn't bind again? I've tried a few combinations of namespacing etc but cannot get this together.

Upvotes: 2

Views: 3359

Answers (3)

no.good.at.coding
no.good.at.coding

Reputation: 20371

If you don't mind this approach (using a marker class) then this might be what you're looking for. No messy binding and unbinding of events - while trying to figure out a way to answer you question, I found it to be quite a bother to track everything that was bound/unbound on the page and I reached a stage once where I had multiple loaders appear for a single click.

$(document).ready(function(){
    function functionThatWaitsFiveSeconds(el, e){
        //stop default link click events
        e.preventDefault();
        e.stopPropagation();

        if($(el).hasClass('loadingMarkerClass')) {
           return false; //we're currently processing this element already
       }
        $(el).addClass('loadingMarkerClass'); //add a dummy, marker class to indicate we're showing a loader for this element

        var loader = $('<div class="loader">Loading: ' + $(el).html() + '</div>');
        $('#content').append(loader);
        loader.animate({'width': '500'}, 5000, function(){
            loader.remove();
            $(el).removeClass('loadingMarkerClass');
        });
    }

    //bind above function to clicking a
    $('a').live('click', function(e){functionThatWaitsFiveSeconds(this, e)});

});

Upvotes: 1

Mark Coleman
Mark Coleman

Reputation: 40863

Update got it working

   function denyRest() {
        $("body").append("<h1>return false</h1>");
        return false;
    }
    function functionThatWaitsFiveSeconds() {
        $('a').die('click.thing', functionThatWaitsFiveSeconds);
        var loader = $('<div class="loader">doing some stuff</div>');
        $('#content').append(loader);
        loader.animate({
            'width': '500'
        }, 5000, function() {
            loader.remove();
            $('a').die('click.otherthing', denyRest).live('click.thing', functionThatWaitsFiveSeconds).live('click.otherthing', denyRest);
        });
    }

    $('a').live('click.thing', functionThatWaitsFiveSeconds);
    $('a').live('click.otherthing', denyRest);

Updated fiddle.

I believe The issue was this.

  1. Use live to attach the handler to wait 5 seconds
  2. Use live to attach a handler that returns false to stop events.
  3. Click anchor tag, which removes the wait 5 second handler.
  4. Clicks to the anchor tag at this time will be stopped via the return false statement.
  5. NOW the return false statement is first. Once we rebind the wait 5 seconds handler it is in second place to be ran but gets denied by the return false handler.
  6. Fixed this to trash both handlers and rebind them in the correct order.

Upvotes: 2

Nikhil
Nikhil

Reputation: 3384

Actually the easiest way to achieve this will be to remove the href tag on the anchor link.

So your code becomes

$(document).ready(function(){

    function functionThatWaitsFiveSeconds(){
       // $('a').die('click', functionThatWaitsFiveSeconds);
        var loader = $('<div class="loader">doing some stuff</div>');
         $(this).attr("href","#");
            $('#content').append(loader)
            loader.animate({'width': '500'}, 5000, function(){
                loader.remove();
                //now rebind click handler
         //       $('a').live('click', functionThatWaitsFiveSeconds)
            })
    }



    //bind above function to clicking a
    $('a').live('click', functionThatWaitsFiveSeconds)

    //need to return false at all times to prevent folowing link
    $('a').live('click',function(){
        return false;    
    })
})

Upvotes: 0

Related Questions