La case à cocher Stop est vérifiée deux fois lorsque vous êtes dans un li avec un événement de clic

J'écris un simple menu déroulant avec jQuery et chaque élément a une case à cocher. Lorsque je clique sur un élément li , la case à cocher est sélectionnée. Cependant, si je clique sur la case à cocher elle-même, elle ne sélectionne pas car elle est effectivement vérifiée deux fois. Comment puis-je arrêter cela?

JsFiddle: http://jsfiddle.net/ZEp7V/

HTML:

 <div id="dropdown">Channels</div> <ul class="droplist"> <li>News <input type="checkbox" /></li> <li>Sport <input type="checkbox" /></li> <li>Science <input type="checkbox" /></li> <li>Health <input type="checkbox" /></li> <li>All</li> </ul> 

CSS:

 div#dropdown { border: 1px solid #000; width: 150px; height: 20px; line-height: 20px; padding: 10px; cursor: pointer; } ul.droplist { display: none; width: 170px; border: 1px solid #000; border-bottom: none; list-style-type: none; padding: 0px; margin: 0px; position: absolute; background-color: #fff; } ul.droplist li { border-bottom: 1px solid #000; padding: 10px; cursor: pointer; } ul.droplist li input { float: right; } 

JS:

 $(document).ready(function(){ $("#dropdown").click(function() { $(this).next().slideToggle(200); }); $(".droplist li").click(function(e) { // Toggle the checkbox var input = $(this).children("input"); $(input).prop("checked", !$(input).prop("checked")); }); $(".droplist li:last").click(function () { // Select all boxes var check = $('.droplist li input:not(:checked)').length; $(".droplist li input").prop("checked", check); }); }); 

Vous pouvez arrêter la propagation de l'événement dans la case à cocher:

 $(".droplist li :checkbox").click(function (e) { e.stopPropagation(); }); 

Cela empêchera l'événement de faire bouillir l'arborescence DOM à l'élément parent li (où, comme vous le dites, il déclenche le gestionnaire d'événements lié à celui-ci).


Comme note secondaire, vous pouvez modifier votre code pour prendre en compte la délégation de l'événement, ce qui est plus efficace car il n'y a qu'un seul gestionnaire d'événements au lieu d'un pour chaque élément li . Par exemple:

 $(".droplist").on("click", "li", function (e) { // Toggle the checkbox var input = $(this).children("input"); $(input).prop("checked", !$(input).prop("checked")); }); 

Voir la méthode .on() pour plus de détails.

Enroulez les cases avec des étiquettes (les étiquettes partagent l'événement de clic natif du navigateur avec l'entrée)

 <li><label for="news_input">News <input type="checkbox" id="news_input" /></label></li> <li><label for="sport_input">Sport <input type="checkbox" id="sport_input" /></li> <li><label for="science_input">Science <input type="checkbox" id="science_input" /></li> <li><label for="health_input">Health <input type="checkbox" id="health_input" /></li> 

Et se débarrasser de ce comportement

 $(".droplist li").click(function(e) { // Toggle the checkbox var input = $(this).children("input"); $(input).prop("checked", !$(input).prop("checked")); }); 

Comme cela, vous devriez être bien. Le problème avec votre solution est que la fonction de la case à cocher du navigateur natif et jQuery se tuent dès qu'un utilisateur frappe l'entrée en un clic. (Le navigateur vérifie la case à cocher, jQuery le décoche)