Есть ли альтернатива DOMAttrModified, которая будет работать в webkit
Мне нужно использовать это событие 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);
}
У меня был тот же вопрос, и я думал о модификации 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) m.
Пожалуйста, используйте код: https://github.com/meetselva/attrchange/blob/master/attrchange.js"DOMAttrModified" + ("propertychange" для IE) используются там, как и в вашем случае. Если он вам не подходит, то "уродливое" решение, которое может удовлетворить это требование, должно быть установлено setInterval(function(){}, delay). В противном случае см. Пост Шона Хогана выше.