October 2, 2012

Why bind and unbind don't work as expected

Question by Ayen

I was originally doing this:

$('div.ocontainer').each(function() {
    var o = $(this);
    var newCode = $(this).attr('id');
    if (o.parents('.ocontainer').length != 0) {
        var oldCode = o.parents('.ocontainer').attr('id');
        console.log('unbinding '+oldCode);
        $('#'+oldCode+' a').each(function() {
            $(this).unbind('click')
            })
    }
    console.log('binding '+newCode);
    $('#'+newCode+' a').each(function() {
        $(this).click(function() {
            decideStMethod(newCode);
        })
    })
})

…but the unbind was not working. I ended up with the original code being passed in the click function. So I changed to using name spaced events:

$('div.ocontainer').each(function() {
    var o = $(this);
    var newCode = $(this).attr('id');
    if (o.parents('.ocontainer').length != 0) {
        var oldCode = o.parents('.ocontainer').attr('id');
        console.log('unbinding '+oldCode);
        $('#'+oldCode+' a').each(function() {
            $(this).unbind('click.'+oldCode)
            })
    }
    console.log('binding click.'+newCode);
    $('#'+newCode+' a').each(function() {
        $(this).bind('click.'+newCode,function() {
            decideStMethod(newCode);
        })
    })
})

…and now the unbind works but the subsequent bind does not. Note, though, that the line that is doing the bind DOES work if it’s not subsequent, that is, if it is not preceded by an unbind.

The use of this is that first a region of the page is processed, and the binding is done on the links within it. Then, the subregions are processed, and if one of them has its own code, the region’s handler must be unbound and replaced with the subregion’s. The reason for all of this is that the subregions are placed in the region dynamically, so what they will be is never known in advance. Oh, and just in case it matters, this is jQuery 1.72

So:

<div id="region" class="ocontainer">
   <div id="subregion" class="ocontainer">
      <a>

On the processing of region, the link is bound to click.region and a function passing ‘region’. Then, click.region should be unbound, which it is, and click.subregion bound in its place with a function passing ‘subregion’, which does not happen.

Answer by Starx

First thing is first, bind() and unbind() are deprecated functions. Use .on() and .off() instead.

Here is an example with some improvements too.

$('div.ocontainer').each(function() {
    var o = $(this);
    var newCode = o.attr('id'); //Use cached version instead
    if (o.parents('.ocontainer').length != 0) {
        var oldCode = o.parents('.ocontainer').attr('id');
        console.log('unbinding '+oldCode);
        $('#'+oldCode+' a').each(function() {
            o.off('click', "#"+oldCode); //Turn off the event handler
        })
    }
    console.log('binding click.'+newCode);
    $('#'+newCode+' a').each(function() {
        $(this).on('click', "#" + newCode, function() {
            decideStMethod(newCode);
        })
    })
})

Author: Nabin Nepal (Starx)

Hello, I am Nabin Nepal and you can call me Starx. This is my blog where write about my life and my involvements. I am a Software Developer, A Cyclist and a Realist. I hope you will find my blog interesting. Follow me on Google+

...

Please fill the form - I will response as fast as I can!