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

Дважды нажатие кнопки Jquery вызывает щелчок по ярлыку html.

У меня есть контейнер div, который содержит html флажок и его метку. Используя jquery, я хотел вызвать событие click, когда кто-то нажимает на метку в этом контейнере.

Я вижу, что jquery click event триггеры дважды, когда я нажимаю на метку!

Для целей тестирования я активировал событие click on checkbox вместо метки и здесь триггеры события щелчка на флажке только один раз, как и должно быть.

Вот скрипка. http://jsfiddle.net/AnNvJ/2/

<tr>
    <td>
        <div id="test">
            <label>
                <input type="checkbox" id="1" />demo1</label>
            <label>
                <input type="checkbox" id="2" />demo2</label>
            <label>
                <input type="checkbox" id="3" />demo3</label>
        </div>
    </td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
</tr>

JQuery

$(document).ready(function () {

    $('#test label').live('click', function (event) {
        alert('clicked');
    });


    $('#test checkbox').live('click', function (event) {
        alert('clicked');
    });

});
4b9b3361

Ответ 1

Один из $('#test checkbox') никогда не вызывается, потому что у вас нет тега с именем checkbox.

И в зависимости, если вы нажмете на флажок или метку, обратный вызов для $('#test label') вызывается один или два раза причиной барботажа, потому что элемент ввода является частью метки и является одним объединением и поэтому также получил событие, если метка нажата (это не пузырь, вы не можете сделать event.stopPropagation()).

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

 $('#test label').live('click', function (event) {
        event.stopPropagation(); //<-- has no effect to the described behavior
        console.log(event.target.tagName);
 });

Нажмите на метку:

LABEL
  ВХОД

Нажмите на вход:

ВХОД

ИЗМЕНИТЬ Если вы хотите обработать только щелчок на label, а не флажок, и вы не можете изменить структуру html, вы можете просто проигнорировать событие элемента input.

Любой из этих способов:

$('#test label').live('click', function (event) {
    if( event.target.tagName === "LABEL" ) {
         alert('clicked');
    }
});

Или используя jQuery для тестирования:

$('#test label').live('click', function (event) {
    if( $(event.target).is("label") ) {
         alert('clicked');
    }
});

Ответ 2

Это потому, что вы помещаете ввод внутри метки, поэтому, когда вы нажимаете на флажок, вы также нажимаете на каждого родителя (который называется bubbling) EDIT, кредит на @t.niese: на самом деле нет пузырей здесь, потому что проблема заключается в том, когда вы нажимаете на метку, и она только пузырится вверх.

Чтобы предотвратить событие двойного щелчка, но также установите флажок, который вы можете использовать:

$(document).ready(function () {

    $('#test label').on('click', function (event) {
        event.preventDefault();
        var $check = $(':checkbox', this);
        $check.prop('checked', !$check.prop('checked'));
        alert('clicked label');
    });


    $('#test :checkbox').on('click', function (event) {
        event.stopPropagation();
        alert('clicked checkbox');
    });
});

FIDDLE

Также предпочитайте использование $.on и обратите внимание на использование :checkbox селектор или [type="checkbox"], который в соответствии с JQuery API быстрее и более совместим (селектора атрибутов)

event.preventDefault() останавливает каждое действие, выполняемое браузером для собственного тега event.stopPropagation() предотвращает появление пузырьков и любые родительские обработчики извещения о событии

Ответ 3

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

Причина, по которой есть два клика, связана с барботажем событий.

Нажатие на метку, связанную с вводом, вызывает два события нажатия кнопки. Первое событие щелчка запускается для метки. Обработка по умолчанию этого события щелчка вызывает событие второго клика, которое будет вызвано для соответствующего входа. Если вход является потомком метки, второе событие щелчка пузырится до метки. Вот почему обработчик события click для метки вызывается дважды.


Поэтому один из способов решения этой проблемы (как обнаружено OP) - не помещать входной сигнал внутри элемента метки. Там все равно будут два события кликов, но второе событие клика не будет пузыриться с входа на метку.

Если вход не находится внутри метки, атрибут "для" может использоваться для связывания метки с вводом. Атрибут "для" должен быть установлен на значение "id" для ввода.

<input type="checkbox" id="1" />
<label for="1">demo1</label>

Другим решением было бы остановить событие от пузырьков от входа:

$('#test :checkbox').on('click', function(event) {
    event.stopPropagation();
});

$('#test label').on('click', function() {
    alert('clicked');
});

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

$('#test label').on('click', function(event) {
    if (event.target == this) {
        alert('clicked');
    }
});

Ответ 4

Вы ДОЛЖНЫ использовать preventDefault в своей метке и stopPropagation в своем флажке:

http://jsfiddle.net/uUZyn/5/

Код:

$(document).ready(function () {

    $('#test label').on('click', function (event) {
      event.preventDefault();        
      alert('clicked label');
      var ele = $(this).find('input');
    if(ele.is(':checked')){
      ele.prop('checked', false);        
    }else{
      ele.prop('checked', true);
    }
  });

  $('#test :checkbox').on('click', function (event) {
    event.stopPropagation();
    alert('clicked checkbox');
  });
});

Таким образом вы избегаете поведения @t.niese объясняет

Спасибо предыдущим ответам, я бы не выяснил их без них: D.

Update

Как указывает t.niese, вот ответ, который я обновил с поведением:

http://jsfiddle.net/uUZyn/6/

Просто добавлено поведение проверки после использования preventDefault XD

Ответ 5

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

Например:

<div id="test">
    <label for="checkbox1">
        <input type="checkbox" name="checkbox1" id="1" />demo1</label>
    <label for="checkbox2">
        <input type="checkbox" name="checkbox2" id="2" />demo2</label>
    <label for="checkbox3">
        <input type="checkbox" name="checkbox3" id="3" />demo3</label>
 </div>

Нет необходимости в JavaScript.

Ответ 6

Это происходит, главным образом, при запуске 'click' для элемента X, имеющего дочерний элемент Y, и когда пользователь нажимает на Y.

Событие, порожденное от элемента с кликом, является нежелательным событием, которое вам не нужно.

У вас есть два варианта избежать этого двойного запуска...

1) Используйте $('selector'). triggerHandler ('any_standard_event_name'). Здесь стандартное событие означает 'click', 'change', 'hover' и т.д. (я никогда не пробовал эту опцию)

2) Используйте имя настраиваемого события. например. $( 'Селектор') триггера ( 'my.click');.

Подробнее о http://api.jquery.com/trigger/

Ответ 7

Что касается моего случая и того факта, что я использую md-button для материального дизайна, приведенные выше предложения не очень хорошо работали, потому что это резко уменьшало площадь области, получающей отпечаток пальца на моем андроиде. Не говоря уже о том, что вместо двух имен тегов я иногда получаю 3 раза (BUTTON, SPAN или MD-ICON). Кроме того, предложение в другом месте в Интернете изменить мою версию Арии тоже не помогло. В итоге я обнаружил, что проблема заключается в загрузке jquery до angular.js, хотя ng-infinate-scroll help doc говорит сначала загрузить jquery. Во всяком случае, если я попытался загрузить jquery после angular ng-infinate-scroll, перестанет работать. Поэтому я загрузил последнюю версию ng-infinate-scroll (нестабильной) версии 1.2.0, и теперь я могу загрузить мой jquery после angular.js, а моя бесконечная прокрутка работает со всеми проблемами, которые у меня были с несколькими стрельбой ng-click раз ушло.

Ответ 8

Мои элементы также обернули друг друга.

Итак, я использовал простой трюк CSS для этого решения:

.off{
   pointer-events:none;
}