How to temporarily disable a click handler in jQuery?

前端 未结 12 1992
不思量自难忘°
不思量自难忘° 2020-12-04 14:02

Say I have something like the following to trap the click event of a button:

$(\"#button_id\").click(function() {
  //disable click event
  //do something
           


        
相关标签:
12条回答
  • 2020-12-04 14:28

    I just barely ran into this problem when trying to display a loading spinner while I waited for a function to complete. Because I was appending the spinner into the HTML, the spinner would be duplicated each time the button was clicked, if you're not against defining a variable on the 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>');
            }    
        });
    

    Notice, all I'm doing is declaring a variable, and as long as its value is null, the actions following the click will occur and then subsequently set the variables value to "true" (it could be any value, as long as it's not empty), further disabling the button until the browser is refreshed or the variable is set to null.

    Looking back it probably would have made more sense to just set the hasCardButtonBeenClicked variable to "false" to begin with, and then alternate between "true" and "false" as needed.

    0 讨论(0)
  • 2020-12-04 14:32

    This example work.


    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();     
        });
    
    0 讨论(0)
  • 2020-12-04 14:34
    $("#button_id").click(function() {
      if($(this).data('dont')==1) return;
      $(this).data('dont',1);
      //do something
      $(this).data('dont',0);
    }
    

    Remeber that $.data() would work only for items with ID.

    0 讨论(0)
  • 2020-12-04 14:37

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

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

    One will only execute once (until attached again). More info here: http://docs.jquery.com/Events/one

    0 讨论(0)
  • 2020-12-04 14:42

    Try utilizing .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 讨论(0)
  • 2020-12-04 14:43

    You can unbind your handler with .off, but there's a caveat; if you're doing this just prevent the handler from being triggered again while it's already running, you need to defer rebinding the handler.

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

    <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 won't work. As you can see if you try it out in this JSFiddle, if you click the button while the handler is already executing, the handler will execute a second time once the first execution finishes. What's more, at least in Chrome and Firefox, this would be true even if you didn't use jQuery and used addEventListener and removeEventListener to add and remove the handler instead. The browser executes the handler after the first click, unbinding and rebinding the handler, and then handles the second click and checks whether there's a click handler to execute.

    To get around this, you need to defer rebinding of the handler using setTimeout, so that clicks that happen while the first handler is executing will be processed before you reattach 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 this in action at this modified JSFiddle.

    Naturally, this is unnecessary if what you're doing in your handler is already asynchronous, since then you're already yielding control to the browser and letting it flush all the click events before you rebind your handler. For instance, code like this will work fine without a setTimeout call:

    <button id="foo">Save Stuff</div>
    <script>
        $('#foo').click(function handler() {
            $('#foo').off('click');
            $.post( "/some_api/save_stuff", function() {
                $('#foo').click(handler);
            });
        });
    </script>
    
    0 讨论(0)
提交回复
热议问题