ラベルをクリックするとjQuery Clickが2回起動する


114

jQueryを使用してカスタムラジオボタンを作成していますが、問題があります。ラジオに関連付けられているラベルをクリックすると、クリックイベントが2回発生します。ラジオ自体のみをクリックすると、正常に機能します(実際には、クリックしているのはラジオではなく、入力とラベル全体をラップしているdivです)。これがコードです:

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>

この動作の解決策はありますか?

回答:


130

追加してみてください:

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

表示されている.bind()または.click()のいずれかに。また、次のevtように関数にパラメータを追加しますfunction(evt) {...


9
なぜこれが起こるのですか?
chovy

8
ネストされたアイテムがあるからです。階層内の各アイテムはイベントを浮き上がらせます。
ジョーダン

7
あなたがチェックボックスのためにこれを使用している場合は、これも実際に確認することが入力を可能にするために私のために必要だった:jQuery('input').prop('checked', true);
デビッド・シンクレア

6
return false;`evt.stopPropagation();と同等です。evt.preventDefault(); (jQuery内
バジル

193

上記のソリューションを追加してみました:

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

しかし、うまくいきませんでした。しかしこれを追加する:

evt.stopImmediatePropagation();

問題を解決しました!:)


6
理由はわかりませんが、あなたの言ったことは私のコードではうまくいっているようです。ありがとうございました!
shaosh 2015

8
完璧です。これはうまくいきました!しませんでしたがevt.stopPropagation(); evt.preventDefault();、しませんでした
James111

1
これだけが私にとってうまくいきました、私は他の機能を試しましたが成功しませんでした
gardarvalur

1
この答えは私の命を救った!おかげで:D
ブルーツリー

1
これが私の答えです!
Dyluck 2018

73

クリックイベントをラベルではなく入力にバインドします。ラベルがクリックされたとき-ダスティンが述べたように、ラベルをクリックすると入力がクリックされるため、イベントは引き続き発生します。これにより、ラベルは通常の機能を保持できます。

$('input').click();

の代わりに

$('label').click();

10
このソリューションは、マークアップがラベルのラッピング入力手法を使用していて、私の正気を保存した場合にも機能します:o)
Whelkaholism

4
changeラベルのテキストはクリック可能であるため、実際にはラジオボタンでもバインドする必要があります。ラベルが常にラジオボタン自体をクリックするとは限りません。
chovy

2
Bootstrapesque label > inputセットアップを使用している場合、これは答えであり、答えではありません。追加evt.stopPropagation()またはevt.preventDefault()あなたのコードに、有効ではあるが、適切な解決策は、よりクリーンでより効率的であるときは避けるべきハックです。
elPastor 2018年

すごいすごいすごい、私はほぼ2日間を費やして考え出した、最後にこれは助けになり、説明に感謝します
opensource-developer

これは私の日を救った!
gab06

11

外側のコンテナーをクリック要素として使用する場合は、イベントを自然にバブルさせて、クリックハンドラーで期待される要素をテストすることもできます。このシナリオは、フォームの一意のクリックゾーンのスタイルを設定する場合に役立ちます。

<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
ラジオボタンを選択したいので、これは私にとってはうまくいきました。私は、イベントハンドラーがすべてに対して2回実行することを望んでいません。
chovy

1
これにより、子を選択できなくなります。ところで、同じ機能を実現するためのより良いオプションはif (e.target == e.currentTarget) {}
チキンスープ

9

これを簡単に修正するには、ラベルの「for」属性を削除します。ラベルをクリックすると、関連する要素もクリックされます。(あなたの場合、これはあなたのクリックイベントを2回発生させています。)

幸運を


確かに迅速な解決策。マークアップをいじくり回していると主張する人もいるかもしれませんが、「for」属性の目的はイベントの伝播であると私は反論します。したがって、別のメカニズム(jquery)を使用している場合は、必ず「for」を削除してください。
Chris Harrington、

5

私は通常このシンタックスを使います

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

の代わりに

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

5

ベストアンサーはコメントの中に隠されています:

changeラベルのテキストはクリック可能であるため、実際にはラジオボタンでもバインドする必要があります。ラベルが常にラジオボタン自体をクリックするとは限りません。- chovy 1時45分で、12月12日'13

このバイオリンは -他のすべてのソリューションということを示しstopPropagationstopImmediatePropagationpreventDefaultreturn false-のいずれかの変化は何もしたり、チェックボックス/ラジオ機能を破壊します)。また、これはjQueryの問題ではなく、JavaScriptの一般的な問題であることも示しています。

編集:が別のスレッドで見つけた別の実用的な解決策onclickは、ラベルではなく入力にをバインドすることです。フィドルを更新しました


2

解決策を追加してみました。

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

しかし、うまくいきませんでした。

追加することにより

evt.stopImmediatePropagation();

問題を解決しました!:)


1

e.preventDefault();の問題 ラベルのクリックでラジオボタンがチェックされないようにするためです。

より良い解決策は、次のように単に「チェックされている」クイックチェックを追加することです。

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

1
さらに簡潔なソリューションは、.clickではなく.mouseupを使用することです
yoshyosh

1
このソリューションは、コードでユーザーがラジオボタンの選択を解除できるようにする場合にも機能しません。二重発火はこの場合深刻なトラブルを引き起こします。
Johncl、2014

1

私の問題は少し異なり、evt.stopPropagation();evt.preventDefault();私にとってはうまくいかないのでreturn false;、最後に追加するだけでうまくいきます。

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

1

私の場合の問題は、関数にクリックイベントがあり、その関数が2回実行されたことです。関数を実行するたびに、新しいクリックイベントが作成されます。- 手のひらを顔に当てます -

関数の外でクリックイベントを移動した後、すべてが期待どおりに機能しました。:)


0

labelタグはクリックをエミュレートするため、入力タグをトリガー要素の外側に配置してみてください。これにより、常に複数の呼び出しが発生します。


0

radio_divに接続されたハンドラーを使用して、このようにラベル内にラジオをネストしたため、同じ問題が発生しました。ネストされたラベルを削除すると、問題が修正されました。

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

0

ラベルにより、ラジオ/チェックボックスがチェックされます。

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

特にラベルがこの動作をトリガーするのを防ぎます。


0

for = "some-id"属性を持つラベルをクリックすると、新しいクリックがトリガーされますが、ターゲットが存在し、それが入力である場合のみです。私がいたではない、私はこのようにそれをしなかったので(e.preventDefaultと完全にそれを解決することができ)、またはそのようなもの:

たとえば、この構造があり、.some-classをクリックしたときにイベントが必要な場合

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

何がうまくいったか:

$(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
    })
;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.