如何暂时禁用jQuery中的单击处理程序?

时间:2009-08-11 21:31:06

标签: javascript jquery

说我有类似以下内容来捕获按钮的click事件:

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

如何暂时禁用按钮的click事件,直到原始点击处理结束?单击按钮后,我基本上消除了div,但如果用户快速点击按钮几次,它会在div有机会消失之前处理所有这些点击。我想“去抖动”按钮,这样只有在div消失之前才能注册第一次点击。

12 个答案:

答案 0 :(得分:60)

我注意到这篇文章很老但是它在google上显得很高,而且从未提供过这种解决方案,所以无论如何我决定发布它。

您可以暂停游标事件,稍后再通过css启用它们。它在所有主流浏览器上都受支持,在某些情况下可能会很有用。

$("#button_id").click(function() {

   $("#button_id").css("pointer-events", "none");
   //do something
   $("#button_id").css("pointer-events", "auto");
}

答案 1 :(得分:37)

这是人工状态变量解决方案的更惯用的替代方案:

$("#button_id").one('click', DoSomething);

function DoSomething() {
  // do something.

  $("#button_id").one('click', DoSomething);
}

一个只会执行一次(直到再次附加)。更多信息:http://docs.jquery.com/Events/one

答案 2 :(得分:10)

$("#button_id").click(function() {
  if($(this).data('dont')==1) return;
  $(this).data('dont',1);
  //do something
  $(this).data('dont',0);
}

请记住,$ .data()仅适用于带有ID的项目。

答案 3 :(得分:6)

你可以用.off取消绑定你的处理程序,但有一个警告;如果你这样做只是阻止处理程序在它已经运行时再次被触发,你需要推迟重新绑定处理程序。

例如,考虑一下这段代码,它使用5秒热睡眠来模拟处理程序中的同步和计算成本高昂的东西(比如说重型DOM操作):

<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 JSFiddle中尝试一样,如果在处理程序已执行时单击按钮,则处理程序将在第一次执行完成后再次执行。更重要的是,至少在Chrome和Firefox中,即使您没有使用jQuery并使用addEventListenerremoveEventListener来添加和删除处理程序,情况也是如此。浏览器在第一次单击,解除绑定和重新绑定处理程序后执行处理程序,然后处理第二次单击并检查是否有要执行的单击处理程序。

要解决此问题,您需要使用setTimeout推迟重新绑定处理程序,以便在执行第一个处理程序时发生的点击将在重新附加处理程序之前处理。

<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>

您可以在this modified JSFiddle处看到这一点。

当然,如果您在处理程序中执行的操作已经是异步的,那么这是不必要的,因为那时您已经对浏览器产生控制权并让它在重新绑定处理程序之前刷新所有单击事件。例如,像这样的代码可以在没有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>

答案 4 :(得分:4)

你可以像我之前告诉你的其他人那样做:

A。)使用button元素的.data来共享一个外观变量(或一个全局变量)

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

B。)禁用鼠标信号

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

C。)如果是HTML按钮,你可以禁用它(输入[type = submit]或按钮)

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

但请注意其他线程!我失败很多次因为我的动画(淡入或淡出)花了一秒钟。 例如。 fadeIn / fadeOut支持回调函数作为第二个参数。 如果没有其他办法,只需使用setTimeout(callback, delay)

电贺, 托马斯

答案 5 :(得分:2)

如果#button_id意味着标准的HTML按钮(如提交按钮),则可以使用“禁用”属性使按钮对浏览器不活动。

$("#button_id").click(function() {
    $('#button_id').attr('disabled', 'true');

    //do something

     $('#button_id').removeAttr('disabled');
});   

然而,您可能需要注意的是这些事情可能发生的顺序。如果您使用的是jquery hide命令,则可能需要包含“$('#button_id')。removeAttr('disabled');”作为回调的一部分,以便在隐藏完成之前不会发生。

[编辑]使用回调的函数示例:

$("#button_id").click(function() {
    $('#button_id').attr('disabled', 'true');
    $('#myDiv').hide(function() { $('#button_id').removeAttr('disabled'); });
});   

答案 6 :(得分:0)

尝试使用.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>

答案 7 :(得分:0)

最好使用当前事件,不要在全局处理程序中保存处理程序。 我得到当前元素事件,然后取消绑定,然后再次绑定。 一个处理程序。

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 );

所有处理程序

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]);
}

答案 8 :(得分:0)

我在等待功能完成时尝试显示加载微调器时,我几乎没有遇到这个问题。因为我将微调器附加到HTML中,所以每次单击按钮时都会复制微调器,如果您不反对在全局范围内定义变量,那么这对我来说效果很好。

    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>');
        }    
    });

注意,我所做的只是声明一个变量,只要其值为 null ,就会发生单击后的操作,然后将变量的值设置为“ true”( (可以为任何值,只要它不为空),就可以进一步禁用该按钮,直到刷新浏览器或将该变量设置为null。

回顾一下,将hasCardButtonBeenClicked变量设置为“ false”开始可能更有意义,然后根据需要在“ true”和“ false”之间交替。

答案 9 :(得分:-1)

这个例子工作。


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();     
    });

答案 10 :(得分:-2)

$("#button_id").click(function() {
    $('#button_id').attr('disabled', 'true');
    $('#myDiv').hide(function() { $('#button_id').removeAttr('disabled'); });
}); 

不要使用.attr()来禁用,使用.prop(),这样会更好。

答案 11 :(得分:-2)

此代码将在按钮标签上显示加载,并设置按钮以禁用状态,然后在处理后重新启用并返回原始按钮文本:

$(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
    }
   );