há uma alternativa para DOMAttrModified que irá trabalhar em webkit
-
18-09-2019 - |
Pergunta
Eu preciso aproveitar este evento DOM. IE tem onPropertyChange, que faz o que eu preciso fazer também. Webkit não parece apoiar este evento, no entanto. Existe uma alternativa que eu poderia usar?
Solução
Embora Chrome faz não eventos expedição DOMAttrModified
, os observadores de mutação mais lightweighted são suportados desde 2011 e estes trabalho para alterações de atributo também.
Aqui está um exemplo para o corpo do documento:
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);
}
Para uma mudança atributo simples, a declaração console.log
iria imprimir:
<body color="black">
<script type="text/html">
document.body.setAttribute("color", "red");
</script>
</body>
Console:
> color red black
Outras dicas
Se você está feliz com apenas detectar chamadas para setAttribute()
(em oposição a monitorar todas as modificações de atributos), então você poderia sobrepor-se que o método em todos os elementos com:
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);
}
Eu tive a mesma pergunta e estava pensando em modificar setAttribute
, então vendo que Sean fez , Copiei isso. Funcionou muito bem, exceto que ele estava atirando quando um atributo foi repetidamente definido para o mesmo valor, então eu adicionei um cheque para minha cópia para pular disparando o evento se o valor não está sendo alterado. Eu também acrescentou val = String(val)
, com base no argumento de que setAttribute
irá coagir números para strings, por isso a comparação deve antecipar isso.
Minha versão modificada é:
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();
Por favor, consulte código: https://github.com/meetselva/attrchange/blob/master/attrchange.js 'DOMAttrModified' + ( 'PropertyChange' para IE) são usadas lá como no seu caso. Se não é adequado para você, a solução "feio" que pode satisfazer essa demanda deve ser setInterval (function () {}, atraso) veja Caso contrário Sean Hogan post acima.
A solução fornecida pela @Filip está perto (e pode ter trabalhado no momento), mas agora você precisa solicitar a entrega do valor do atributo de idade.
Assim, você vai querer mudar:
observer.observe(element, { attributes: true, subtree: bubbles });
a esta:
observer.observe(element, { attributes: true, attributeOldvalue:true, subtree: bubbles });
Caso contrário, você não verá os oldValues ??(você vai ter nulo em vez.) Isto foi testado no Chrome 34.0.1847.131 (Official Desenvolver 265.687) m.