Làm cách nào để khởi chạy một sự kiện nếu một lớp CSS được thêm hoặc thay đổi bằng jQuery? Việc thay đổi một lớp CSS có kích hoạt change()
sự kiện jQuery không?
Làm cách nào để khởi chạy một sự kiện nếu một lớp CSS được thêm hoặc thay đổi bằng jQuery? Việc thay đổi một lớp CSS có kích hoạt change()
sự kiện jQuery không?
Câu trả lời:
Bất cứ khi nào bạn thay đổi một lớp trong kịch bản của mình, bạn có thể sử dụng một trigger
để nâng cao sự kiện của riêng bạn.
$(this).addClass('someClass');
$(mySelector).trigger('cssClassChanged')
....
$(otherSelector).bind('cssClassChanged', data, function(){ do stuff });
nhưng nếu không, không, không có cách nào để khởi động một sự kiện khi một lớp thay đổi. change()
chỉ kích hoạt sau khi lấy nét để lại một đầu vào có đầu vào bị thay đổi.
$(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
sự kiện và tất cả những đối tượng đăng ký vào sự kiện đó có thể phản ứng tương ứng.
IMHO giải pháp tốt hơn là kết hợp hai câu trả lời của @ RamboNo5 và @Jason
Tôi có nghĩa là ghi đè hàm addClass và thêm một sự kiện tùy chỉnh được gọi là 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
});
});
$()
, khi hành động thực sự bắt đầu.
cssClassChanged
sự kiện này với một yếu tố, bạn phải biết rằng nó sẽ bị sa thải ngay cả khi con của nó thay đổi lớp. Do đó, ví dụ nếu bạn không muốn tổ chức sự kiện này cho họ, chỉ cần thêm một cái gì đó như $("#YourExampleElementID *").on('cssClassChanged', function(e) { e.stopPropagation(); });
sau khi liên kết của bạn. Dù sao, giải pháp thực sự tốt đẹp, cảm ơn!
Nếu bạn muốn phát hiện thay đổi lớp, cách tốt nhất là sử dụng Trình quan sát đột biến, cho phép bạn kiểm soát hoàn toàn mọi thay đổi thuộc tính. Tuy nhiên, bạn cần tự xác định người nghe và nối nó vào phần tử bạn đang nghe. Điều tốt là bạn không cần kích hoạt bất cứ thứ gì một cách thủ công một khi người nghe được nối thêm.
$(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
}
});
});
Trong ví dụ này, trình nghe sự kiện được thêm vào mọi phần tử, nhưng bạn không muốn điều đó trong hầu hết các trường hợp (lưu bộ nhớ). Nối trình nghe "attrchange" này vào phần tử bạn muốn quan sát.
DOMMutationObserver
.
Tôi sẽ đề nghị bạn ghi đè hàm addClass. Bạn có thể làm theo cách này:
// 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
});
Chỉ là một bằng chứng về khái niệm:
Nhìn vào ý chính để xem một số chú thích và cập nhật:
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));
Cách sử dụng khá đơn giản, chỉ cần thêm một trình lắng nghe mới vào nút mà bạn muốn quan sát và thao tác các lớp như thường lệ:
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]
không được xác định ... chỉ cần thay thế phần cuối của dòng bằng var oldClass
và var newClass
gán sau:= (this[0] ? this[0].className : "");
sử dụng đột biến jquery mới nhất
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
});
// bất kỳ mã nào cập nhật div có lớp bắt buộc nhập trong mục tiêu $ như $ target.addClass ('search-class');
change()
không kích hoạt khi một lớp CSS được thêm hoặc xóa hoặc định nghĩa thay đổi. Nó kích hoạt trong các trường hợp như khi giá trị hộp chọn được chọn hoặc không được chọn.
Tôi không chắc nếu bạn định nghĩa nếu định nghĩa lớp CSS bị thay đổi (có thể được thực hiện theo chương trình nhưng tẻ nhạt và thường không được đề xuất) hoặc nếu một lớp được thêm hoặc xóa thành phần tử. Không có cách nào đáng tin cậy để nắm bắt điều này xảy ra trong cả hai trường hợp.
Tất nhiên bạn có thể tạo sự kiện của riêng bạn cho việc này nhưng điều này chỉ có thể được mô tả là tư vấn . Nó sẽ không bắt được mã mà không phải của bạn làm điều đó.
Ngoài ra, bạn có thể ghi đè / thay thế các addClass()
phương thức (vv) trong jQuery nhưng điều này sẽ không nắm bắt được khi nó được thực hiện thông qua Javascript vanilla (mặc dù tôi đoán bạn cũng có thể thay thế các phương thức đó).
Có một cách nữa mà không kích hoạt một sự kiện tùy chỉnh
Trình cắm jQuery để theo dõi các thay đổi CSS của phần tử Html của Rick Strahl
Trích dẫn từ trên cao
Trình cắm đồng hồ hoạt động bằng cách kết nối với DOMAttrModified trong FireFox, onPropertyChanged trong Internet Explorer hoặc bằng cách sử dụng bộ hẹn giờ với setInterval để xử lý phát hiện các thay đổi cho các trình duyệt khác. Thật không may, WebKit không hỗ trợ DOMAttrModified một cách nhất quán vào lúc này vì vậy Safari và Chrome hiện phải sử dụng cơ chế setInterval chậm hơn.
Câu hỏi hay. Tôi đang sử dụng Menu thả xuống Bootstrap và cần thiết để thực hiện một sự kiện khi Dropstrap Dropdown bị ẩn. Khi thả xuống được mở, div chứa với tên lớp là "nhóm nút" sẽ thêm một lớp "mở"; và bản thân nút có thuộc tính "aria-extend" được đặt thành true. Khi đóng cửa thả xuống, lớp "mở" đó sẽ bị xóa khỏi div chứa và mở rộng aria được chuyển từ true thành false.
Điều đó dẫn tôi đến câu hỏi này, về cách phát hiện sự thay đổi của lớp.
Với Bootstrap, có "Sự kiện thả xuống" có thể được phát hiện. Tìm "Sự kiện thả xuống" tại liên kết này. http://www.w3schools.com/bootstrap/bootstrap_Vf_js_dropdown.asp
Dưới đây là một ví dụ nhanh và bẩn về việc sử dụng sự kiện này trên Dropstrap Dropstrap.
$(document).on('hidden.bs.dropdown', function(event) {
console.log('closed');
});
Bây giờ tôi nhận ra điều này cụ thể hơn câu hỏi chung đang được hỏi. Nhưng tôi tưởng tượng các nhà phát triển khác đang cố gắng phát hiện một sự kiện mở hoặc đóng bằng Dropstrap Dropdown sẽ thấy điều này hữu ích. Giống như tôi, ban đầu họ có thể đi theo con đường chỉ đơn giản là cố gắng phát hiện sự thay đổi của lớp phần tử (điều này dường như không đơn giản như vậy). Cảm ơn.
Nếu bạn cần kích hoạt một sự kiện cụ thể, bạn có thể ghi đè phương thức addClass () để khởi chạy một sự kiện tùy chỉnh có tên là 'classadded'.
Đây như thế nào:
(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
// ...
});
Bạn có thể liên kết sự kiện DOMSubtreeModified. Tôi thêm một ví dụ ở đây:
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');
});
});
nếu bạn biết một sự kiện nào đó đã thay đổi lớp ở nơi đầu tiên, bạn có thể sử dụng một chút chậm trễ cho cùng một sự kiện và kiểm tra lớp. thí dụ
//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');
});