[解決済み】DOMの変更を検出する
質問
htmlにdivやinputが追加されたときに関数を実行したいのですが、どうすればいいですか? これは可能でしょうか?
例えば、テキスト入力が追加された場合、その関数が呼ばれるようにします。
どのように解決するのですか?
2015年アップデート、新
MutationObserver
はモダンブラウザでサポートされています。
Chrome 18+、Firefox 14+、IE 11+、Safari 6+。
古いものに対応する必要がある場合は、この中で紹介されているような他のアプローチに頼ってみてもいいかもしれません。 5 (!)年前の回答は以下。ドラゴンがいる。お楽しみに :)
他の誰かがドキュメントを変更しているのですか?なぜなら、もしあなたが変更を完全にコントロールできるのであれば、あなたはただ自分自身の
domChanged
API - 関数やカスタムイベント - を使って、何かを変更するたびにそれをトリガー/コールします。
その DOM Level-2には 変異イベントの種類 しかし、古いバージョンの IE ではサポートされていません。なお、ミューテーションイベントは DOM3 Events 仕様では非推奨となっています。 を持ち、かつ パフォーマンスペナルティ .
突然変異のイベントをエミュレートするために
onpropertychange
IEで
(そして、それらが利用できない場合は、ブルートフォースアプローチにフォールバックします)。
については フル domChangeの間隔が長すぎる可能性があります。ドキュメント全体の現在の状態を保存し、すべての要素のすべてのプロパティが同じであることを確認する必要があると想像してください。
たぶん、(質問にあったように)要素とその順序にしか興味がないのであれば、このように
getElementsByTagName("*")
は動作します。これは、要素を追加したり、削除したり、要素を置き換えたり、文書の構造を変更したりすると、自動的に発火します。
概念実証を書きました。
(function (window) {
var last = +new Date();
var delay = 100; // default delay
// Manage event queue
var stack = [];
function callback() {
var now = +new Date();
if (now - last > delay) {
for (var i = 0; i < stack.length; i++) {
stack[i]();
}
last = now;
}
}
// Public interface
var onDomChange = function (fn, newdelay) {
if (newdelay) delay = newdelay;
stack.push(fn);
};
// Naive approach for compatibility
function naive() {
var last = document.getElementsByTagName('*');
var lastlen = last.length;
var timer = setTimeout(function check() {
// get current state of the document
var current = document.getElementsByTagName('*');
var len = current.length;
// if the length is different
// it's fairly obvious
if (len != lastlen) {
// just make sure the loop finishes early
last = [];
}
// go check every element in order
for (var i = 0; i < len; i++) {
if (current[i] !== last[i]) {
callback();
last = current;
lastlen = len;
break;
}
}
// over, and over, and over again
setTimeout(check, delay);
}, delay);
}
//
// Check for mutation events support
//
var support = {};
var el = document.documentElement;
var remain = 3;
// callback for the tests
function decide() {
if (support.DOMNodeInserted) {
window.addEventListener("DOMContentLoaded", function () {
if (support.DOMSubtreeModified) { // for FF 3+, Chrome
el.addEventListener('DOMSubtreeModified', callback, false);
} else { // for FF 2, Safari, Opera 9.6+
el.addEventListener('DOMNodeInserted', callback, false);
el.addEventListener('DOMNodeRemoved', callback, false);
}
}, false);
} else if (document.onpropertychange) { // for IE 5.5+
document.onpropertychange = callback;
} else { // fallback
naive();
}
}
// checks a particular event
function test(event) {
el.addEventListener(event, function fn() {
support[event] = true;
el.removeEventListener(event, fn, false);
if (--remain === 0) decide();
}, false);
}
// attach test events
if (window.addEventListener) {
test('DOMSubtreeModified');
test('DOMNodeInserted');
test('DOMNodeRemoved');
} else {
decide();
}
// do the dummy test
var dummy = document.createElement("div");
el.appendChild(dummy);
el.removeChild(dummy);
// expose
window.onDomChange = onDomChange;
})(window);
使用方法
onDomChange(function(){
alert("The Times They Are a-Changin'");
});
IE 5.5+、FF 2+、Chrome、Safari 3+、Opera 9.6+で動作します。
関連
-
[解決済み】ある要素が可視DOMに存在するかどうかを確認するにはどうすればいいですか?
-
[解決済み】コンソールがUnterminated JSX contentsエラーを投げる【終了しました
-
[解決済み】ある要素を別の要素に移動させるには?
-
[解決済み] 要素外でのクリックを検出するにはどうすればよいですか?
-
[解決済み] JavaScriptで "use strict "は何をするのか、その根拠は?
-
[解決済み] なぜGoogleはJSONレスポンスにwhile(1);を前置するのでしょうか?
-
[解決済み] event.preventDefault() vs. return false
-
[解決済み] JavaScriptで文字列をbooleanに変換するにはどうしたらいいですか?
-
[解決済み] jQueryで要素にスクロールする
-
[解決済み] JavaScript で DOM ノードのすべての子要素を削除する
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】 Uncaught TypeError: data.push is not a function
-
[解決済み】Uncaught TypeError: nullのプロパティ'value'を読み取ることができない
-
[解決済み】JavaScriptのinnerHTMLで要素が更新されない
-
[解決済み】ある要素が可視DOMに存在するかどうかを確認するにはどうすればいいですか?
-
[解決済み】getElementByIdはnullを返す?[クローズド]
-
[解決済み】エラー:リスン EACCES 0.0.0.0:80 OSx Node.js
-
[解決済み】JS ファイルが net::ERR_ABORTED 404 (Not Found) を取得する)
-
[解決済み】PhantomJS 2.1.1を使用してReactJSアプリケーションをレンダリングできない理由とは?
-
[解決済み】このオブジェクトの "forEach "はなぜ関数でないのですか?
-
[解決済み】Syntax error: JavaScriptの不正なreturnステートメント