addClass et removeClass en jQuery-classe non supprimée
j'essaie de faire quelque chose de très simple. Fondamentalement, j'ai un div cliquable "point chaud", quand vous cliquez sur qu'il remplit l'écran et affiche du contenu. J'ai réalisé ceci en changeant simplement la classe de div, en supprimant 'spot' et en ajoutant 'grown' et il y a une petite animation CSS pour la faire grandir. Cela fonctionne très bien.
le problème est que, dans cette div il y a un close_button, qui pour le moment n'est qu'un texte. Je veux que cela change les classes de retour - c.-à-d. supprimer cultivé et readd spot. Ça ne fait pas ça quand on clique. Je crois que c'est à cause de l'élément qui n'a pas ces cours quand le DOM est chargé, mais je suis nouveau à jQuery et je ne sais pas comment travailler avec ça.
je pense qu'il y a probablement une façon beaucoup plus sensée de le faire, quelqu'un pourrait-il me diriger dans la bonne direction? Je serais très reconnaissant. J'ai essayé d'utiliser toggleClass à la place en vain.
$( document ).ready(function() {
$(".clickable").click(function() {
$(this).addClass("grown");
$(this).removeClass("spot");
});
$(".close_button").click(function() {
alert (this);
$("#spot1").removeClass("grown");
$("#spot1").addClass("spot");
});
});
mise à JOUR:
j'utilise ce code maintenant,
$( document ).ready(function() {
$(document).on("click", ".close_button", function () {
alert ("oi");
$("#spot1").addClass("spot");
$("#spot1").removeClass("grown");
});
$(document).on("click", ".clickable", function () {
if ($(this).hasClass("spot")){
$(this).addClass("grown");
$(this).removeClass("spot");
}
});
});
étrangement la fonction close_button n'ajoutera toujours pas' spot 'ou ne supprimera pas' grown ' bien qu'elle ajoutera d'autres classes et supprimera d'autres classes... J'ai ajouté la clause if parce que je pensais que peut-être les deux fonctions étaient déclenchées en même temps, se défaisant l'une l'autre, mais cela ne semble pas faire de différence
9 réponses
Ce qui se passe, c'est que votre bouton de fermeture est placé à l'intérieur de votre .clickable
div, le clic événement sera déclenché dans les deux éléments.
le bubbling de l'événement fera que l'événement click se propagera à partir des noeuds enfant vers leurs parents. Si votre .close_button
rappel sera exécuté en premier, et quand .clickable
est atteint, il va basculer les classes à nouveau. Comme cette course très rapide, vous ne pouvez pas remarquer les deux événements se sont produits.
/ \
--------------------| |-----------------
| .clickable | | |
| ----------------| |----------- |
| | .close_button | | | |
| ------------------------------ |
| event bubbling |
----------------------------------------
pour empêcher votre événement d'atteindre .clickable
, vous devez ajouter le paramètre event à votre fonction de rappel et ensuite appeler stopPropagation
méthode sur elle.
$(".close_button").click(function (e) {
$("#spot1").addClass("spot");
$("#spot1").removeClass("grown");
e.stopPropagation();
});
Violon: http://jsfiddle.net/u4GCk/1/
Plus d'info sur l'événement de l'ordre en général: http://www.quirksmode.org/js/events_order.html (c'est là que j'ai choisi cette jolie ASCII art =])
Le problème est causé en raison de remontée d'événements. La première partie de votre code à ajouter .grown
fonctionne très bien.
la deuxième partie "supprimer la classe cultivée" en cliquant sur le lien ne fonctionne pas comme prévu comme le gestionnaire pour .close_button
et .clickable
sont exécutées. Donc il supprime et readd le grown
classe div
.
Vous pouvez éviter cela en utilisant e.stopPropagation()
à l'intérieur .close_button
cliquez sur gestionnaire pour éviter l'événement bouillonnement.
DEMO:http://jsfiddle.net/vL8DP/
Code Complet
$(document).on('click', '.clickable', function () {
$(this).addClass('grown').removeClass('spot');
}).on('click', '.close_button', function (e) {
e.stopPropagation();
$(this).closest('.clickable').removeClass('grown').addClass('spot');
});
Chaque fois que je vois addClass
et removeClass
je pense pourquoi ne pas simplement utiliser toggleClass
. Dans ce cas, nous pouvons supprimer le .clickable
classe pour éviter que l'événement bouillonne, et pour éviter que l'événement ne soit tiré sur tout ce que l'on clique à l'intérieur de la .clickable
div
.
$(document).on("click", ".close_button", function () {
$(this).closest(".grown").toggleClass("spot grown clickable");
});
$(document).on("click", ".clickable", function () {
$(this).toggleClass("spot grown clickable");
});
je recommande également d'un parent wrapper pour votre .clickable
divs
au lieu d'utiliser le document
. Je ne suis pas sûr de la façon dont vous les ajoutez dynamiquement donc je ne voulais pas assumer votre mise en page pour vous.
http://jsfiddle.net/bplumb/ECQg5/2/
Bon Codage :)
je recommande de mettre en cache les objets jQuery que vous utilisez plus d'une fois. Par Exemple:
$(document).on("click", ".clickable", function () {
$(this).addClass("grown");
$(this).removeClass("spot");
});
:
var doc = $(document);
doc.on('click', '.clickable', function(){
var currentClickedObject = $(this);
currentClickedObject.addClass('grown');
currentClickedObject.removeClass('spot');
});
c'est en fait plus de code, mais c'est beaucoup plus rapide parce que vous n'avez pas à "marcher" à travers toute la bibliothèque jQuery pour obtenir l'objet $(this).
je pense que tu y es presque.
La chose est, votre $(this)
dans le "bouton de fermeture" l'auditeur n'est pas le div cliquable. Si vous souhaitez rechercher d'abord. essayez de remplacer $(this)
$(this).closest(".clickable")
. Et n'oubliez pas les e.stopPropagation()
comme le suggère Guilherme. cela devrait être quelque chose comme:
$( document ).ready(function() {
$(document).on("click", ".close_button", function () {
alert ("oi");
e.stopPropagation()
$(this).closest(".clickable").addClass("spot");
$(this).closest(".clickable").removeClass("grown");
});
$(document).on("click", ".clickable", function () {
if ($(this).hasClass("spot")){
$(this).addClass("grown");
$(this).removeClass("spot");
}
});
});
essaye ceci :
$('.close-button').on('click', function(){
$('.element').removeClass('grown');
$('.element').addClass('spot');
});
$('.element').on('click', function(){
$(this).removeClass('spot');
$(this).addClass('grown');
});
j'espère avoir compris votre question.
pourquoi ne pas simplifier?
jquery
$('.clickable').on('click', function() {//on parent click
$(this).removeClass('spot').addClass('grown');//use remove/add Class here because it needs to perform the same action every time, you don't want a toggle
}).children('.close_button').on('click', function(e) {//on close click
e.stopPropagation();//stops click from triggering on parent
$(this).parent().toggleClass('spot grown');//since this only appears when .grown is present, toggling will work great instead of add/remove Class and save some space
});
de cette façon, c'est beaucoup plus facile à entretenir.
fait un violon: http://jsfiddle.net/filever10/3SmaV/
Utiliser .sur()
Vous avez besoin de la délégation d'événement car ces classes ne sont pas présentes sur DOM quand DOM est prêt.
$(document).on("click", ".clickable", function () {
$(this).addClass("grown");
$(this).removeClass("spot");
});
$(document).on("click", ".close_button", function () {
$("#spot1").removeClass("grown");
$("#spot1").addClass("spot");
});
je pense que le problème est dans l'imbrication des éléments. Une fois que vous attachez un événement à l'élément extérieur, les clics sur les éléments intérieurs tirent en fait le même événement de clic pour l'élément extérieur. Donc, tu ne vas jamais dans le second état. Ce que vous pouvez faire est de vérifier l'élément cliqué. Et si c'est le bouton Fermer alors pour éviter le changement de classe. Voici ma solution:
var element = $(".clickable");
var closeButton = element.find(".close_button");
var onElementClick = function(e) {
if(e.target !== closeButton[0]) {
element.removeClass("spot").addClass("grown");
element.off("click");
closeButton.on("click", onCloseClick);
}
}
var onCloseClick = function() {
element.removeClass("grown").addClass("spot");
closeButton.off("click");
element.on("click", onElementClick);
}
element.on("click", onElementClick);
en plus, j'ajoute et je supprime les gestionnaires d'événements.
JSFiddle - > http://jsfiddle.net/zmw9E/1/