Почему два события щелчка зарегистрированы в этом html / css/jquery

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

HTML-код:

<ul>
    <li>
        <label for="test_0" class="">
            <input id="test_0" name="offering_cycle" type="checkbox" value="1"> Fall
        </label>
    </li>
    <li>
        <label for="test_1" class="">
            <input id="test_1" name="offering_cycle" type="checkbox" value="2"> Spring
        </label>
    </li>
    <li>
        <label for="test_2" class="">
            <input id="test_2" name="offering_cycle" type="checkbox" value="3"> Summer
        </label>
    </li>
    <li>
        <label for="test_3" class="">
            <input id="test_3" name="offering_cycle" type="checkbox" value="4"> Other
        </label>
    </li>
</ul>

css:

ul {
    list-style-type:none;
}
label {
    position:relative;
    display:inline-block;
    padding-left:27px;
    height:25px;
}
label:before {
    display:block;
    position:absolute;
    top:-2px;
    margin-left:-28px;
    width:18px;
    height:18px;
    background-color:#fff;
    border-radius:5px;
    border:1px solid #ccc;
    text-align: center;
    color:#fff;
    font-size:18px;
    content:'a';
}
input {
    width:1px;
    height:1px;
    border:0;
    opacity:0;
    float:right;
}

jquery:

$('label[for*=test_]').on('click',function(){
    $(this).toggleClass('testing');
});

9 ответов


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

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


если вы действительно хотите обработать событие click для метки (и выполнить его только один раз для щелчка):

(1) Если вы хотите и можете изменить HTML, вы можете переместить Ввод, чтобы он не был потомком метки. По-прежнему будет два события click, но второе событие click не будет всплывать из ввода в метку, поскольку метка больше не является предком ввода.

при входе не является потомком метки, Вы должны использовать атрибут метки "for", чтобы связать его с входными данными. Значение атрибута " for "должно быть значением" id " входных данных. (Вы уже включаете атрибут "for" с правильным значением.)

<input id="test_0" name="offering_cycle" type="checkbox" value="1">
<label for="test_0" class="">Fall</label>

(2) предотвращение обработки по умолчанию первого события щелчка предотвращает запуск второго события щелчка, но это нарушает ярлык. То есть, флажок не будет проверяться / отменяться при нажатии метки.

$('label[for*=test_]').on('click', function(event) {
    event.preventDefault();
    $(this).toggleClass('testing');
    // returning false would be another way to prevent the default handling.
});

jsfiddle


(3) вместо этого вы можете остановить второе событие щелчка от пузырьков на входе.

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

$('label[for*=test_]').on('click', function() {
    $(this).toggleClass('testing');
});

jsfiddle

Примечание: Если вход не был дочерним для метки, это не было бы необходимо.


(4) или вы можете проверить цель события в обработчике. Это будет ярлык для первого щелкните событие и ввод для второго. Следующий обработчик выполняет код внутри оператора if только для первого события click.

$('label[for*=test_]').on('click', function(event) {
    if (event.target == this) {
        $(this).toggleClass('testing');
    }
});

jsfiddle

Примечание: Если вход не был дочерним для метки, код выше все равно будет работать, но оператор if будет ненужным, потому что событие click, инициированное для ввода, не будет пузыриться до метки.


обработка щелчка для ввода вместо этого:

в вашем случае вам действительно не нужно регистрировать обработчик щелчка для элемента label. Вместо этого вы можете зарегистрировать обработчик щелчка (или изменения) для ввода. Затем вы можете использовать $(this).closest('label') чтобы получить элемент Label.

$('input[name=offering_cycle]').on('click', function() {
     $(this).closest('label').toggleClass('testing');
});

jsfiddle

Примечание: Если вход не был дочерним для метки, обработчик выше все равно вызывается при нажатии на метку, но $(this).closest('label') не получил бы ярлык. Вам придется использовать что-то вроде $('label[for="' + this.id + '"]') вместо.


относительно атрибута " for " на элементах метки:

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

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

С HTML5 spec для "для" атрибут элемент "Label":

