jQueryを使用してクラス変更時にイベントを発生させる方法は?


回答:


172

クラスが変更されたときに発生するイベントはありません。別の方法は、プログラムでクラスを変更するときに手動でイベントを発生させることです。

$someElement.on('event', function() {
    $('#myDiv').addClass('submission-ok').trigger('classChange');
});

// in another js file, far, far away
$('#myDiv').on('classChange', function() {
     // do stuff
});

更新

この質問は何人かの訪問者を集めているようです、それでここに新しいものを使って既存のコードを修正する必要なしに使うことができるアプローチでアップデートがありますMutationObserver

var $div = $("#foo");
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    if (mutation.attributeName === "class") {
      var attributeValue = $(mutation.target).prop(mutation.attributeName);
      console.log("Class attribute changed to:", attributeValue);
    }
  });
});
observer.observe($div[0], {
  attributes: true
});

$div.addClass('red');
.red { color: #C00; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo" class="bar">#foo.bar</div>

MutationObserverは新しいブラウザ、特にChrome 26、FF 14、IE 11、Opera 15、Safari6でのみ使用できることに注意してください。詳細についてはMDNを参照してください。従来のブラウザをサポートする必要がある場合は、最初の例で概説した方法を使用する必要があります。


この回答の完了で、私はこれを見つけました:stackoverflow.com/a/1950052/1579667
Benj 2017年

1
@Benjこれは私の元の答え(つまり、を使用するtrigger())と同じですが、の使用により非常に古くなっていることに注意してくださいbind()。しかし、それがどのように「完了する」かはわかりません
Rory McCrossan 2018

私の場合、domノードに特定のクラスがMutationObserver機能するときにイベントを発生させる必要がありました
マリオ

1
これは、フィルタを使用してこの溶液の改良された形態であるstackoverflow.com/a/42121795/12074818
MVDeveloper1

20

元のjQueryのaddClass関数とremoveClass関数を、元の関数を呼び出してカスタムイベントをトリガーする独自の関数に置き換えることができます。(自己呼び出し無名関数を使用して元の関数参照を含める)

(function( func ) {
    $.fn.addClass = function() { // replace the existing function on $.fn
        func.apply( this, arguments ); // invoke the original function
        this.trigger('classChanged'); // trigger the custom event
        return this; // retain jQuery chainability
    }
})($.fn.addClass); // pass the original function as an argument

(function( func ) {
    $.fn.removeClass = function() {
        func.apply( this, arguments );
        this.trigger('classChanged');
        return this;
    }
})($.fn.removeClass);

そうすれば、残りのコードは期待どおりに単純になります。

$(selector).on('classChanged', function(){ /*...*/ });

更新:

このアプローチでは、クラスはjQueryのaddClassメソッドとremoveClassメソッドを介してのみ変更されることを前提としています。クラスが他の方法で変更された場合(DOM要素を介したクラス属性の直接操作など)MutationObserver、ここで受け入れられた回答で説明されているようなsのようなものを使用する必要があります。

また、これらの方法のいくつかの改善点として:

  • コールバック関数に引数として渡された特定のクラスを使用して、追加()または削除()されるクラスのイベントをトリガーし、特定のクラスが実際に追加(以前は存在しなかった)または削除(以前に存在)した場合にのみトリガーされます。classAddedclassRemoved
  • classChangedクラスが実際に変更された場合にのみトリガーされます

    (function( func ) {
        $.fn.addClass = function(n) { // replace the existing function on $.fn
            this.each(function(i) { // for each element in the collection
                var $this = $(this); // 'this' is DOM element in this context
                var prevClasses = this.getAttribute('class'); // note its original classes
                var classNames = $.isFunction(n) ? n(i, prevClasses) : n.toString(); // retain function-type argument support
                $.each(classNames.split(/\s+/), function(index, className) { // allow for multiple classes being added
                    if( !$this.hasClass(className) ) { // only when the class is not already present
                        func.call( $this, className ); // invoke the original function to add the class
                        $this.trigger('classAdded', className); // trigger a classAdded event
                    }
                });
                prevClasses != this.getAttribute('class') && $this.trigger('classChanged'); // trigger the classChanged event
            });
            return this; // retain jQuery chainability
        }
    })($.fn.addClass); // pass the original function as an argument
    
    (function( func ) {
        $.fn.removeClass = function(n) {
            this.each(function(i) {
                var $this = $(this);
                var prevClasses = this.getAttribute('class');
                var classNames = $.isFunction(n) ? n(i, prevClasses) : n.toString();
                $.each(classNames.split(/\s+/), function(index, className) {
                    if( $this.hasClass(className) ) {
                        func.call( $this, className );
                        $this.trigger('classRemoved', className);
                    }
                });
                prevClasses != this.getAttribute('class') && $this.trigger('classChanged');
            });
            return this;
        }
    })($.fn.removeClass);
    

これらの置換関数を使用すると、classChangedを介して変更されたクラス、またはコールバック関数の引数をチェックすることで追加または削除された特定のクラスを処理できます。

$(document).on('classAdded', '#myElement', function(event, className) {
    if(className == "something") { /* do something */ }
});

1
これは正常に機能しますが、「残りのコード」では、イベントハンドラーをターゲットセレクターに委任して、新しい要素にバインドできるようにする必要があります$(parent_selector).on('classChanged', target_selector, function(){ /*...*/ });。動的に作成された要素がハンドラーを起動しなかった理由を確認するのに少し時間がかかりました。learn.jquery.com/events/event-delegation
Timm


2

次のようなものを使用できます。

$(this).addClass('someClass');

$(Selector).trigger('ClassChanged')

$(otherSelector).bind('ClassChanged', data, function(){//stuff });

それ以外の場合は、クラスが変更されたときにイベントを発生させる事前定義された関数はありません。

トリガーについて詳しくはこちらをご覧ください


1
イベントのハンドラーは、イベントをトリガーするアイテムと同じである必要があります。$(this).addClass( 'someClass'); $(Selector).trigger( 'ClassChanged')//同じセレクターである必要があります$(Selector).bind( 'ClassChanged'、data、function(){// stuff});
Meko Perez Estevez 2013年

3
あなたがリンクを提供するならば、良いはいすぎる場合は、ここからコピーしてきたようだstackoverflow.com/questions/1950038/...
シンSatinder
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.