2012-02-28 6 views
17

jQueryを使ってDOMツリー全体の変更をどのように聞くことができますか?jQuery:DOMの変更をリッスンする方法

私の特有の問題をhtml要素に使用すると、title属性の内容をスタイリッシュな方法で表示するツールヒント機能があります。しかし、あなたがホバーすると、ブラウザは標準でtitleをそれ自身のボックスにレンダリングします。私はそれを抑えたいです。だから私が考えているのは、最初にページが読み込まれたときに、属性の内容をカスタム(HTML5)data-title属性に移動してから、ツールチップの機能がdata-titleで機能するようにすることです。

後で、HTMLを動的に追加/削除/変更する可能性があるので、それらの要素を「再バインド」する必要があります。これらの要素を再度変更してください。そのような変更を私のためにリッスンし、要素を自動的にリバインドするイベントリスナーがあれば、いいでしょう。

+0

可能重複[DOMが変更されたときを識別する方法?](http://stackoverflow.com/questions/3744706/how-to-identify-when-the -dom-has-been-changed) –

+2

は、DOMのあらゆる変更を聴き取るように思えますし、毎回あなたの要素を検索するのは本当に高価になるでしょう。 – charlietfl

+0

[jQuery DOMの変更リスナーはありますか?](http://stackoverflow.com/questions/2844565/is-there-a-jquery-dom-change-listener) – APerson

答えて

33

私の最高の推測では、DOMの突然変異事象を聞きたいということです。 これは、マウスのクリックなどの通常のjavascriptイベントとしてDOM突然変異イベントによって行うことができます。

これを参照してください。W3 MutationEvent

例:

$("element-root").bind("DOMSubtreeModified", "CustomHandler"); 
+1

引用符は必要ありません。イベントにバインドされる関数を取得する方法の1つです。 – MacMac

+1

このコードは短く見えるかもしれませんが、ブラウザ上に表示される負荷は、以下のイベント委譲ソリューションが存在する場合、このユースケースでは不可能です。 – charlietfl

+0

私の間違い..私は急いで引用を追加しました – nightf0x

2

[メンバートニーによって研究への応答で編集]

したがって、追加のコードなしで、これはブラインドショットのビットでありますしかし、私にはここで考えるべき2つのことがあるようです:1.デフォルトのブラウザのツールチップの動作。 2.潜在的に更新されるDOMとカスタムツールチップが機能し続ける能力。

#1:についてカスタムイベントを要素にバインドすると、ツールチップが表示されないようにevent.preventDefault()を使用できます。これは正しく動作しません。したがって、 "title"属性を使用したまま使用する場合の回避策は、値を取得してデータオブジェクト($.data()関数)にプッシュし、空の文字列(removeAttrが矛盾している)でタイトルをnullにすることです。その後、mouseleaveで、データオブジェクトから値を取得し、タイトルに戻します。この考え方はここから来ます:How to disable tooltip in the browser with jQuery?

#2について:DOM変更に再バインドするのではなく、破壊されることは決してないリスナー要素に一度だけバインドする必要があります。通常、これは何らかのコンテナ要素ですが、実際には包括的なコンテナが必要な場合はdocument(現在は非推奨の.live()となります)でもかまいません。ここに私自身の工夫のいくつかの偽のマークアップを使用するサンプルです:

<div class="section"> 
    <a href="#" title="foo">Hover this foo!</a> 
    <div id="notatooltip"></div> 
</div> 

そして、フィドルはこちらです::(ちょうどこの例)

var container = $('.section'); 

container.on('mouseenter', 'a', function() { 
    var $this = $(this); 
    var theTitle = $this.attr('title'); 
    $this.attr('title', ''); 
    $('#notatooltip').html(theTitle); 
    $.data(this, 'title', theTitle); 
}); 

container.on('mouseleave', 'a', function() { 
    $('#notatooltip').html(''); 
    var $this = $(this); 
    var storedTitle = $.data(this, 'title'); 
    $this.attr('title', storedTitle); 
}); 

私の非現実的なマークアップはここにあるhttp://jsfiddle.net/GVDqn/ または一部をhttp://jsfiddle.net/GVDqn/1/

これを行うにはもっと最適な方法があります(2つの別々のイベントを1つのセレクタで2つの別々の関数にバインドできるかどうかは正直に研究していませんでしたが)。

DOMの変更に基づいて再バインドする必要はありません。委任されたリスナーは自動的にそれを処理します。そして、それを防ぐだけで、デフォルトのツールチップの機能を妨げることができるはずです。

+0

ここで最も感覚的なアプローチです...マウスの中でタイトルが$(this).data( 'title')に移動されたかどうかをテストできますか – charlietfl

+0

は最も洗練されたソリューションでした。 'preventDefault'は' mouseover'(少なくともChromeでは)でタイトルを表示できないようです - http://code.google.com/p/chromium/issues/detail?id=42549 –

+0

@Tony Good find;私はFxでも失敗したと思う。私は新しいコードで更新しました。 –

0

Greg Pettitが指摘したように、要素でon()関数を使用する必要があります。

これは、セレクタをイベントにバインドできるようにするため、セレクタから返されたオブジェクトが利用可能なときにjQueryがこのイベントハンドラを追加します。

あなたがイベントの上にマウスの上に発射する機能を望んでいたし、あなたはそれがのクラスにすべての要素に発砲したい場合は* FIELD_TITLE *あなたがこれを行うだろう:

$('.field_title').bind('mouseenter', function() { doSomething(); }); 

これは、上のトリガされます* field_title *のクラスを持つオブジェクト上のオーバーマウスオーバーイベント。doSomething()を実行します。

理にかなっている希望:)の

+1

あなたはタイプミスがあります。 '.bind( 'mouseenter')' not '。( 'mouseenter')'にする必要があります。 – MacMac

関連する問題