атрибут for может быть указан для указания элемента управления формы с с которой должна быть связана подпись. Если атрибут указан, значение атрибута должно быть идентификатором элемента labelable в тот же документ, что и элемент label. Если атрибут указан и в документе есть элемент, идентификатор которого равен значению атрибут for, и первым таким элементом является элемент labelable, тогда этот элемент является элементом управления label.

если атрибут for не указан, но элемент label имеет labelable элемент потомок, то первый такой потомок в дереве порядок-это метка элемента label управление.


вы также можете попробовать:

$('label[for^="test_"]').click(function(){
    $('div#target').append($(this).clone());
    return false;    
});

это потому, что вы связываете событие на label, которая содержит checkbox и вы используете for="chekbox_id". Итак, событие уволено за label а также checkbox.

<ul>
    <li>
        <label for="test_0" class="">Fall</label>
        <input id="test_0" name="offering_cycle" type="checkbox" value="1" />
    </li>
    <li>
        <label for="test_1" class="">Spring</label>
        <input id="test_1" name="offering_cycle" type="checkbox" value="2" />
    </li>
    <li>
        <label for="test_2" class="">Summer</label>
        <input id="test_2" name="offering_cycle" type="checkbox" value="3" />
    </li>
    <li>
        <label for="test_3" class="">Other</label>
        <input id="test_3" name="offering_cycle" type="checkbox" value="4" />
    </li>
</ul>
<div id="target"></div>

взять input из label.

демо:http://jsfiddle.net/tusharj/fdm1pmj2/5/


Итак, что я сказал в комментарии. Он генерирует два события щелчка мыши, сделайте это вместо этого, и он работает как шарм:Скрипка

$('input').on('click',function(){
   console.log("clicked");
    $('div#target').append($(this).parent().clone());    
});

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


а попробуйте это.

добавьте общий класс ко всем событиям Label и fire на этом. Вот так:

<ul>
    <li>
        <label for="test_0" class="testClass">
            <input id="test_0" name="offering_cycle" type="checkbox" value="1"> Fall
        </label>
    </li>
    <li>
        <label for="test_1" class="testClass">
            <input id="test_1" name="offering_cycle" type="checkbox" value="2"> Spring
        </label>
    </li>
    <li>
        <label for="test_2" class="testClass">
            <input id="test_2" name="offering_cycle" type="checkbox" value="3"> Summer
        </label>
    </li>
    <li>
        <label for="test_3" class="testClass">
            <input id="test_3" name="offering_cycle" type="checkbox" value="4"> Other
        </label>
    </li>
</ul>

и

$(".testClass").on('click',function(){
      $(this).toggleClass('testing');
});

событие click запускается дважды: один раз для метки и один раз для флажка. Вам нужно выбрать только флажок.

$('label[for*=test_] > input').on('click',function(){
    $('div#target').append($(this).parent().clone());    
});

JSFiddle здесь


вы можете попробовать это...

$("label").find("*").click(function( event ) {
     event.stopPropagation();
});

$('label[for*=test_]').on('click',function(){
     $(this).toggleClass('test');
});

чтобы объяснить, что происходит:

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

так как вы обернули свои флажки ввода внутри Элемент метки,
вы можете на самом деле слушайте даже на том input:

$('label[for*=test_] input').on('click',function(){
    $('div#target').append($(this).closest("label").clone());    
});

и чем клонировать родительскую метку. jsFiddle


другой способ предотвратить это братство между меткой и внутренним входом-остановить вход, чтобы распространить событие, позволяя ограничивать метку > > флажок к его заданию: скрипка

$("label:input").on("click", function( evt ) {
    evt.stopPropagation();
});
$('label[for*=test_]').on('click',function(){
    $('div#target').append($(this).clone());
});

иначе мог бы запретить поведение метки по умолчанию jsFiddle
это запускает события из связанного ввода, и это использует e.preventDefault() но ваш (скрытый) флажок ввода не получит проверено!

$('label[for*=test_]').on('click',function( e ){
    e.preventDefault();
    $('div#target').append($(this).clone()); 
});

https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault


на на атрибут на данной метке должен быть связан с имя ввода не id.

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

пример:

$('label[for*=test_]').on('click',function(e){
    e.stopPropagation();
});

пример html:

<div class="parent something">
    <div class="child something">
    </div>
</div>

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

источники: