web-dev-qa-db-fra.com

Comment déclencher un événement sur un changement de classe à l'aide de jQuery?

J'aimerais avoir quelque chose comme:

$('#myDiv').bind('class "submission ok" added'){
    alert('class "submission ok" has been added');
});
59
Matoeil

Il n'y a pas d'événement déclenché quand une classe change. L'alternative consiste à déclencher manuellement un événement lorsque vous modifiez la classe par programme:

$someElement.on('event', function() {
    $('#myDiv').addClass('submission-ok').trigger('classChange');
});

// in another js file, far, far away
$('#myDiv').on('classChange', function() {
     // do stuff
});

UPDATE

Cette question semble rassembler quelques visiteurs, voici donc une mise à jour avec une approche qui peut être utilisée sans avoir à modifier le code existant à l'aide du nouveau MutationObserver:

var $div = $("#foo");
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    if (mutation.attributeName === "class") {
      var attributeValue = $(mutation.target).prop(mutation.attributeName);
      console.log("Class attribute changed to:", attributeValue);
    }
  });
});
observer.observe($div[0], {
  attributes: true
});

$div.addClass('red');
.red { color: #C00; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo" class="bar">#foo.bar</div>

Sachez que la MutationObserver n'est disponible que pour les nouveaux navigateurs, en particulier Chrome 26, 14 FF, IE 11, Opera 15 et Safari 6. Voir MDN pour plus de détails. Si vous devez prendre en charge les anciens navigateurs, vous devrez utiliser la méthode que j'ai décrite dans mon premier exemple.

123
Rory McCrossan

Vous pouvez remplacer les fonctions jQuery addClass et removeClass d’origine par les vôtres qui appellent les fonctions d’origine, puis déclenchent un événement personnalisé. (Utilisation d'une fonction anonyme invocante pour contenir la référence de fonction d'origine)

(function( func ) {
    $.fn.addClass = function() { // replace the existing function on $.fn
        func.apply( this, arguments ); // invoke the original function
        this.trigger('classChanged'); // trigger the custom event
        return this; // retain jQuery chainability
    }
})($.fn.addClass); // pass the original function as an argument

(function( func ) {
    $.fn.removeClass = function() {
        func.apply( this, arguments );
        this.trigger('classChanged');
        return this;
    }
})($.fn.removeClass);

Ensuite, le reste de votre code sera aussi simple que vous le souhaiteriez.

$(selector).on('classChanged', function(){ /*...*/ });

Mise à jour:

Cette approche suppose que les classes ne seront modifiées que via les méthodes jQuery addClass et removeClass. Si les classes sont modifiées d'une autre manière (telle que la manipulation directe de l'attribut de classe via l'élément DOM), il serait nécessaire d'utiliser quelque chose comme MutationObservers, comme expliqué dans la réponse acceptée.

Aussi comme quelques améliorations à ces méthodes:

  • Déclencher un événement pour each la classe ajoutée (classAdded) ou supprimée (classRemoved) avec la classe spécifique transmise en tant qu'argument à la fonction de rappel et déclenchée uniquement si la classe particulière a été réellement ajouté (non présent auparavant) ou supprimé (était présent précédemment)
  • Déclenchez uniquement classChanged si des classes sont réellement modifiées

    (function( func ) {
        $.fn.addClass = function(n) { // replace the existing function on $.fn
            this.each(function(i) { // for each element in the collection
                var $this = $(this); // 'this' is DOM element in this context
                var prevClasses = this.getAttribute('class'); // note its original classes
                var classNames = $.isFunction(n) ? n(i, prevClasses) : n.toString(); // retain function-type argument support
                $.each(classNames.split(/\s+/), function(index, className) { // allow for multiple classes being added
                    if( !$this.hasClass(className) ) { // only when the class is not already present
                        func.call( $this, className ); // invoke the original function to add the class
                        $this.trigger('classAdded', className); // trigger a classAdded event
                    }
                });
                prevClasses != this.getAttribute('class') && $this.trigger('classChanged'); // trigger the classChanged event
            });
            return this; // retain jQuery chainability
        }
    })($.fn.addClass); // pass the original function as an argument
    
    (function( func ) {
        $.fn.removeClass = function(n) {
            this.each(function(i) {
                var $this = $(this);
                var prevClasses = this.getAttribute('class');
                var classNames = $.isFunction(n) ? n(i, prevClasses) : n.toString();
                $.each(classNames.split(/\s+/), function(index, className) {
                    if( $this.hasClass(className) ) {
                        func.call( $this, className );
                        $this.trigger('classRemoved', className);
                    }
                });
                prevClasses != this.getAttribute('class') && $this.trigger('classChanged');
            });
            return this;
        }
    })($.fn.removeClass);
    

Avec ces fonctions de remplacement, vous pouvez ensuite gérer n'importe quelle classe modifiée via classChanged ou ajouter ou supprimer des classes spécifiques en vérifiant l'argument de la fonction de rappel:

$(document).on('classAdded', '#myElement', function(event, className) {
    if(className == "something") { /* do something */ }
});
20
Nickolas Hook

Utilisez trigger pour déclencher votre propre événement. Chaque fois que vous changez de classe, ajoutez un déclencheur avec le nom

JS Fiddle DEMO

$("#main").on('click', function () {
    $("#chld").addClass("bgcolorRed").trigger("cssFontSet");
});

$('#chld').on('cssFontSet', function () {

    alert("Red bg set ");
});

apprendre jQuery: blog de tutoriels jQuery simple et facile

7
Satinder singh

vous pouvez utiliser quelque chose comme ceci:

$(this).addClass('someClass');

$(Selector).trigger('ClassChanged')

$(otherSelector).bind('ClassChanged', data, function(){//stuff });

mais sinon, non, il n'y a pas de fonction prédéfinie pour déclencher un événement quand une classe change.

En savoir plus sur les déclencheurs ici

2
Deep Sharma