web-dev-qa-db-ja.com

jQuery:DOMの変更をリッスンする方法は?

JQueryを使用して、DOMツリー全体で変更をリッスンすることは可能ですか?

私の特定の問題:html要素でtitleを実行すると、hover属性の内容をスタイリッシュな方法で表示する 'ツールチップ'関数があります。ただし、ホバーすると、標準でブラウザーはtitleを独自のボックスにレンダリングします。それを抑えたいのですが。したがって、最初にページがロードされたときにtitle属性の内容をカスタム(HTML5)のdata-title属性に移動すると、ツールチップ関数がdata-titleで機能するようになります。

問題は、後でHTMLを動的に追加/削除/変更する可能性があるため、これらの要素を「再バインド」する必要があることです。これらのタイトル属性をもう一度変更してください。そのような変更をリッスンし、要素を自動的に再バインドするイベントリスナーがあったらいいですね。

17
Tony Bogdanov

私の推測では、DOM変異イベントをリッスンしたいと思います。 DOMミューテーションイベントによって、マウスクリックなどの通常のJavaScriptイベントと同じように行うことができます。

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

例:

$("element-root").bind("DOMSubtreeModified", "CustomHandler");
35
nightf0x

[トニー会員の調査に応じて編集]

したがって、追加のコードがなければ、これは少し盲目的なショットですが、私にはここで2つのことを考える必要があるように見えます。1。デフォルトのブラウザーツールチップの動作。 2.更新される可能性のあるDOM、およびカスタムツールチップが機能し続ける機能。

#1について: カスタムイベントを要素にバインドするときに、event.preventDefault()を使用して、ツールチップが表示されないようにすることができます。 これは正しく動作しません。したがって、「title」属性を使い続けるための回避策は、値を取得し、それをデータオブジェクトにプッシュし($.data()関数)、次に空の文字列でタイトルをnullにすることです(removeAttrに一貫性がありません)。 。次に、mouseleaveで、データオブジェクトから値を取得し、それをタイトルにプッシュします。このアイデアはここから来ます: jQueryでブラウザーのツールチップを無効にする方法?

#2に関して:DOMの変更を再バインドする代わりに、破棄されることが決して予想されないリスナー要素に一度バインドするだけで済みます。通常、これはある種のコンテナー要素ですが、本当にすべてを含むコンテナーが必要な場合は、document(現在は非推奨の.live()に近い)にすることもできます。これは、私が考案した偽のマークアップを使用するサンプルです。

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

私の非現実的なマークアップ(この例のみ)はここにあります:

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

そしてフィドルがここにあります: http://jsfiddle.net/GVDqn/ またはいくつかの健全性チェック: http://jsfiddle.net/GVDqn/1/

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

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

2
Greg Pettit
0
Adam Merrifield

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

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

マウスオーバーイベントで関数を起動し、クラスが* field_title *のすべての要素で関数を起動したい場合は、次のようにします。

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

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

理にかなっていると思います:)

0