How to temporarily disable click handler in jQuery?

Let's say I have something like the following to catch a button click event:

$("#button_id").click(function() { //disable click event //do something //re-enable click event } 

How to temporarily disable the button click event until the end of the processing of the initial click occurs? Basically, my div disappears after clicking the button, but if the user clicks the button quickly several times, he processes all these clicks before the div gets a chance to disappear. I want to β€œcancel” the button so that only the first click is registered before the div disappears.

+62
javascript jquery
Aug 11 '09 at 21:31
source share
13 answers

I noticed that this post was old, but it appears on top of google and there has never been such a solution, so I decided to post it anyway.

You can simply disable the cursor events and enable them later via css. It is supported in all major browsers and may be useful in some situations.

 $("#button_id").click(function() { $("#button_id").css("pointer-events", "none"); //do something $("#button_id").css("pointer-events", "auto"); } 
+60
Aug 02 '14 at 14:12
source share

This is a more idiomatic alternative to solutions with variable artificial state:

 $("#button_id").one('click', DoSomething); function DoSomething() { // do something. $("#button_id").one('click', DoSomething); } 

One will be executed only once (before re-joining). More details here: http://docs.jquery.com/Events/one

+37
Aug 11 '09 at 21:51
source share
 $("#button_id").click(function() { if($(this).data('dont')==1) return; $(this).data('dont',1); //do something $(this).data('dont',0); } 

Recall that $ .data () will only work for items with an identifier.

+10
Aug 11 '09 at 21:38
source share

You can .off your handler with .off , but there is a warning; if you do this, simply prevent the handler from re-starting when it is already running, you need to delay the re-binding of the handler.

For example, consider this code, which uses a 5-second hot sleep to simulate something synchronous and computationally expensive, executed from a handler (say, heavy DOM manipulation):

 <button id="foo">Click Me!</div> <script> function waitForFiveSeconds() { var startTime = new Date(); while (new Date() - startTime < 5000) {} } $('#foo').click(function handler() { // BAD CODE, DON'T COPY AND PASTE ME! $('#foo').off('click'); console.log('Hello, World!'); waitForFiveSeconds(); $('#foo').click(handler); }); </script> 

This will not work. As you can see, if you try this in this JSFiddle , if you click the button when the handler is already running, the handler will be executed a second time when the first run ends. Moreover, at least in Chrome and Firefox, this will be true even if you did not use jQuery and used addEventListener and removeEventListener to add and remove a handler. The browser executes the handler after the first click, unbinds and re-binds the handler, and then processes the second click and checks if there is a click handler to execute.

To get around this, you need to delay re-binding the handler with setTimeout so that the clicks that occur during the execution of the first handler are handled before you re-hook the handler.

 <button id="foo">Click Me!</div> <script> function waitForFiveSeconds() { var startTime = new Date(); while (new Date() - startTime < 5000) {} } $('#foo').click(function handler() { $('#foo').off('click'); console.log('Hello, World!'); waitForFiveSeconds(); // Defer rebinding the handler, so that any clicks that happened while // it was unbound get processed first. setTimeout(function () { $('#foo').click(handler); }, 0); }); </script> 

You can see it in action on this modified JSFiddle .

Naturally, this is not necessary if what you are doing in your handler is already asynchronous, since then you are already transferring control to the browser and letting it reset all click events before rebinding your handler. For example, similar code would work well without calling setTimeout :

 <button id="foo">Save Stuff</div> <script> $('#foo').click(function handler() { $('#foo').off('click'); $.post( "/some_api/save_stuff", function() { $('#foo').click(handler); }); }); </script> 
+6
Jul 10 '15 at 18:04
source share

You can do this, like other people who have told you before me using the look:

A.) Use the .data of the button element to share the look variable (or just a global variable)

 if ($('#buttonId').data('locked') == 1) return $('#buttonId').data('locked') = 1; // Do your thing $('#buttonId').data('locked') = 0; 

B.) Disable mouse signals

 $("#buttonId").css("pointer-events", "none"); // Do your thing $("#buttonId").css("pointer-events", "auto"); 

C.) If it is an HTML button, you can disable it (enter [type = send] or button)

 $("#buttonId").attr("disabled", "true"); // Do your thing $("#buttonId").attr("disabled", "false"); 

But stay tuned for other topics! I have failed many times because my animation (fade out or exit) took one second. For example. fadeIn / fadeOut supports the callback function as a second parameter. If there is no other way, just do it using setTimeout(callback, delay) .

Congratulations, Thomas

+4
Apr 21 '15 at 23:00
source share

If #button_id implies a standard HTML button (such as a submit button), you can use the disabled attribute to make the button inactive in the browser.

 $("#button_id").click(function() { $('#button_id').attr('disabled', 'true'); //do something $('#button_id').removeAttr('disabled'); }); 

However, you may need to be careful, as this is the order in which these things can happen. If you use the jquery hide command, you can include "$ ('# button_id"). RemoveAttr ('disabled'); "as part of the callback, so this will not happen until the hide is complete.

[edit] example function using a callback:

 $("#button_id").click(function() { $('#button_id').attr('disabled', 'true'); $('#myDiv').hide(function() { $('#button_id').removeAttr('disabled'); }); }); 
+2
Aug 11 '09 at 21:46
source share

Try using .one()

 var button = $("#button"), result = $("#result"), buttonHandler = function buttonHandler(e) { result.html("processing..."); $(this).fadeOut(1000, function() { // do stuff setTimeout(function() { // reset `click` event at `button` button.fadeIn({ duration: 500, start: function() { result.html("done at " + $.now()); } }).one("click", buttonHandler); }, 5000) }) }; button.one("click", buttonHandler); 
 #button { width: 50px; height: 50px; background: olive; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"> </script> <div id="result"></div> <div id="button">click</div> 
0
Jul 11 '15 at 3:02
source share

it is better to use the current event and not save the handler in the global handler. I get the current event of the element, then unbind, then bind again for the handler.

 var element = $("#elemid")[0]; var tempHandler = jQuery._data(element)["events"]["click"][0].handler; $("#elemid").unbind("click"); // do the job that click not suppose to listen; $("#elemid").bind("click" , tempHandler ); 

for the whole handler

 var element = $("#elemid")[0]; var clickHandlerList = jQuery._data(element)["events"]["click"]; var handlerList = []; for(var i = 0 ; i < clickHandlerList .length ; i++) { handlerList .push(clickHandlerList [i].handler); } $("#elemid").unbind("click"); // do the job that click not suppose to listen; for(var i = 0 ; i < handlerList.length ; i++) { // return back all handler to element. $("#elemid").bind("click" , handlerList[i]); } 
0
Jan 13 '19 at 11:59
source share

I barely ran into this problem when I tried to display the boot counter while I was waiting for the function to complete. Since I added a counter to HTML, it will be duplicated every time the button is clicked, if you are not against the definition of a variable on a global scale, then this worked well for me.

  var hasCardButtonBeenClicked = ''; $(".js-mela-card-button").on("click", function(){ if(!hasCardButtonBeenClicked){ hasCardButtonBeenClicked = true; $(this).append('<i class="fa fa-circle-o-notch fa-spin" style="margin-left: 3px; font-size: 15px;" aria-hidden="true"></i>'); } }); 

Please note that all I do is declare a variable, and as long as its value is zero , the actions that follow the click will be executed, and then subsequently the value of the variable will be "true" (this can be any value if it is not empty ), further disabling the button until the browser is updated or the variable is set to null.

Looking back, it might make more sense to just set the hasCardButtonBeenClicked variable to false to start with, and then alternate between true and false if necessary.

0
May 23 '19 at 20:41
source share

This example works.




HTML code:

  <div class="wrapper"> <div class="mask">Something</div> </div> 

JQuery

  var fade = function(){ $(".mask").fadeToggle(500,function(){ $(this).parent().on("click",function(){ $(this).off("click"); fade(); }); }); }; $(".wrapper").on("click",function(){ $(this).off("click"); fade(); }); 
-one
Nov 10 '13 at
source share
 $("#button_id").click(function() { $('#button_id').attr('disabled', 'true'); $('#myDiv').hide(function() { $('#button_id').removeAttr('disabled'); }); }); 

Do not use .attr() to disable, use .prop() , this is better.

-2
12 Oct '13 at 23:43
source share

This code displays the download on the button label and sets the button to turn off the state, then after processing, re-enabling and returning the button's source text:

 $(function () { $(".btn-Loading").each(function (idx, elm) { $(elm).click(function () { //do processing if ($(".input-validation-error").length > 0) return; $(this).attr("label", $(this).text()).text("loading ...."); $(this).delay(1000).animate({ disabled: true }, 1000, function () { //original event call $.when($(elm).delay(1000).one("click")).done(function () { $(this).animate({ disabled: false }, 1000, function () { $(this).text($(this).attr("label")); }) }); //processing finalized }); }); }); // and fire it after definition } ); 
-2
Mar 18 '14 at 15:03
source share

A simple solution would be to comment out the code inside the onclick attribute:

To disable onClick:

 var code = $('#mybutton').attr("onclick"); btn.attr("onclick", '/*' + code + '*/'); 

To enable onClick:

 var code = $('#mybutton').attr("onclick"); code = code.replace(/\*\//gi, " "); code = code.replace(/\/\*/gi, " "); $('#mybutton').attr("onclick", code); 
-7
Feb 03 '12 at 16:29
source share



All Articles