2

The code below I use to create a sliding menu. I need to know how to unbind the function attached to the click event and re-attach it some other time. (using jQuery 1.7.2)

$(document).ready(function(){
    $('.section').hide();
    $('.header').click(function(){
      if($(this).next('.section').is(':visible'))
      {
        $('.section:visible').slideUp()              
        $('.arrows:visible').attr("src","right.gif")
      }
      else
      {
        $('.section').slideUp();
        $(this).next('.section').slideToggle();
        $(this).find('.arrows').attr("src","down.gif")
    });
});

The code below is what I have so far

$('#printVers').click(function(){
   if($('#formVersion').val() != "Print")
   {
     $('.header').unbind('click');
   }
   else
   {
     //else re-attach functionality?
   }
});

Thanks

Mark Walters
  • 12,060
  • 6
  • 33
  • 48
  • So you simply want to take the click event handler for `$('.header')` on or off based on some formVersion value? – Tejs Apr 27 '12 at 14:52
  • Well yes, but how do i refer to the click function in the first code block to re-attach it? – Mark Walters Apr 27 '12 at 14:54
  • possible duplicate of [How to temporarily disable a click handler in jQuery?](http://stackoverflow.com/questions/1263042/how-to-temporarily-disable-a-click-handler-in-jquery) – Fabrizio Calderan Apr 27 '12 at 14:55
  • Maybe i should try and re-engage my brain with coffee and food rather than ask silly questions on a Friday afternoon, not only was it a silly question but one that has already been asked :( – Mark Walters Apr 27 '12 at 14:59

7 Answers7

7

Simply make a named function. You can go low tech here and back to basics to unbind and reattach specific events.

function doStuff()
{
    if($(this).,next('.section').is(':visible'))
        ...
}

$('.header').on('click', doStuff);
$('.header').off('click', doStuff);
Tejs
  • 40,736
  • 10
  • 68
  • 86
  • Damn, you beat me by 30 seconds XD – DangerMonkey Apr 27 '12 at 14:57
  • It's so simple it's not even funny. Thanks Tejs – Mark Walters Apr 27 '12 at 15:00
  • It would be nice to be able to get a handle of the last bound function without having to use the fn name. Like `elem.on('click', myfn)`. Then somewhere else completely unrelated we could have `var fn = elem.lastClickHandler()`, `elem.off('click', fn)`, `// some code without handler`, `elem.on('click', fn)` – AlexMorley-Finch Jan 21 '14 at 10:59
2

Instead of unbind and re-bind, I suggest you to add a simple class to .header and check for the class in the click handler. See below,

$('#printVers').click(function(){
   if($('#formVersion').val() != "Print")
   {
     $('.header').addClass('dontClick');
   } else  {
     $('.header').removeClass('dontClick');
   }
});

And in your .header click handler,

$('.header').click(function(){
     if ($(this).hasClass('dontClick')) {
        return false;
     }
     //rest of your code

If you insist on having a unbind and bind, then you can move the handler to a function and unbind/bind the function any number of time..

Aaron Miler
  • 869
  • 11
  • 22
Selvakumar Arumugam
  • 79,297
  • 15
  • 120
  • 134
  • Thanks i also like this version, again something i hadn't thought of doing. – Mark Walters Apr 27 '12 at 15:01
  • @MarkWalters bind/unbinding a event handler is lot of work than simply adding and removing a class. This is a common technique, but again it is up to you to choose which method you want to follow. – Selvakumar Arumugam Apr 27 '12 at 15:03
  • How is Tjes idea of using `.on()` and `.off()` and naming the function a lot of hassle? I like both ideas and i did upvote your answer! :) – Mark Walters Apr 27 '12 at 15:10
  • @MarkWalters upvote doesn't matter.. I was just saying that bind/rebind an event handler is expensive than adding a class and removing a class. – Selvakumar Arumugam Apr 27 '12 at 15:11
  • What do you mean by expensive? because you said it was a lot of work before, to which i disagree i actually think for me to implement (although minimal) there is slightly more to do with your code? – Mark Walters Apr 27 '12 at 15:13
  • @MarkWalters expensive is not always lengthy code. Check out this simple jsPerformance comparision >> http://jsperf.com/bind-rebind-vs-addclass-removeclass << -> $.noop is an empty function. Again, I am just giving you a suggestion and not trying to force you to follow any specific implementation. – Selvakumar Arumugam Apr 27 '12 at 15:24
  • I know you aren't trying to force me, Thank you for the explanation i will take a look at that link. :) – Mark Walters Apr 27 '12 at 15:29
1

You can try something like this.

$('#printVers').click(function(){
   if($('#formVersion').val() != "Print")
   {
       $('.header').addClass('clickDisabled');
   }
   else
   {
       $('.header').removeClass('clickDisabled');
   }
});

And then in the click handler check for this class.

$(document).ready(function(){
    $('.section').hide();
    $('.header').click(function(){
        if(!$(this).hasClass('clickDisabled')){
            ...
            ...
        }
    });
});
ShankarSangoli
  • 69,612
  • 13
  • 93
  • 124
0

Why not make that top section a function, and then call it in your else statement?

Adam Sweeney
  • 386
  • 3
  • 15
0

You could try setting a variable as a flag. var canClick = ($('#formVersion').val() != 'Print'); Then in the click handler for your .header elements check to see if canClick is true before executing your code.

If you still want to remove the handler you can assign the events object to a variable. var eventObj = #('.header').data('events'); That will give you an object with all the handlers assigned to that object. To reassign the click event it would be like $('.header').bind('click', eventObj.click[0]);

hradac
  • 2,431
  • 1
  • 19
  • 21
0

After trying so hard with bind, unbind, on, off, click, attr, removeAttr, prop I made it work. So, I have the following scenario: In my html i have NOT attached any inline onclick handlers.

Then in my Javascript i used the following to add an inline onclick handler:

$(element).attr('onclick','myFunction()');

To remove this at a later point from Javascript I used the following:

$(element).prop('onclick',null);

This is the way it worked for me to bind and unbind click events dinamically in Javascript. Remember NOT to insert any inline onclick handler in your elements.

bboydflo
  • 907
  • 1
  • 15
  • 24
  • 1
    Couple of issues with this, firstly you're using two different methods to set and nullify the onclick handler. What is wrong with using `.prop` for both? secondly It's not good practice to pass a "string" reference to a function as you did in your first line, as far as i'm aware this leads to a call to `eval()` which is evil! :) – Mark Walters Mar 21 '14 at 08:49
  • 2
    @MarkWalters - in short, I think he uses attr correctly to set the onclick, and is forced to use prop to remove by IE. From the jQuery "removeattr" docs: "Note: Removing an inline onclick event handler using .removeAttr() doesn't achieve the desired effect in Internet Explorer 6, 7, or 8. To avoid potential problems, use .prop() instead:" – Tony Carbone May 09 '14 at 05:46
-2

You could put all the code under the .click in a separated function

function headerClick(){
  if($(this).next('.section').is(':visible'))
  {
    $('.section:visible').slideUp()              
    $('.arrows:visible').attr("src","right.gif")
  }
  else
  {
    $('.section').slideUp();
    $(this).next('.section').slideToggle();
    $(this).find('.arrows').attr("src","down.gif")
  }
}

and then bind it like this:

$(document).ready(function(){
    $('.section').hide();
    $('.header').click(headerClick);
});

$('#printVers').click(function(){
   if($('#formVersion').val() != "Print")
   {
       $('.header').unbind('click');
   }
   else
   {
       $('.header').click(headerClick);
   }
});
DangerMonkey
  • 385
  • 1
  • 5