この DOM イベントを活用する必要があります。IE には onpropertychange があり、必要なことも実行します。ただし、Webkit はこのイベントをサポートしていないようです。私が使用できる代替手段はありますか?
5 に答える
Chrome はイベントをディスパッチしませんDOMAttrModified
が、2011 年以降、軽量化されたミューテーション オブザーバーがサポートされており、これらは属性の変更にも対応しています。
ドキュメント本文の例を次に示します。
var element = document.body, bubbles = false;
var observer = new WebKitMutationObserver(function (mutations) {
mutations.forEach(attrModified);
});
observer.observe(element, { attributes: true, subtree: bubbles });
function attrModified(mutation) {
var name = mutation.attributeName,
newValue = mutation.target.getAttribute(name),
oldValue = mutation.oldValue;
console.log(name, newValue, oldValue);
}
単純な属性変更の場合、console.log
ステートメントは次のように出力します。
<body color="black">
<script type="text/html">
document.body.setAttribute("color", "red");
</script>
</body>
コンソール:
> color red black
(すべての属性の変更を監視するのではなく)への呼び出しを単に検出することに満足している場合は、setAttribute()
次のようにしてすべての要素でそのメソッドをオーバーライドできます。
Element.prototype._setAttribute = Element.prototype.setAttribute
Element.prototype.setAttribute = function(name, val) {
var e = document.createEvent("MutationEvents");
var prev = this.getAttribute(name);
this._setAttribute(name, val);
e.initMutationEvent("DOMAttrModified", true, true, null, prev, val, name, 2);
this.dispatchEvent(e);
}
同じ質問があり、 を変更することを考えていたので、Sean が行ったsetAttribute
ことを見て、それをコピーしました。属性が同じ値に繰り返し設定されたときに発生していたことを除いて、うまく機能したので、値が変更されていない場合はイベントの発生をスキップするようにコピーにチェックを追加しました. また、数値を文字列に強制する理論的根拠に基づいて も追加したため、比較ではそれが予測されるはずです。val = String(val)
setAttribute
私の修正版は次のとおりです。
var emulateDOMAttrModified = {
isSupportedNatively: function () {
var supported = false;
function handler() {
supported = true;
}
document.addEventListener('DOMAttrModified', handler);
var attr = 'emulateDOMAttrModifiedTEST';
document.body.setAttribute(attr, 'foo'); // aka $('body').attr(attr, 'foo');
document.removeEventListener('DOMAttrModified', handler);
document.body.removeAttribute(attr);
return supported;
},
install: function () {
if (!this.isSupportedNatively() &&
!Element.prototype._setAttribute_before_emulateDOMAttrModified) {
Element.prototype._setAttribute_before_emulateDOMAttrModified = Element.prototype.setAttribute
Element.prototype.setAttribute = function(name, val) {
var prev = this.getAttribute(name);
val = String(val); /* since attributes do type coercion to strings,
do type coercion here too; in particular, D3 animations set x and y to a number. */
if (prev !== val) {
this._setAttribute_before_emulateDOMAttrModified(name, val);
var e = document.createEvent('MutationEvents');
e.initMutationEvent('DOMAttrModified', true, true, null, prev, val, name, 2);
this.dispatchEvent(e);
}
};
}
}
};
// Install this when loaded. No other file needs to reference this; it will just make Chrome and Safari
// support the standard same as Firefox does.
emulateDOMAttrModified.install();
@Filip が提供するソリューションは近いですが (当時は機能していた可能性があります)、古い属性値の配信をリクエストする必要があります。
したがって、次のように変更する必要があります。
observer.observe(element, { attributes: true, subtree: bubbles });
これに:
observer.observe(element, { attributes: true, attributeOldvalue:true, subtree: bubbles });
そうしないと、oldValues が表示されません (代わりに null が返されます)。これは、Chrome 34.0.1847.131 (公式ビルド 265687) でテストされています
コードを参照 してください。それがあなたに適していない場合、この要求を満たすことができる「醜い」ソリューションは setInterval(function(){}, delay) にする必要があります。それ以外の場合は、上記の Sean Hogan の投稿を参照してください。