Comment puis-je déclencher un événement si une classe CSS est ajoutée ou modifiée à l'aide de jQuery? Le changement d'une classe CSS déclenche-t-il l' change()
événement jQuery ?
Comment puis-je déclencher un événement si une classe CSS est ajoutée ou modifiée à l'aide de jQuery? Le changement d'une classe CSS déclenche-t-il l' change()
événement jQuery ?
Réponses:
Chaque fois que vous changez une classe dans votre script, vous pouvez utiliser un trigger
pour déclencher votre propre événement.
$(this).addClass('someClass');
$(mySelector).trigger('cssClassChanged')
....
$(otherSelector).bind('cssClassChanged', data, function(){ do stuff });
mais sinon, il n'y a aucun moyen de déclencher un événement quand une classe change. change()
ne se déclenche que lorsque le focus laisse une entrée dont l'entrée a été modifiée.
$(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
événement, et tous ces objets abonnés à cet événement peuvent réagir en conséquence.
À mon humble avis, la meilleure solution consiste à combiner deux réponses de @ RamboNo5 et @Jason
Je veux dire remplacer la fonction addClass et ajouter un événement personnalisé appelé 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
});
});
$()
, lorsque l'action réelle commence.
cssClassChanged
événement à un élément, vous devez être conscient qu'il sera déclenché même lorsque son enfant changera de classe. Par conséquent, si, par exemple, vous ne souhaitez pas déclencher cet événement pour eux, ajoutez simplement quelque chose comme $("#YourExampleElementID *").on('cssClassChanged', function(e) { e.stopPropagation(); });
après votre liaison. Quoi qu'il en soit, solution vraiment sympa, merci!
Si vous souhaitez détecter un changement de classe, la meilleure façon est d'utiliser les observateurs de mutation, ce qui vous donne un contrôle complet sur tout changement d'attribut. Cependant, vous devez définir l'auditeur vous-même et l'ajouter à l'élément que vous écoutez. Heureusement, vous n'avez pas besoin de déclencher quoi que ce soit manuellement une fois l'écouteur ajouté.
$(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
}
});
});
Dans cet exemple, l'écouteur d'événements est ajouté à chaque élément, mais vous ne le souhaitez pas dans la plupart des cas (économiser de la mémoire). Ajoutez cet écouteur "attrchange" à l'élément que vous souhaitez observer.
DOMMutationObserver
.
Je vous suggère de remplacer la fonction addClass. Vous pouvez le faire de cette façon:
// 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
});
Juste une preuve de concept:
Regardez l'essentiel pour voir quelques annotations et restez à jour:
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'utilisation est assez simple, il suffit d'ajouter un nouveau listender sur le nœud que vous souhaitez observer et manipuler les classes comme d'habitude:
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]
n'est pas défini ... remplacez simplement la fin des lignes par var oldClass
et var newClass
avec l'affectation suivante:= (this[0] ? this[0].className : "");
en utilisant la dernière mutation 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
});
// tout code qui met à jour div ayant une entrée obligatoire de classe qui est dans $ target comme $ target.addClass ('search-class');
change()
ne se déclenche pas lorsqu'une classe CSS est ajoutée ou supprimée ou que la définition change. Il se déclenche dans des circonstances comme lorsqu'une valeur de zone de sélection est sélectionnée ou désélectionnée.
Je ne sais pas si vous voulez dire si la définition de classe CSS est modifiée (ce qui peut être fait par programme mais est fastidieux et n'est généralement pas recommandé) ou si une classe est ajoutée ou supprimée à un élément. Il n'y a aucun moyen de capturer de manière fiable ce qui se passe dans les deux cas.
Vous pouvez bien sûr créer votre propre événement pour cela, mais cela ne peut être décrit que comme un conseil . Il ne capturera pas de code qui ne vous appartient pas.
Alternativement, vous pouvez remplacer / remplacer les addClass()
méthodes (etc) dans jQuery mais cela ne sera pas capturé quand cela sera fait via vanilla Javascript (bien que je suppose que vous pourriez également remplacer ces méthodes).
Il y a un autre moyen sans déclencher un événement personnalisé
Un plug-in jQuery pour surveiller les modifications CSS des éléments HTML par Rick Strahl
Citant d'en haut
Le plug-in de surveillance fonctionne en se connectant à DOMAttrModified dans FireFox, à onPropertyChanged dans Internet Explorer, ou en utilisant un minuteur avec setInterval pour gérer la détection des modifications pour d'autres navigateurs. Malheureusement, WebKit ne prend pas en charge DOMAttrModified de manière cohérente pour le moment, donc Safari et Chrome doivent actuellement utiliser le mécanisme setInterval plus lent.
Bonne question. J'utilise le menu déroulant Bootstrap et j'avais besoin d'exécuter un événement lorsqu'un Bootstrap Dropdown était masqué. Lorsque la liste déroulante est ouverte, le div contenant avec un nom de classe de "bouton-groupe" ajoute une classe de "open"; et le bouton lui-même a un attribut "aria-expand" défini sur true. Lorsque la liste déroulante est fermée, cette classe "open" est supprimée de la div contenant, et aria-expand est passé de true à false.
Cela m'a amené à cette question, de savoir comment détecter le changement de classe.
Avec Bootstrap, il existe des "événements de liste déroulante" qui peuvent être détectés. Recherchez "Dropdown Events" sur ce lien. http://www.w3schools.com/bootstrap/bootstrap_ref_js_dropdown.asp
Voici un exemple rapide et sale d'utilisation de cet événement sur une liste déroulante Bootstrap.
$(document).on('hidden.bs.dropdown', function(event) {
console.log('closed');
});
Maintenant, je me rends compte que c'est plus spécifique que la question générale qui est posée. Mais j'imagine que d'autres développeurs essayant de détecter un événement ouvert ou fermé avec une liste déroulante Bootstrap trouveront cela utile. Comme moi, ils peuvent initialement tenter de détecter un changement de classe d'élément (ce qui n'est apparemment pas si simple). Merci.
Si vous devez déclencher un événement spécifique, vous pouvez remplacer la méthode addClass () pour déclencher un événement personnalisé appelé «classadded».
Voici comment:
(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
// ...
});
Vous pouvez lier l'événement DOMSubtreeModified. J'ajoute un exemple ici:
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 vous connaissez un événement qui a changé la classe en premier lieu, vous pouvez utiliser un léger retard sur le même événement et vérifier la classe. exemple
//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');
});