2012-07-15 29 views
38

特定のDOM要素の子のいずれかで属性の変更を監視する必要があります。今のところ、私はmutation eventsを使っています。DOMの変更を監視する、エレガントな方法

問題は - バグだった。クロムの下でDOMAttrModifiedは発射されなかったが、DOMSubtreeModifiedはあった。問題は簡単に解決できました。他のイベントが発生した場合はDOMSubtreeModifiedが発生するため、DOMSubtreeModifiedを聞いただけです。

とにかく、最近のバージョンでは、属性が変更された場合、Chromiumは何も実行を停止しました。

ただし、新しいMutation Observer APIは問題なく動作します。

これまでは、特定の要素のサブツリーを変更したときにコールバックを行うだけで済みました。他のものは変更されていないため、私は突然変異イベントを使用して問題を解決しました。& )を同じコードで使用します。

しかし、今私は(削除したノード上の例えば新しいノード上で、)イベントのより強力なフィルタリングを行う必要がある - そうはエレガントな使用に私をできるようになること、おそらくjQueryのプラグイン、ライブラリがありますこれらのAPIのと利用可能な場合は、変異イベントをフォールバックとして特定のイベントタイプをフィルタリングする機能(たとえば、要素の追加、属性の変更など)。

など。

$("#test").watch({onNewElement: 1}, function(newElement){}) 
$("#test").watch({onNewAttribute: 1}, function(modifiedElement) {}) 

またはjQueryの

なし
watchChanges("#test", {onNewElement: 1}, function(newElement){}) 
watchChanges("#test", {onNewAttribute: 1}, function(modifiedElement){}) 
+0

、それが唯一の新しいAPIをサポートしています。http://code.google.com/p/mutation-summary/ 。私はまた、あなたが求めているものの単純なバージョンであると思われるこれを見つけました:http://stackoverflow.com/questions/10868104/can-you-have-a-javascript-hook-trigger-after-a- dom-elements-style-object-change – thirtydot

+0

私も突然変異サマリを見つけましたが、フォールバックとして突然変異イベントをサポートしていません。 あなたが投稿したスレッドの最初の答えは、基本的に私のコードで属性の変化を観察するために行うことです。 同じ原理で、変異観察者と(フォールバックとして)イベントの両方を使用して特定のDOMイベントを監視できるライブラリを構築できます。それが私の必要なものです。 – Ivo

+2

+1:私は本当に「ベストプラクティス」の質問を掘り下げます。 –

答えて

2

この作品は、でしょうか? jQueryを使って効率的なDOMの監視のために

http://darcyclarke.me/development/detect-attribute-changes-with-jquery/

$.fn.watch = function(props, callback, timeout){ 
    if(!timeout) 
     timeout = 10; 
    return this.each(function(){ 
     var el  = $(this), 
      func = function(){ __check.call(this, el) }, 
      data = { props: props.split(","), 
         func: callback, 
         vals: [] }; 
     $.each(data.props, function(i) { data.vals[i] = el.css(data.props[i]); }); 
     el.data(data); 
     if (typeof (this.onpropertychange) == "object"){ 
      el.bind("propertychange", callback); 
     } else if ($.browser.mozilla){ 
      el.bind("DOMAttrModified", callback); 
     } else { 
      setInterval(func, timeout); 
     } 
    }); 
    function __check(el) { 
     var data = el.data(), 
      changed = false, 
      temp = ""; 
     for(var i=0;i < data.props.length; i++) { 
      temp = el.css(data.props[i]); 
      if(data.vals[i] != temp){ 
       data.vals[i] = temp; 
       changed = true; 
       break; 
      } 
     } 
     if(changed && data.func) { 
      data.func.call(el, data); 
     } 
    } 
} 
+0

私はそれを見ましたが、属性のためだけです。さらに、ブラウザがDOMAttrModifiedをサポートしていても、setIntervalに戻ります。 – Ivo

+0

@Ivo権利。ここに考えがあります - あなたはdomに起こっているこれらのすべての変更をコントロールしていますか?変更/追加/削除イベントをトリガするためにjquery操作メソッドをオーバーライドすることを検討しましたか(ただし、すべての変更はjqueryによって行われるものとします)。それは、あなたが探しているものではなく、仕事が多いことを知っています。 –

+1

私は既に長い時間前に仕事を終えました。私は、属性を監視するために突然変異イベントと観察者の両方を使用しています。そして、DOM上に新しく追加されたものを見るためにイベントだけを使用します。 contenteditable/WYSIHTML5エディタを介して行われた変更を監視します。しかし、それは私がサポートしようとしているブラウザではすべて機能します。 これは「ベストアプローチ」の問題です。 そして、猿のパッチを当てるjQueryは悪い考えのようです。 DOM APIを猿でパッチする方が適切かもしれませんが、私はまだ分かりません。 – Ivo

2

、あなたはjQuery Behavior Plugin(免責事項:私は著者です)を見かかることがありますLive Queryの最適化されたバージョンを利用しています。私は何年も何年も問題なく、いくつかの製品に使っています。

編集:属性の変更のためのリスニングは次のように動作します:いくつかはこれを見つけたサーチし

$.behavior({ 
    'div:first': { 
     'changeAttr': function (event, data) { 
      console.log('Attribute "' + data.attribute + '" changed from "' + data.from + '" to "' + data.to + '"'); 
     } 
    } 
}); 

$('div:first').attr('foo', 'bar'); 
関連する問題