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

26
demandé sur Shikiryu 2013-09-24 20:03:08

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 =])

55
répondu Guilherme Sehn 2013-10-30 22:09:04

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');
});
13
répondu Selvakumar Arumugam 2017-05-23 12:17:33

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

$(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 .clickabledivs 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 :)

7
répondu Blake Plumb 2013-10-31 16:37:13

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

4
répondu Mensur Grišević 2013-11-06 10:27:49

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");
        }
    });
});
3
répondu thomasstephn 2013-11-06 18:34:03

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.

1
répondu lefoy 2013-09-24 16:09:16

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/

1
répondu FiLeVeR10 2013-11-06 16:07:02

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");
});  
0
répondu Tushar Gupta 2013-09-24 16:04:56

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/

0
répondu Krasimir 2013-10-30 21:56:45