¿Cómo puedo activar un evento si se agrega o cambia una clase CSS usando jQuery? ¿El cambio de una clase CSS activa el change()
evento jQuery ?
¿Cómo puedo activar un evento si se agrega o cambia una clase CSS usando jQuery? ¿El cambio de una clase CSS activa el change()
evento jQuery ?
Respuestas:
Cada vez que cambie una clase en su secuencia de comandos, puede usar a trigger
para generar su propio evento.
$(this).addClass('someClass');
$(mySelector).trigger('cssClassChanged')
....
$(otherSelector).bind('cssClassChanged', data, function(){ do stuff });
pero por lo demás, no, no hay una forma preparada de disparar un evento cuando cambia una clase. change()
solo se dispara después de que el foco deja una entrada cuya entrada ha sido alterada.
$(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 y todos los objetos que se suscriben a ese evento pueden reaccionar en consecuencia.
En mi humilde opinión, la mejor solución es combinar dos respuestas de @ RamboNo5 y @Jason
Me refiero a anular la función addClass y agregar un evento personalizado llamado 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
});
});
$()
, cuando comienza la acción real.
cssClassChanged
evento a un elemento, debe tener en cuenta que se activará incluso cuando su hijo cambie de clase. Por lo tanto, si por ejemplo no desea activar este evento para ellos, simplemente agregue algo como $("#YourExampleElementID *").on('cssClassChanged', function(e) { e.stopPropagation(); });
después de su enlace. De todos modos, muy buena solución, ¡gracias!
Si desea detectar el cambio de clase, la mejor manera es usar Observadores de mutación, que le da control total sobre cualquier cambio de atributo. Sin embargo, debe definir el oyente usted mismo y agregarlo al elemento que está escuchando. Lo bueno es que no necesita activar nada manualmente una vez que se agrega el oyente.
$(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
}
});
});
En este ejemplo, el detector de eventos se agrega a cada elemento, pero no lo desea en la mayoría de los casos (guardar memoria). Agregue este oyente "attrchange" al elemento que desea observar.
DOMMutationObserver
.
Sugeriría que anule la función addClass. Puedes hacerlo de esta manera:
// 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 prueba de concepto:
Mira la esencia para ver algunas anotaciones y mantente actualizado:
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));
El uso es bastante simple, solo agregue un nuevo listender en el nodo que desea observar y manipule las clases como de costumbre:
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]
no está definido ... simplemente reemplace el final de las líneas con var oldClass
y var newClass
con la siguiente asignación:= (this[0] ? this[0].className : "");
utilizando la última mutación 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
});
// cualquier código que actualice div que tenga una clase required-entry que esté en $ target como $ target.addClass ('search-class');
change()
no se dispara cuando se agrega o elimina una clase CSS o cambia la definición. Se activa en circunstancias como cuando se selecciona o no se selecciona un valor de cuadro de selección.
No estoy seguro de si quiere decir si la definición de clase CSS se modifica (lo que se puede hacer mediante programación pero es tedioso y generalmente no se recomienda) o si se agrega o elimina una clase a un elemento. No hay forma de capturar de manera confiable este hecho en ninguno de los casos.
Por supuesto, podría crear su propio evento para esto, pero esto solo puede describirse como un aviso . No capturará código que no sea tuyo haciéndolo.
Alternativamente, podría anular / reemplazar los addClass()
métodos (etc.) en jQuery, pero esto no capturará cuando se haga a través de Javascript vainilla (aunque supongo que también podría reemplazar esos métodos).
Hay una forma más sin activar un evento personalizado
Un complemento de jQuery para monitorear los cambios de CSS del elemento HTML por Rick Strahl
Citando desde arriba
El complemento de reloj funciona al conectarse a DOMAttrModified en FireFox, a onPropertyChanged en Internet Explorer, o al usar un temporizador con setInterval para manejar la detección de cambios para otros navegadores. Desafortunadamente, WebKit no es compatible con DOMAttrModified de manera consistente en este momento, por lo que Safari y Chrome actualmente tienen que usar el mecanismo setInterval más lento.
Buena pregunta. Estoy usando el menú desplegable Bootstrap y necesitaba ejecutar un evento cuando un menú desplegable Bootstrap estaba oculto. Cuando se abre el menú desplegable, el div que lo contiene con un nombre de clase de "grupo de botones" agrega una clase de "abierto"; y el botón en sí tiene un atributo "expandido en aria" establecido en verdadero. Cuando se cierra el menú desplegable, esa clase de "abrir" se elimina del div que contiene y aria-expandido se cambia de verdadero a falso.
Eso me llevó a esta pregunta, de cómo detectar el cambio de clase.
Con Bootstrap, hay "Eventos desplegables" que se pueden detectar. Busque "Eventos desplegables" en este enlace. http://www.w3schools.com/bootstrap/bootstrap_ref_js_dropdown.asp
Aquí hay un ejemplo rápido y sucio de usar este evento en un menú desplegable Bootstrap.
$(document).on('hidden.bs.dropdown', function(event) {
console.log('closed');
});
Ahora me doy cuenta de que esto es más específico que la pregunta general que se hace. Pero me imagino que otros desarrolladores que intentan detectar un evento abierto o cerrado con un menú desplegable Bootstrap encontrarán esto útil. Al igual que yo, inicialmente pueden seguir el camino de simplemente tratar de detectar un cambio de clase de elemento (que aparentemente no es tan simple). Gracias.
Si necesita activar un evento específico, puede anular el método addClass () para activar un evento personalizado llamado 'classadded'.
Aquí como:
(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
// ...
});
Puede vincular el evento DOMSubtreeModified. Añado un ejemplo aquí:
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');
});
});
si sabe un evento que cambió la clase en primer lugar, puede usar un ligero retraso en el mismo evento y verificar la clase. ejemplo
//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');
});