Обработчик события щелчка jQuery вызывается дважды для флажка

У меня проблема со следующим кодом на странице ASPX:

<script type="text/javascript">
$(document).ready(function() {
    $('.test').click(function() {
        alert("click")
    })
});
</script>

<asp:CheckBox runat="server" Text="Checkbox XYZ" CssClass="test" ID="cb1" />

В браузере (FF3.5 / IE8) у меня следующая проблема:

  • если я нажимаю флажок (маленький квадрат), он работает как положено
  • если я щелкну по тексту флажка ("Checkbox XYZ"), то событие щелчка запускается дважды, и предупреждение отображается дважды.

Я предполагаю, что это связано с тем, как флажок отображается в HTML, например:

<span class="test">
 <input id="ctl00_c1_cb1" type="checkbox" name="ctl00$c1$cb1" checked="checked"/>
 <label for="ctl00_c1_cb1">Checkbox XYZ</label>
</span>

Как правильно настроить обработчик события click, чтобы он не вызывался дважды?

11 ответов

Решение

Хорошо прочитав мой вопрос еще раз, я нашел способ, как решить его.

Просто добавьте "input" в селектор jQuery:

<script type="text/javascript">
$(document).ready(function() {
        $('.test input').click(function() {
                alert("click")
        })
});
</script>

Я только что испытал то же самое, но не уверен, что пузыри событий вызывают мою проблему. У меня есть пользовательский элемент управления дерева, и когда элемент открыт, я использую $(id).click() прикрепить обработчик ко всем элементам определенного вида.

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

$('img.load_expand').unbind("click").click(function()
{
  // handler
});

Я думаю, это потому, что <label> с for атрибут вызывает событие клика <input type="radio"> или же <input type="checkbox"> элемент, связанный с при нажатии.

Итак, в вашем коде jQuery вы устанавливаете обработчик события click для обоих <label> и <input> внутри <span class="test">, При нажатии на <label>, обработчик события щелчка, который вы настроили для метки, будет выполнен, затем обработчик события щелчка, настроенный на <input> выполнится, когда метка вызовет событие нажатия на <input>,

$(document).ready(function() {
    $('.test').click(function(event) {
                    event.stopImmediatePropagation();
                    alert("Click");
                    })
                 }
              );

Я смог заставить свой код работать, остановив распространение событий. Это не повлияло на изменение статуса чекбокса.

Просто используйте.mouseup вместо.click

Решено: это для работы с Firefox 3.6.12 и IE8.

$(function(){
        $("form input:checkbox").unbind("click")
        .click(function(){
            val = $(this).val();
            alert(val);
        })
    }

Хитрость заключается в unbind("click"). прежде чем связать это с .click(fn); это отключит одно и то же событие, чтобы выстрелить дважды.

Обратите внимание, что событие "изменение" не будет обманутым при первом включении флажка. Поэтому вместо этого я использую "щелчок".

То, что вы видите, - это пузыри событий. Событие click сначала обрабатывается меткой, а затем передается флажку. Вы получаете одно предупреждение для каждого. Чтобы предотвратить появление событий, вам нужно вернуть false в ваш обработчик кликов.

$(document).ready(function() {
        $('.test').click(function() {
                alert("Click");
                return false;
        })
});

Однако, хотя это предотвращает возникновение событий, оно также имеет нежелательный побочный эффект, заключающийся в предотвращении изменения состояния флажка. Так что вам нужно обойти это.

Я столкнулся с той же проблемой с событием щелчка и нашел эту статью. По сути, если у вас есть несколько готовых к работе с документами функций jQuery внутри <body></body>теги, вы можете получить несколько событий. Исправление, конечно, состоит в том, чтобы не делать этого, или отсоединять событие click и перепривязывать его, как отмечено выше. Иногда, с несколькими библиотеками javascript, может быть трудно избежать нескольких document.ready(), поэтому отмена привязки - хороший обходной путь.

<code>
$('#my-div-id').unbind("click").click(function()
  {
    alert('only click once!');
  }
</code>

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

Когда вы добавляете код ASP, как:

<asp:CheckBox runat="server" Text="Checkbox XYZ" CssClass="test" ID="cb1" />

проблема в том, что <asp:CheckBox ...> это не элемент управления html, это просто что-то ASP, созданное из извращенного ума какого-то придуманного психа, поэтому браузер получит что-то еще.

Браузер получит что-то вроде:

<span class="test">
    <input id="garbageforYourId_cb1" type="checkbox" name="garbage$moregarbage$cb1"/>
    <label for="evenMoreGarbage_cb1">Checkbox XYZ</label>
</span>

Одно из многих возможных решений:

Браузер получает промежуток, который содержит поле ввода и метку для него с вашим текстом. Поэтому мое решение для этого было бы что-то вроде:

$('.test > :checkbox').click(function() {
    if ($(this).attr("checked")) {
        alert("checked!!!");
    } else {
        alert("non checked!!!");
    }
});

Что там произошло? Этот селектор $('.test > :checkbox') означает: найдите элементы с классом "test" и принесите любой флажок, который он содержит.

У меня была такая же проблема с селектором. И в конечном итоге использовать off()функция.

      $('body').off('click').on('click', '<your selector>', function(){
    // Your code                
});

Функция запускается дважды. Один раз изнутри, а затем снова вызывается изнутри. Просто добавьте оператор возврата в конце.

<script type="text/javascript">
$(document).ready(function() {
    $('.test').click(function() {
        alert("click");
        return false;
    })
});
</script>

<asp:CheckBox runat="server" Text="Checkbox XYZ" CssClass="test" ID="cb1" />

Это отлично сработало для меня.

Другие вопросы по тегам