Jak mogę uruchomić zdarzenie, jeśli klasa CSS zostanie dodana lub zmieniona za pomocą jQuery? Czy zmiana klasy CSS wywołuje change()
zdarzenie jQuery ?
Jak mogę uruchomić zdarzenie, jeśli klasa CSS zostanie dodana lub zmieniona za pomocą jQuery? Czy zmiana klasy CSS wywołuje change()
zdarzenie jQuery ?
Odpowiedzi:
Za każdym razem, gdy zmieniasz klasę w skrypcie, możesz użyć a, trigger
aby wywołać własne wydarzenie.
$(this).addClass('someClass');
$(mySelector).trigger('cssClassChanged')
....
$(otherSelector).bind('cssClassChanged', data, function(){ do stuff });
ale w przeciwnym razie nie, nie ma sposobu na uruchomienie zdarzenia, gdy klasa się zmieni. change()
strzela tylko wtedy, gdy fokus pozostawia wejście, którego wejście zostało zmienione.
$(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
zdarzenie, a wszystkie obiekty subskrybujące to zdarzenie mogą odpowiednio zareagować.
IMHO lepszym rozwiązaniem jest połączenie dwóch odpowiedzi @ RamboNo5 i @Jason
Mam na myśli przesłonięcie funkcji addClass i dodanie niestandardowego zdarzenia o nazwie 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
});
});
$()
momentu rozpoczęcia prawdziwej akcji.
cssClassChanged
zdarzenie z elementem, musisz mieć świadomość, że zostanie ono zwolnione, nawet jeśli jego dziecko zmieni klasę. Dlatego jeśli na przykład nie chcesz odpalić tego wydarzenia dla nich, po prostu dodaj coś $("#YourExampleElementID *").on('cssClassChanged', function(e) { e.stopPropagation(); });
po powiązaniu. W każdym razie naprawdę fajne rozwiązanie, dzięki!
Jeśli chcesz wykryć zmianę klasy, najlepszym sposobem jest użycie obserwatora mutacji, który daje ci pełną kontrolę nad każdą zmianą atrybutu. Musisz jednak samodzielnie zdefiniować słuchacza i dołączyć go do słuchanego elementu. Dobrą rzeczą jest to, że nie trzeba ręcznie uruchamiać niczego po dołączeniu detektora.
$(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
}
});
});
W tym przykładzie detektor zdarzeń jest dołączany do każdego elementu, ale w większości przypadków nie chcesz tego (oszczędzaj pamięć). Dołącz ten detektor „attrchange” do elementu, który chcesz obserwować.
DOMMutationObserver
.
Sugeruję przesłonięcie funkcji addClass. Możesz to zrobić w ten sposób:
// 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
});
Tylko dowód koncepcji:
Spójrz na sedno, aby zobaczyć niektóre adnotacje i być na bieżąco:
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));
Użycie jest dość proste, wystarczy dodać nowego listera w węźle, który chcesz obserwować, i jak zwykle manipulować klasami:
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]
jest niezdefiniowane ... po prostu zamień koniec linii na var oldClass
i var newClass
z następującym przypisaniem:= (this[0] ? this[0].className : "");
przy użyciu najnowszej mutacji 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
});
// każdy kod, który aktualizuje div mający wpis klasy wymagany, który jest w $ target, np. $ target.addClass ('search-class');
change()
nie jest uruchamiany po dodaniu lub usunięciu klasy CSS lub zmianie definicji. Uruchamia się w okolicznościach, takich jak wybranie lub odznaczenie wartości pola wyboru.
Nie jestem pewien, czy masz na myśli zmianę definicji klasy CSS (co można zrobić programowo, ale jest żmudna i ogólnie nie zalecana), czy też klasa jest dodawana lub usuwana z elementu. W obu przypadkach nie ma możliwości wiarygodnego uchwycenia tego zdarzenia.
Możesz oczywiście stworzyć własne wydarzenie w tym celu, ale można to opisać jedynie jako doradztwo . Nie będzie przechwytywać kodu, który nie należy do Ciebie.
Alternatywnie możesz zastąpić / zastąpić metody addClass()
(itp.) W jQuery, ale to nie zostanie przechwycone, gdy zostanie to zrobione za pomocą waniliowego Javascript (chociaż myślę, że możesz również zastąpić te metody).
Jest jeszcze jeden sposób bez wyzwalania niestandardowego zdarzenia
Wtyczka jQuery do monitorowania zmian HTML CSS elementu HTML przez Rick Strahl
Cytowanie z góry
Wtyczka zegarka działa poprzez podłączenie do DOMAttrModified w FireFox, onPropertyChanged w Internet Explorer lub za pomocą timera z setInterval do obsługi wykrywania zmian w innych przeglądarkach. Niestety WebKit nie obsługuje obecnie DOMAttrModified, więc Safari i Chrome muszą obecnie korzystać z wolniejszego mechanizmu setInterval.
Dobre pytanie. Korzystam z menu rozwijanego Bootstrap i potrzebowałem wykonać zdarzenie, gdy menu rozwijane Bootstrap było ukryte. Po otwarciu menu zawierającego div z nazwą klasy „grupa przycisków” dodaje klasę „otwarta”; a sam przycisk ma atrybut „aria-expanded” ustawiony na true. Kiedy menu rozwijane jest zamknięte, klasa „otwarta” jest usuwana z zawierającego div, a aria-expanded jest zmieniana z true na false.
Doprowadziło mnie to do pytania, jak wykryć zmianę klasy.
Dzięki Bootstrap można wykryć „Zdarzenia rozwijane”. Znajdź „Zdarzenia rozwijane” pod tym linkiem. http://www.w3schools.com/bootstrap/bootstrap_ref_js_dropdown.asp
Oto szybki i brudny przykład użycia tego zdarzenia w menu rozwijanym Bootstrap.
$(document).on('hidden.bs.dropdown', function(event) {
console.log('closed');
});
Teraz zdaję sobie sprawę, że jest to bardziej szczegółowe niż zadawane ogólne pytanie. Ale wyobrażam sobie, że inni programiści próbujący wykryć otwarte lub zamknięte zdarzenie za pomocą menu rozwijanego Bootstrap uznają to za pomocne. Podobnie jak ja, początkowo mogą pójść ścieżką po prostu próbując wykryć zmianę klasy elementu (co najwyraźniej nie jest takie proste). Dzięki.
Jeśli chcesz wyzwolić określone zdarzenie, możesz przesłonić metodę addClass (), aby uruchomić niestandardowe zdarzenie o nazwie „classadded”.
Oto jak:
(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
// ...
});
Możesz powiązać zdarzenie DOMSubtreeModified. Tutaj dodaję przykład:
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');
});
});
jeśli wiesz, które wydarzenie zmieniło klasę, możesz użyć niewielkiego opóźnienia na tym samym wydarzeniu i sprawdzić, czy klasa. przykład
//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');
});