jQuery Click, etikete tıklandığında iki kez tetikleniyor


114

Özel radyo düğmeleri oluşturmak için jQuery kullanıyorum ve bir sorunum var. Telsizle ilişkili etikete tıkladığımda tıklama olayları iki kez tetikleniyor, sadece telsizin kendisine tıklarsam iyi çalışıyor (aslında tıkladığım radyo değil, tüm girişi ve etiketi saran div). İşte kod:

HTML:

 <div id="box">
     <asp:RadioButtonList ID="RadioButtonList1" runat="server">
         <asp:ListItem>RADIO1</asp:ListItem>
         <asp:ListItem>RADIO2</asp:ListItem>
         <asp:ListItem>RADIO3</asp:ListItem>
     </asp:RadioButtonList>
</div>

jQuery:

<script type="text/javascript">
       $(function () {
            $('#box').find('input:radio').each(function (i) {

            var input = $(this);
            // get the associated label using the input's id
            var label = $('label[for=' + input.attr('id') + ']');
            // wrap the input + label in a div
            $('<div class="custom-radio"></div>').insertBefore(input).append(label, input);

            var wrapperDiv = input.parent();

            // find all inputs in this set using the shared name attribute
            var allInputs = $('input[name=' + input.attr('name') + ']');

            // necessary for browsers that don't support the :hover pseudo class on labels
            label.hover(

            function () {
                $(this).addClass('hover');
            }, function () {
                $(this).removeClass('hover checkedHover');
            });

            //bind custom event, trigger it, bind click,focus,blur events
            wrapperDiv.bind('updateState', function () {
                if ($(this)[0].children[1].checked) {
                    allInputs.each(function () {
                        var curDiv = $('div > label[for=' + $(this).attr('id') + ']').parent();
                        curDiv.removeClass('custom-radio-checked');
                        curDiv.addClass('custom-radio');
                    });
                    $(this).toggleClass('custom-radio custom-radio-checked');
                }
                else {
                    $(this).removeClass('custom-radio-checked checkedHover checkedFocus');
                }

            })
            .trigger('updateState')
            .click(function () { console.log('click'); })
            .focus(function () {
                label.addClass('focus');
            }).blur(function () {
                label.removeClass('focus checkedFocus');
            });
        }); 
       });
   </script>

Bu davranış için herhangi bir çözüm var mı?

Yanıtlar:


130

Eklemeyi deneyin:

evt.stopPropagation();
evt.preventDefault();

