Подтвердить что ты не робот

Как временно отключить обработчик кликов в jQuery?

Скажем, у меня есть что-то вроде следующего, чтобы уловить событие нажатия кнопки:

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

Как временно отключить событие нажатия кнопки до тех пор, пока не произойдет окончание обработки исходного клика? В основном у меня исчезает div после нажатия кнопки, но если пользователь нажимает кнопку быстро несколько раз, он обрабатывает все эти клики, прежде чем div получит шанс исчезнуть. Я хочу "отменить" кнопку, чтобы только первый клик регистрировался до исчезновения div.

4b9b3361

Ответ 1

Я заметил, что это сообщение было старым, но оно появляется сверху на google, и такого решения никогда не предлагалось, поэтому я решил опубликовать его в любом случае.

Вы можете просто отключить события курсора и включить их позже через css. Он поддерживается во всех основных браузерах и может оказаться полезным в некоторых ситуациях.

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

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

Ответ 2

Это более идиоматическая альтернатива решениям с переменным искусственным состоянием:

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

function DoSomething() {
  // do something.

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

Один будет выполняться только один раз (до повторного присоединения). Подробнее здесь: http://docs.jquery.com/Events/one

Ответ 3

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

Вспомните, что $.data() будет работать только для элементов с идентификатором.

Ответ 4

Вы можете .off вашего обработчика с помощью .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>

Это не сработает. Как вы можете видеть, если вы попробуете это в этом JSFiddle, если вы нажмете кнопку, когда обработчик уже выполняется, обработчик будет выполнен второй раз, когда закончится первое выполнение. Более того, по крайней мере в Chrome и Firefox, это будет верно, даже если вы не использовали jQuery и использовали addEventListener и removeEventListener для добавления и удаления обработчика. Браузер выполняет обработчик после первого щелчка, отменяет привязку и повторную привязку обработчика, а затем обрабатывает второй щелчок и проверяет, есть ли обработчик щелчка для выполнения.

Чтобы обойти это, вам нужно отложить повторную привязку обработчика с помощью 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>

Вы можете увидеть это в действии на этом модифицированном 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>

Ответ 5

Вы можете сделать это, как и другие люди, которые до меня говорили вам, используя внешний вид:

A.) Используйте .data элемента кнопки для совместного использования переменной look (или просто глобальной переменной)

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, вы можете ее отключить (введите [тип = отправить] или кнопку)

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

Но следите за другими темами! Я терпел неудачу много раз, потому что моя анимация (затухание или выход) заняла одну секунду. Например. fadeIn/fadeOut поддерживает функцию обратного вызова в качестве второго параметра. Если нет другого способа, просто сделайте это, используя setTimeout(callback, delay).

Поздравил, Томас

Ответ 6

Если #button_id подразумевает стандартную кнопку HTML (например, кнопку отправки), вы можете использовать атрибут "disabled", чтобы сделать кнопку неактивной в браузере.

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

    //do something

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

Однако вам может потребоваться осторожность, так это порядок, в котором эти вещи могут случиться. Если вы используете команду jquery hide, вы можете включить "$ ('# button_id" ). RemoveAttr (' disabled '); " как часть обратного вызова, так что это произойдет не до тех пор, пока скрытие не будет завершено.

[edit] пример функции с использованием обратного вызова:

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

Ответ 7

Попробуйте использовать .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>

Ответ 8

лучше использовать текущее событие и не сохранять обработчик в глобальном обработчике. я получаю текущее событие элемента, затем отменяю привязку, затем снова связываю для обработчика.

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

Ответ 9

Я едва столкнулся с этой проблемой, когда пытался отобразить загрузочный счетчик, пока ждал завершения функции. Поскольку я добавлял счетчик в 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>');
        }    
    });

Обратите внимание, все, что я делаю, это объявляю переменную, и, пока ее значение равно нулю, будут выполняться действия, следующие за щелчком, а затем впоследствии значение переменной будет равно "true" (это может быть любое значение, если оно не пусто), дальнейшее отключение кнопки до тех пор, пока браузер не обновится или для переменной не будет задано значение null.

Оглядываясь назад, возможно, имело бы больше смысла просто установить для переменной hasCardButtonBeenClicked значение "false" для начала, а затем при необходимости чередовать "true" и "false".

Ответ 10

Этот пример работает.


Код HTML:

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

Ответ 11

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

Не используйте .attr() для отключения, используйте .prop(), это лучше.

Ответ 12

Этот код отображает загрузку на ярлыке кнопки и устанавливает кнопку для отключения состояния, затем после обработки, повторного включения и возврата исходного текста кнопки:

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

Ответ 13

Простым решением было бы прокомментировать код внутри атрибута onclick:

Чтобы отключить onClick:

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

Чтобы включить onClick:

var code = $('#mybutton').attr("onclick");
code = code.replace(/\*\//gi, " ");
code = code.replace(/\/\*/gi, " ");
$('#mybutton').attr("onclick", code);