Wie kann ich ein Ereignis auslösen, wenn eine CSS-Klasse mit jQuery hinzugefügt oder geändert wird? Löst das Ändern einer CSS-Klasse das jQuery- change()
Ereignis aus?
Wie kann ich ein Ereignis auslösen, wenn eine CSS-Klasse mit jQuery hinzugefügt oder geändert wird? Löst das Ändern einer CSS-Klasse das jQuery- change()
Ereignis aus?
Antworten:
Wann immer Sie eine Klasse in Ihrem Skript ändern, können Sie mit a trigger
Ihr eigenes Ereignis auslösen.
$(this).addClass('someClass');
$(mySelector).trigger('cssClassChanged')
....
$(otherSelector).bind('cssClassChanged', data, function(){ do stuff });
Aber ansonsten gibt es keine Möglichkeit, ein Ereignis auszulösen, wenn sich eine Klasse ändert. change()
Wird erst ausgelöst, nachdem der Fokus eine Eingabe hinterlassen hat, 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>
changeColor
Ereignis auslösen , und alle Objekte, die dieses Ereignis abonnieren, können entsprechend reagieren.
IMHO ist die bessere Lösung, zwei Antworten von @ RamboNo5 und @Jason zu kombinieren
Ich meine, die addClass-Funktion zu überschreiben und ein benutzerdefiniertes Ereignis namens aufzurufen cssClassChanged
// 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
});
});
$()
der eigentlichen Aktion sind es Hunderte von Ereignissen .
cssClassChanged
Ereignis an ein Element binden , müssen Sie sich darüber im Klaren sein, dass es ausgelöst wird, selbst wenn sein Kind seine Klasse wechselt. Wenn Sie dieses Ereignis beispielsweise nicht für sie auslösen möchten, fügen Sie einfach etwas wie $("#YourExampleElementID *").on('cssClassChanged', function(e) { e.stopPropagation(); });
nach dem Binden hinzu. Wie auch immer, wirklich schöne Lösung, danke!
Wenn Sie Klassenänderungen erkennen möchten, verwenden Sie am besten Mutationsbeobachter, mit denen Sie die vollständige Kontrolle über alle Attributänderungen erhalten. Sie müssen den Listener jedoch selbst definieren und an das Element anhängen, das Sie gerade hören. Gut ist, dass Sie nichts manuell auslösen müssen, sobald der Listener angehängt ist.
$(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 Ereignis-Listener an jedes Element angehängt, aber das möchten Sie in den meisten Fällen nicht (Speicherplatz sparen). Hängen Sie diesen "attrchange" -Listener an das Element an, das Sie beobachten möchten.
DOMMutationObserver
.
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
});
Nur ein Proof of Concept:
Schauen Sie sich das Wesentliche an, um einige Anmerkungen zu sehen und auf dem neuesten Stand zu bleiben:
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 recht einfach. Fügen Sie einfach einen neuen Listener zu dem Knoten hinzu, den Sie beobachten möchten, und bearbeiten Sie die Klassen wie gewohnt:
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');
this[0]
ist undefiniert ... ersetzen Sie einfach das Ende der Zeilen durch var oldClass
und var newClass
mit der folgenden Zuordnung:= (this[0] ? this[0].className : "");
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 dem erforderlichen Klasseneintrag aktualisiert, der sich in $ target befindet, wie $ target.addClass ('Suchklasse');
change()
wird nicht ausgelöst, wenn eine CSS-Klasse hinzugefügt oder entfernt wird oder sich die Definition ändert. Es wird unter Umständen ausgelöst, wenn ein Auswahlfeldwert ausgewählt oder nicht ausgewählt ist.
Ich bin mir nicht sicher, ob Sie meinen, ob die CSS-Klassendefinition geändert wird (was programmgesteuert erfolgen kann, aber langwierig ist und nicht allgemein empfohlen wird) oder ob eine Klasse zu einem Element hinzugefügt oder daraus entfernt wird. In beiden Fällen gibt es keine Möglichkeit, dieses Ereignis zuverlässig zu erfassen.
Sie können natürlich Ihre eigene Veranstaltung dafür erstellen, dies kann jedoch nur als Beratung bezeichnet werden . Es wird kein Code erfasst, der nicht von Ihnen stammt.
Alternativ können Sie die addClass()
(etc) -Methoden in jQuery überschreiben / ersetzen , dies wird jedoch nicht erfasst, wenn dies über Vanilla Javascript erfolgt (obwohl Sie diese Methoden vermutlich auch ersetzen könnten).
Es gibt noch eine Möglichkeit, ohne ein benutzerdefiniertes Ereignis auszulösen
Ein jQuery-Plug-In zur Überwachung von CSS-Änderungen an HTML-Elementen von Rick Strahl
Zitat von oben
Das Watch-Plug-In funktioniert, indem Sie eine Verbindung zu DOMAttrModified in FireFox, zu onPropertyChanged in Internet Explorer herstellen oder einen Timer mit setInterval verwenden, um Änderungen für andere Browser zu erkennen. Leider unterstützt WebKit DOMAttrModified derzeit nicht konsistent, sodass Safari und Chrome derzeit den langsameren setInterval-Mechanismus verwenden müssen.
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 "aria-erweitertes" Attribut, das auf "true" gesetzt ist. Wenn das Dropdown-Menü geschlossen ist, wird diese Klasse von "open" aus dem enthaltenen div entfernt und aria-expanded von true auf false umgeschaltet.
Das führte mich zu der Frage, wie man den Klassenwechsel erkennt.
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 kurzes 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. Wie ich gehen sie möglicherweise zunächst den Weg, einfach zu versuchen, eine Änderung der Elementklasse zu erkennen (was anscheinend nicht so einfach ist). Vielen Dank.
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
// ...
});
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');
});
});
Wenn Sie wissen, welches Ereignis die Klasse überhaupt geändert hat, können Sie eine geringfügige Verzögerung für dasselbe Ereignis verwenden und die für die Klasse überprüfen. Beispiel
//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);
});
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');
});