132 votes

jQuery Click se déclenche deux fois en cliquant sur l'étiquette

J'utilise jQuery pour créer des boutons radio personnalisés et j'ai un problème. Lorsque vous cliquez sur l'étiquette associée à la radio, les événements de clic se déclenchent deux fois, si je clique uniquement sur la radio elle-même, cela fonctionne bien (en fait, ce n'est pas la radio sur laquelle je clique mais le div qui enveloppe l'ensemble de l'entrée et de l'étiquette). Voici le code :

Le 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>

Existe-t-il une solution à ce comportement ?

230voto

N3da Points 109

J'ai essayé d'ajouter la solution ci-dessus en ajoutant:

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

mais n'a pas fonctionné. Cependant en ajoutant ceci:

 evt.stopImmediatePropagation();

résolu le problème! :)

143voto

Jordan Points 12780

Essayez d'ajouter :

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

au .bind() ou .click(), selon ce que vous voyez. Ajoutez également le paramètre evt à la fonction, comme function(evt) {...

83voto

Doug M Points 202

Liez l'événement click à l'entrée plutôt qu'à l'étiquette. Lorsque l'on clique sur l'étiquette, l'événement se produira toujours car, comme Dustin l'a mentionné, un clic sur l'étiquette déclenche un clic sur l'entrée. Cela permettra à l'étiquette de conserver sa fonctionnalité normale.

 $('input').click();

À la place de

 $('label').click();

11voto

tobius Points 108

Si vous essayez d'utiliser un conteneur externe comme élément de clic, vous pouvez également laisser les événements se propager naturellement et tester l'élément attendu dans votre gestionnaire de clics. Ce scénario est utile si vous essayez de styliser une zone de clic unique pour un formulaire.

 <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>

10voto

Dustin Points 59

Pour résoudre ce problème facilement, supprimez l'attribut "for" sur l'étiquette. Un clic sur l'étiquette déclenchera également un clic sur l'élément associé. (ce qui, dans votre cas, déclenche votre événement de clic deux fois.)

Bonne chance

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X