web-dev-qa-db-ja.com

jQuery - CSSクラスが変更された場合に発生するイベント

cSSクラスがjQueryで追加または変更された場合、どうすればイベントを発生させることができますか? CSSクラスの変更はjQueryのchange()イベントを発生させますか?

233
user237060

スクリプト内のクラスを変更するときはいつでも、あなた自身のイベントを発生させるためにtriggerを使うことができます。

$(this).addClass('someClass');
$(mySelector).trigger('cssClassChanged')
....
$(otherSelector).bind('cssClassChanged', data, function(){ do stuff });

それ以外の場合、いいえ、クラスが変更されたときにイベントを起動する方法はありません。 change()は、入力が変更された入力からフォーカスが離れた後にのみ起動します。

$(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>

jQueryトリガーの詳細

220
Jason

私見より良い解決策は@ RamboNo5と@Jasonによる2つの答えを組み合わせることです。

AddClass関数をオーバーライドして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
    });
});
134
Arash Milani

クラスの変更を検出したい場合は、Mutation Observersを使用するのが最善の方法です。これにより、属性の変更を完全に制御できます。ただし、リスナーを自分で定義し、それをリスニングしている要素に追加する必要があります。良いことは、リスナーが追加されたら手動で何かをトリガーする必要がないということです。

$(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
    }

});
});

この例ではイベントリスナがすべての要素に追加されていますが、ほとんどの場合はそうしたくありません(メモリを節約する)。観察したい要素にこの "attrchange"リスナーを追加してください。

53
Mr Br

AddClass関数をオーバーライドすることをお勧めします。あなたはそれをこうすることができます:

// 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
});
52
RamboNo5

単なる概念実証:

要点を見て注釈を確認し、最新の状態に保ちます。

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));

使い方はとても簡単です。観察したいノードに新しいリスナーを追加して、通常どおりクラスを操作します。

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');
20
yckart

最新の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
            });

//クラスを持つdivを更新するすべてのコードrequired-entry $ target.addClass( 'search-class')のように$ targetにあります。

7

CSSクラスが追加または削除されたり定義が変更されたりしても、change()は起動しません。選択ボックスの値が選択されているかどうかなどの状況で発生します。

CSSクラスの定義が変更されたのか(プログラム的には可能ですが面倒で一般的にはお勧めできません)、あるいはクラスが要素に追加または削除されたのかどうかはわかりません。どちらの場合も、これを確実に捉える方法はありません。

あなたはもちろんこれのためにあなた自身のイベントを作成することができますが、これは助言として記述されることができるだけです。あなたのやり方ではないコードを捉えることはありません。

あるいは、jQueryでaddClass()(etc)メソッドをオーバーライドまたは置換することもできますが、Vanilla Javascriptを介して実行した場合はこれは取得できません(ただし、これらのメソッドも置換できると思います)。

7
cletus

もう1つの方法がありますwithoutカスタムイベントをトリガーする

Rick StrahlによるHTML要素のCSSの変更を監視するためのjQueryプラグイン

上からの引用

監視プラグインは、FireFoxのDOMAttrModified、Internet ExplorerのonPropertyChanged、またはsetIntervalのタイマーを使用して他のブラウザの変更の検出を処理することによって機能します。残念ながらWebKitはDOMAttrModifiedを現時点では一貫してサポートしていないので、SafariとChromeは現在遅いsetIntervalメカニズムを使わなければならない。

7
Amitd

良い質問。私はブートストラップドロップダウンメニューを使用していて、ブートストラップドロップダウンが隠されたときにイベントを実行する必要がありました。ドロップダウンが開かれると、クラス名が "button-group"の含まれているdivが "open"のクラスを追加します。ボタン自体の "aria-expansion"属性はtrueに設定されています。ドロップダウンが閉じられると、そのクラス "open"はそれを含むdivから削除され、aria-expansionはtrueからfalseに切り替わります。

それで私は、クラスの変化をどうやって検出するかというこの疑問に私を導いた。

ブートストラップでは、検出可能な「ドロップダウンイベント」があります。このリンクで「ドロップダウンイベント」を探してください。 http://www.w3schools.com/bootstrap/bootstrap_ref_js_dropdown.asp

これはBootstrap Dropdownでこのイベントを使う簡単な例です。

$(document).on('hidden.bs.dropdown', function(event) {
    console.log('closed');
});

今、私はこれが尋ねられている一般的な質問より具体的であることに気づきます。しかし、Bootstrap Dropdownでオープンイベントまたはクローズイベントを検出しようとしている他の開発者がこれを役に立つと思うでしょう。私と同じように、彼らは最初は単に要素クラスの変更を検出しようとする道をたどっているかもしれません(これは明らかにそれほど単純ではありません)。ありがとう。

5
Ken Palmer

DOMSubtreeModifiedイベントをバインドできます。ここに例を追加します。

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');
  });
});

http://jsfiddle.net/hnCxK/13/

4
Sativa Diva

特定のイベントをトリガーする必要がある場合は、addClass()メソッドをオーバーライドして「classadded」というカスタムイベントを発生させることができます。

ここでどうやって:

(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
    // ...
});
4
micred
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');
});
0
Jérome Obbiet

そもそもどのイベントがクラスを変更したのかを知っているのなら、同じイベントに少し遅延をかけてクラスをチェックしてください。例

//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);
});

http://jsfiddle.net/GuDCp/3/

0
Nikos Tsagkas