webentwicklung-frage-antwort-db.com.de

jQuery - Feuerereignis, wenn sich die CSS-Klasse geändert hat

wie kann ich ein Ereignis auslösen, wenn die a css-Klasse mit jQuery hinzugefügt oder geändert wurde? Wird durch das Ändern der CSS-Klasse das Ereignis jQuery change () ausgelöst?

226
user237060

Wann immer Sie eine Klasse in Ihrem Skript ändern, können Sie eine trigger verwenden, um Ihr eigenes Ereignis auszulösen.

$(this).addClass('someClass');
$(mySelector).trigger('cssClassChanged')
....
$(otherSelector).bind('cssClassChanged', data, function(){ do stuff });

ansonsten, nein, es gibt keine Möglichkeit, ein Ereignis auszulösen, wenn sich eine Klasse ändert. change() wird nur ausgelöst, wenn der Fokus eine Eingabe verlässt, deren Eingabe geändert wurde.

$(function() {
  var button = $('.clickme')
      , box = $('.box')
  ;
  
  button.on('click', function() { 
    box.removeClass('box');
    $(document).trigger('buttonClick');
  });
            
  $(document).on('buttonClick', function() {
    box.text('Clicked!');
  });
});
.box { background-color: red; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="box">Hi</div>
<button class="clickme">Click me</button>

Weitere Informationen zu jQuery-Auslösern

215
Jason

IMHO ist die bessere Lösung, zwei Antworten mit @ RamboNo5 und @ Jason zu kombinieren

Ich meine, die addClass-Funktion überschreiben und ein benutzerdefiniertes Ereignis mit dem Namen cssClassChanged hinzufügen.

// Create a closure
(function(){
    // Your base, I'm in it!
    var originalAddClassMethod = jQuery.fn.addClass;

    jQuery.fn.addClass = function(){
        // Execute the original method.
        var result = originalAddClassMethod.apply( this, arguments );

        // trigger a custom event
        jQuery(this).trigger('cssClassChanged');

        // return the original result
        return result;
    }
})();

// document ready function
$(function(){
    $("#YourExampleElementID").bind('cssClassChanged', function(){ 
        //do stuff here
    });
});
132
Arash Milani

Ich würde vorschlagen, dass Sie die Funktion addClass überschreiben. Sie können es so machen:

// Create a closure
(function(){
    // Your base, I'm in it!
    var originalAddClassMethod = jQuery.fn.addClass;

    jQuery.fn.addClass = function(){
        // Execute the original method.
        var result = originalAddClassMethod.apply( this, arguments );

        // call your function
        // this gets called everytime you use the addClass method
        myfunction();

        // return the original result
        return result;
    }
})();

// document ready function
$(function(){
    // do stuff
});
52
RamboNo5

Wenn Sie Klassenänderungen feststellen möchten, verwenden Sie am besten Mutationsbeobachter, mit denen Sie die vollständige Attributänderung steuern können. Sie müssen den Listener jedoch selbst definieren und an das Element anhängen, das Sie hören. Gut ist, dass Sie nichts manuell auslösen müssen, sobald der Listener angehängt wird.

$(function() {
(function($) {
    var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;

    $.fn.attrchange = function(callback) {
        if (MutationObserver) {
            var options = {
                subtree: false,
                attributes: true
            };

            var observer = new MutationObserver(function(mutations) {
                mutations.forEach(function(e) {
                    callback.call(e.target, e.attributeName);
                });
            });

            return this.each(function() {
                observer.observe(this, options);
            });

        }
    }
})(jQuery);

//Now you need to append event listener
$('body *').attrchange(function(attrName) {

    if(attrName=='class'){
            alert('class changed');
    }else if(attrName=='id'){
            alert('id changed');
    }else{
        //OTHER ATTR CHANGED
    }

});
});

In diesem Beispiel wird der Ereignislistener an jedes Element angehängt, dies ist jedoch in den meisten Fällen nicht erwünscht (Speicherplatz sparen). Hängen Sie diesen Listener "attrchange" an das Element an, das Sie beobachten möchten.

49
Mr Br

Nur ein Proof of Concept:

Schauen Sie sich den Gist an, um einige Anmerkungen zu sehen und bleiben Sie auf dem Laufenden:

https://Gist.github.com/yckart/c893d7db0f49b1ea4dfb

(function ($) {
  var methods = ['addClass', 'toggleClass', 'removeClass'];

  $.each(methods, function (index, method) {
    var originalMethod = $.fn[method];

    $.fn[method] = function () {
      var oldClass = this[0].className;
      var result = originalMethod.apply(this, arguments);
      var newClass = this[0].className;

      this.trigger(method, [oldClass, newClass]);

      return result;
    };
  });
}(window.jQuery || window.Zepto));

Die Verwendung ist ziemlich einfach. Fügen Sie einfach einen neuen Listener auf dem Knoten hinzu, den Sie beobachten möchten, und bearbeiten Sie die Klassen wie üblich:

var $node = $('div')

// listen to class-manipulation
.on('addClass toggleClass removeClass', function (e, oldClass, newClass) {
  console.log('Changed from %s to %s due %s', oldClass, newClass, e.type);
})

// make some changes
.addClass('foo')
.removeClass('foo')
.toggleClass('foo');
20
yckart

change() wird nicht ausgelöst, wenn eine CSS-Klasse hinzugefügt oder entfernt wird oder die Definition geändert wird. Es wird ausgelöst, wenn beispielsweise ein Auswahlfeldwert ausgewählt oder nicht ausgewählt ist.

Ich bin mir nicht sicher, ob Sie damit meinen, ob die Definition der CSS-Klasse geändert wird (was programmgesteuert erfolgen kann, aber langwierig und nicht generell empfohlen wird) oder ob einem Element eine Klasse hinzugefügt oder entfernt wird. In keinem Fall kann dies zuverlässig erfasst werden.

Sie können natürlich Ihre eigene Veranstaltung erstellen, dies kann jedoch nur als Advisory beschrieben werden. Es wird kein Code erfasst, der nicht bei Ihnen ist.

Alternativ können Sie die addClass() (etc) -Methoden in jQuery überschreiben/ersetzen. Dies wird jedoch nicht erfasst, wenn dies über Vanilla Javascript erfolgt (obwohl ich denke, dass Sie diese Methoden auch ersetzen können).

7
cletus

Es gibt eine weitere Möglichkeit, ohne ein benutzerdefiniertes Ereignis auszulösen

Ein jQuery-Plug-In zum Überwachen von HTML-Element-CSS-Änderungen von Rick Strahl

Zitat von oben 

Das Watch-Plug-In funktioniert durch Anschließen an DOMAttrModified in FireFox onPropertyChanged in Internet Explorer oder mithilfe eines Timers mit setInterval, um die Erkennung von Änderungen für andere Browser zu behandeln . Leider unterstützt WebKit DOMAttrModified nicht ständig unter Im Moment müssen Safari und Chrome also das langsamere .__ verwenden. setInterval-Mechanismus.

7
Amitd

unter Verwendung der neuesten Jquery-Mutation

var $target = jQuery(".required-entry");
            var observer = new MutationObserver(function(mutations) {
                mutations.forEach(function(mutation) {
                    if (mutation.attributeName === "class") {
                        var attributeValue = jQuery(mutation.target).prop(mutation.attributeName);
                        if (attributeValue.indexOf("search-class") >= 0){
                            // do what you want
                        }
                    }
                });
            });
            observer.observe($target[0],  {
                attributes: true
            });

// jeder Code, der div mit der Klasse required-entry aktualisiert, der sich in $ target befindet wie $ target.addClass ('search-class');

6

Gute Frage. Ich verwende das Bootstrap-Dropdown-Menü und musste ein Ereignis ausführen, wenn ein Bootstrap-Dropdown ausgeblendet wurde. Wenn das Dropdown-Menü geöffnet wird, fügt das enthaltende div mit dem Klassennamen "button-group" eine Klasse von "open" hinzu. und die Schaltfläche selbst hat ein Attribut "Aria-Expanded", das auf "true" gesetzt ist. Wenn das Dropdown-Menü geschlossen ist, wird diese Klasse von "open" aus dem enthaltenden div entfernt und die Erweiterung von aria von true auf false umgestellt.

Das brachte mich zu dieser Frage, wie man den Klassenwechsel erkennen kann.

Mit Bootstrap können "Dropdown-Ereignisse" erkannt werden. Suchen Sie unter diesem Link nach "Dropdown-Ereignissen" . http://www.w3schools.com/bootstrap/bootstrap_ref_js_dropdown.asp

Hier ist ein schnelles und schmutziges Beispiel für die Verwendung dieses Ereignisses in einem Bootstrap-Dropdown.

$(document).on('hidden.bs.dropdown', function(event) {
    console.log('closed');
});

Jetzt ist mir klar, dass dies spezifischer ist als die allgemeine Frage, die gestellt wird. Ich kann mir jedoch vorstellen, dass andere Entwickler, die versuchen, ein offenes oder geschlossenes Ereignis mit einem Bootstrap-Dropdown zu erkennen, dies hilfreich finden werden. Wie ich mag sie zunächst den Weg gehen, einfach eine Elementklassenänderung zu entdecken (was anscheinend nicht so einfach ist). Vielen Dank.

5
Ken Palmer

Wenn Sie ein bestimmtes Ereignis auslösen müssen, können Sie die Methode addClass () überschreiben, um ein benutzerdefiniertes Ereignis mit dem Namen "classadded" auszulösen.

Hier wie:

(function() {
    var ev = new $.Event('classadded'),
        orig = $.fn.addClass;
    $.fn.addClass = function() {
        $(this).trigger(ev, arguments);
        return orig.apply(this, arguments);
    }
})();

$('#myElement').on('classadded', function(ev, newClasses) {
    console.log(newClasses + ' added!');
    console.log(this);
    // Do stuff
    // ...
});
4
micred

Sie können das DOMSubtreeModified-Ereignis binden. Ich füge hier ein Beispiel hinzu:

HTML

<div id="mutable" style="width:50px;height:50px;">sjdfhksfh<div>
<div>
  <button id="changeClass">Change Class</button>
</div>

JavaScript

$(document).ready(function() {
  $('#changeClass').click(function() {
    $('#mutable').addClass("red");
  });

  $('#mutable').bind('DOMSubtreeModified', function(e) {
      alert('class changed');
  });
});

http://jsfiddle.net/hnCxK/13/

3
Sativa Diva
var timeout_check_change_class;

function check_change_class( selector )
{
    $(selector).each(function(index, el) {
        var data_old_class = $(el).attr('data-old-class');
        if (typeof data_old_class !== typeof undefined && data_old_class !== false) 
        {

            if( data_old_class != $(el).attr('class') )
            {
                $(el).trigger('change_class');
            }
        }

        $(el).attr('data-old-class', $(el).attr('class') );

    });

    clearTimeout( timeout_check_change_class );
    timeout_check_change_class = setTimeout(check_change_class, 10, selector);
}
check_change_class( '.breakpoint' );


$('.breakpoint').on('change_class', function(event) {
    console.log('haschange');
});
0
Jérome Obbiet

wenn Sie wissen, welches Ereignis die Klasse überhaupt geändert hat, können Sie für dasselbe Ereignis eine geringfügige Verzögerung und das Kontrollkästchen für die Klasse . verwenden

//this is not the code you control
$('input').on('blur', function(){
    $(this).addClass('error');
    $(this).before("<div class='someClass'>Warning Error</div>");
});

//this is your code
$('input').on('blur', function(){
    var el= $(this);
    setTimeout(function(){
        if ($(el).hasClass('error')){ 
            $(el).removeClass('error');
            $(el).prev('.someClass').hide();
        }
    },1000);
});

http://jsfiddle.net/GuDCp/3/

0
Nikos Tsagkas