Come posso generare un evento se una classe CSS viene aggiunta o modificata usando jQuery? Il cambio di una classe CSS genera l' change()
evento jQuery ?
Come posso generare un evento se una classe CSS viene aggiunta o modificata usando jQuery? Il cambio di una classe CSS genera l' change()
evento jQuery ?
Risposte:
Ogni volta che cambi una classe nella tua sceneggiatura, puoi usare a trigger
per creare il tuo evento.
$(this).addClass('someClass');
$(mySelector).trigger('cssClassChanged')
....
$(otherSelector).bind('cssClassChanged', data, function(){ do stuff });
ma in caso contrario, no, non esiste un modo predefinito per generare un evento quando una classe cambia. change()
si attiva solo dopo che il focus lascia un input il cui input è stato modificato.
$(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
evento e tutti quegli oggetti che si iscrivono a quell'evento possono reagire di conseguenza.
IMHO la soluzione migliore è combinare due risposte di @ RamboNo5 e @Jason
Intendo sostituire la funzione addClass e aggiungere un evento personalizzato chiamato 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
});
});
$()
, quando inizia la vera azione.
cssClassChanged
evento a un elemento, devi essere consapevole che verrà generato anche quando suo figlio cambierà classe. Pertanto, se per esempio non vuoi lanciare questo evento per loro, aggiungi qualcosa come $("#YourExampleElementID *").on('cssClassChanged', function(e) { e.stopPropagation(); });
dopo il tuo bind. Comunque, davvero una bella soluzione, grazie!
Se vuoi rilevare il cambio di classe, il modo migliore è usare gli osservatori di mutazioni, che ti danno il controllo completo su ogni cambiamento di attributo. Tuttavia, devi definire tu stesso l'ascoltatore e aggiungerlo all'elemento che stai ascoltando. La cosa buona è che non è necessario attivare nulla manualmente una volta aggiunto l'ascoltatore.
$(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 questo esempio il listener di eventi viene aggiunto a ogni elemento, ma nella maggior parte dei casi non lo si desidera (salvare memoria). Aggiungi questo ascoltatore "attrchange" all'elemento che vuoi osservare.
DOMMutationObserver
.
Vorrei suggerire di ignorare la funzione addClass. Puoi farlo in questo modo:
// 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
});
Solo una prova di concetto:
Guarda l'essenza per vedere alcune annotazioni e rimanere aggiornato:
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));
L'utilizzo è abbastanza semplice, basta aggiungere un nuovo listener sul nodo che si desidera osservare e manipolare le classi come al solito:
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]
non è definito ... è sufficiente sostituire la fine delle righe con var oldClass
e var newClass
con il seguente incarico:= (this[0] ? this[0].className : "");
usando l'ultima mutazione jquery
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
});
// qualsiasi codice che aggiorna div con classe richiesto-entry che è in $ target come $ target.addClass ('classe di ricerca');
change()
non si attiva quando una classe CSS viene aggiunta o rimossa o la definizione cambia. Viene generato in circostanze come quando un valore di casella di selezione viene selezionato o non selezionato.
Non sono sicuro se intendi se la definizione della classe CSS è cambiata (cosa che può essere fatta a livello di programmazione ma è noiosa e generalmente sconsigliata) o se una classe viene aggiunta o rimossa a un elemento. Non è possibile catturare in modo affidabile ciò che accade in entrambi i casi.
Ovviamente potresti creare il tuo evento per questo, ma questo può essere descritto solo come consulenza . Non acquisirà il codice che non è il tuo a farlo.
In alternativa, potresti sostituire / sostituire i addClass()
metodi (ecc.) In jQuery ma questo non verrà catturato quando viene eseguito tramite Javascript vanilla (anche se immagino che potresti sostituire anche questi metodi).
C'è un altro modo senza innescare un evento personalizzato
Un plug-in jQuery per monitorare le modifiche CSS dell'elemento HTML di Rick Strahl
Citando dall'alto
Il plug-in watch funziona collegandosi a DOMAttrModified in FireFox, a onPropertyChanged in Internet Explorer o utilizzando un timer con setInterval per gestire il rilevamento di modifiche per altri browser. Sfortunatamente WebKit al momento non supporta costantemente DOMAttrModified, quindi Safari e Chrome devono attualmente utilizzare il meccanismo setInterval più lento.
Buona domanda. Sto usando il menu a discesa Bootstrap e avevo bisogno di eseguire un evento quando un menu a discesa Bootstrap era nascosto. Quando viene aperto il menu a discesa, il div contenente un nome di classe di "gruppo-pulsante" aggiunge una classe di "aperto"; e il pulsante stesso ha un attributo "aria-espanso" impostato su true. Quando il menu a discesa viene chiuso, quella classe di "open" viene rimossa dal div contenente e l'aria-espanso passa da vero a falso.
Ciò mi ha portato a questa domanda, su come rilevare il cambio di classe.
Con Bootstrap, ci sono "Eventi a discesa" che possono essere rilevati. Cerca "Eventi a discesa" a questo link. http://www.w3schools.com/bootstrap/bootstrap_ref_js_dropdown.asp
Ecco un esempio veloce e sporco dell'utilizzo di questo evento in un menu a discesa Bootstrap.
$(document).on('hidden.bs.dropdown', function(event) {
console.log('closed');
});
Ora mi rendo conto che questo è più specifico della domanda generale che viene posta. Ma immagino che altri sviluppatori che provano a rilevare un evento aperto o chiuso con un menu a discesa Bootstrap lo trovino utile. Come me, inizialmente potrebbero seguire la strada del semplice tentativo di rilevare un cambio di classe di elementi (che apparentemente non è così semplice). Grazie.
Se devi attivare un evento specifico, puoi ignorare il metodo addClass () per generare un evento personalizzato chiamato 'classadded'.
Ecco come:
(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
// ...
});
È possibile associare l'evento DOMSubtreeModified. Aggiungo un esempio qui:
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');
});
});
se si conosce un evento quale ha cambiato la classe in primo luogo, è possibile utilizzare un leggero ritardo sullo stesso evento e controllare la per la classe. esempio
//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');
});