.bind () veya .click (), hangisini görüyorsanız. Ayrıca, parametreyi evtişleve ekleyin , örneğinfunction(evt) {...


9
bu neden oluyor
chovy

8
Çünkü iç içe geçmiş öğeler var. Hiyerarşideki her öğe, etkinliği havaya uçuracak.
Ürdün

7
Bunu bir onay kutusu için kullanıyorsanız, girdinin gerçekten kontrol edilmesini sağlamak için de buna ihtiyacım vardı:jQuery('input').prop('checked', true);
David Sinclair

6
return false;`evt.stopPropagation () ile eşdeğerdir; evt.preventDefault (); ( jQuery'de )
fesleğen

193

Yukarıdaki çözümü ekleyerek eklemeyi denedim:

evt.stopPropagation();
evt.preventDefault();

ama işe yaramadı. Ancak şunu eklemek:

evt.stopImmediatePropagation();

sorunu çözdü! :)


6
Neden bilmiyorum ama söylediklerin kodum için işe yarıyor gibi görünüyor. Teşekkür ederim!
shaosh

8
Mükemmel. Bu iyi çalıştı! Olmasa da evt.stopPropagation(); evt.preventDefault();; 't
James111

1
sadece bu benim için çalıştı, diğer işlevleri başarılı olmadan denedim
gardarvalur

1
Bu cevap hayatımı kurtardı! Teşekkürler: D
Bluetree

1
Bu benim için cevaptı!
Dyluck

73

Tıklama etkinliğini etiket yerine girişe bağlayın. Etiket tıklandığında - etkinlik yine de gerçekleşir çünkü Dustin'in bahsettiği gibi, etikete yapılan tıklama girişin tıklanmasını tetikler. Bu, etiketin normal işlevselliğini korumasına izin verecektir.

$('input').click();

Onun yerine

$('label').click();

10
Bu çözüm, işaretlemeniz giriş etiketini sarma tekniğini kullanıyorsa ve aklımı kurtardığında da işe yarar: o)
Whelkaholism

4
changeBir etiketin metni tıklanabilir olduğundan, radyo düğmesine bile bağlamanız gerekir - her zaman radyo düğmesinin kendisine tıklamazlar.
chovy

2
Bir Bootstrapesque label > inputkurulumu kullanıyorsanız , bu bir cevap değil, cevaptır. Kodunuza evt.stopPropagation()veya evt.preventDefault()kodunuza eklemek , etkili olsa da, doğru çözüm çok daha temiz ve daha verimli olduğunda kaçınılması gereken bir saldırıdır.
elPastor

vay vay sadece vay canına, neredeyse birkaç günümü anlamak için harcadım, sonunda bu yardımcı oldu ve açıklama için çok teşekkürler
açık kaynak geliştirici

bu benim günümü kurtardı!
gab06

11

Tıklama öğesi olarak bir dış kapsayıcı kullanmaya çalışıyorsanız, olayların doğal olarak kabarmasına izin verebilir ve tıklama işleyicinizde beklenen öğeyi test edebilirsiniz. Bu senaryo, bir form için benzersiz bir tıklama bölgesinin stilini belirlemeye çalışıyorsanız kullanışlıdır.

<form>
<div id="outer">
    <label for="mycheckbox">My Checkbox</label>
    <input type="checkbox" name="mycheckbox" id="mycheckbox" value="on"/>
</div>
</form>
<script>
$('#outer').on('click', function(e){
    // this fires for #outer, label, and input
    if (e.target.tagName == 'INPUT'){
        // only interested in input
        console.log(this);
    }
});
</script>

1
Hala radyo düğmesinin seçilmesini istediğim için bu benim için çalıştı. Olay işleyicisinin her şeyi iki kez yapmasını istemedim.
chovy

1
Bu, çocukların seçilmesine izin vermez. BTW, aynı işlevselliği elde etmek için daha iyi bir seçenek olacaktırif (e.target == e.currentTarget) {}
Tavuk Çorbası

9

Bunu kolay bir şekilde düzeltmek için, etiket üzerindeki "for" özelliğini kaldırın. Etikete bir tıklama aynı zamanda ilişkili öğenin de tıklanmasını tetikleyecektir. (sizin durumunuzda tıklama etkinliğinizi iki kez tetikliyor.)

İyi şanslar


Gerçekten de hızlı çözüm. İşaretlemeyle karıştırıldığı iddia edilebilir, ancak "for" özniteliğinin amacının olay yayılımı olduğunu kabul ediyorum. Yani başka bir mekanizma (jquery) kullanıyorsanız, o zaman kesinlikle "for" dan kurtulun.
Chris Harrington

5

Genellikle bu synthax'ı kullanırım

.off('click').on('click', function () { console.log('click'); })

onun yerine

.click(function () { console.log('click'); })

5

En iyi cevap yorumların içinde gizlidir:

changeBir etiketin metni tıklanabilir olduğundan, radyo düğmesine bile bağlamanız gerekir - her zaman radyo düğmesinin kendisine tıklamazlar. - chovy 12 Aralık 2013 , 1:45

Bu keman - Diğer tüm çözümler göstermektedir stopPropagation, stopImmediatePropagation, preventDefault, return false- değişiklik hiçbir şey ya ya) onay kutusu / radyo işlevselliği yok. Ayrıca bunun bir jQuery sorunu değil, vanilya JavaScript sorunu olduğunu da göstermektedir.

DÜZENLEME: Başka bir iş parçacığında bulduğum başka bir çalışma çözümü onclick, etiket yerine girişe bağlamaktır . Güncellenmiş keman .


2

Çözüm ekleyerek denedim.

evt.stopPropagation();
evt.preventDefault();

ama işe yaramadı.

Toplayarak

evt.stopImmediatePropagation();

sorunu çözdü! :)


1

E.preventDefault () ile ilgili sorun; etiket tıklamasının radyo düğmesini kontrol etmesini durdurması mı?

Daha iyi bir çözüm, şöyle bir "kontrol edildi" hızlı kontrolü eklemek olacaktır:

$("label").click(function(e){
  var rbtn = $(this).find("input");
  if(rbtn.is(':checked')){
  **All the code you want to have happen on click**
  }
)};

1
Daha da kısa ve öz bir çözüm .click yerine .mouseup kullanmak olabilir
yoshyosh

1
Kodunuz ayrıca bir kullanıcının bir radyo düğmesinin seçimini kaldırmasına izin verecekse bu çözüm işe yaramaz. Çifte yangın bu durumda ciddi sıkıntılara neden olur.
Johncl

1

Benim sorunum biraz farklı, çünkü evt.stopPropagation();evt.preventDefault();benim için işe yaramıyor, sadece return false;sonunda ekliyorum , sonra çalışıyor.

$("#addressDiv").on("click", ".goEditAddress", function(event) {
    alert("halo");
    return false;
});

1

Benim durumumda sorun, bir işlevde tıklama olayına sahip olmam ve işlevin iki kez çalıştırılmasıydı .... işlevin her yürütülmesi yeni bir tıklama olayı oluşturur. - yüz maskesi -

tıklama olayını işlevin dışına taşıdıktan sonra, her şey beklendiği gibi çalıştı! :)


0

Giriş etiketinizi tetikleyici öğenin dışına koymayı deneyin, çünkü etiket tıklamaya öykünür, böylece her zaman birden fazla çağrınız olur.


0

Aynı sorunu yaşadım çünkü radyomu radyo_div'e bağlı işleyici ile bu etiketin içine yerleştirmiştim. Yuvalanmış etiketin kaldırılması sorunu çözdü.

<div id="radio_div">
    <label>
       <input type="radio" class="community_radio" name="community_radio" value="existing">
           Add To Existing Community
    </label>
</div>

0

Etiket, işaretlenecek radyo / onay kutusunu tetikler.

if ($(event.target).is('label')){
    event.preventDefault();
}

Özellikle etiketin bu davranışı tetiklemesini engeller.


0

For = "some-id" özniteliğine sahip etikete yapılan tıklama, yeni bir tıklamayı tetikler, ancak yalnızca hedef varsa ve bir girişse. Ben değil e.preventDefault () veya şeylerle mükemmel şekilde çözebilecek gibi ben böyle yaptım bu yüzden:

Örneğin, bu yapıya sahipseniz ve .some-class seçeneğine tıklayarak bir olay istiyorsanız

<div class="some-class">
    <input type=checkbox" id="the-input-id" />
    <label for="the-input-id">Label</label>
</div>

Ne işe yaradı:

$(document)
    .on('click', '.some-class', function(e) {
        if(
            $(e.target).is('label[for]')
            &&
            $('input#' + $(e.target).attr('for')).length
        ) {
            // This will trigger a new click so we are out of here
            return;
        }

        // else do your thing here, it will not get called twice
    })
;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.