Eu tenho alguns códigos que dependem de offsetParent de um HTMLElement, especificamente dentro de um ouvinte de evento. Código que tenho aqui:
window.addEventListener('mousemove', function(e) {
const control = e.target.offsetParent;
if (!control) {
return;
}
const factor = this.state.duration / control.offsetWidth;
const time = e.pageX * factor;
actions.setCurrentTime(time);
});
No entanto, quando eu testo isso com jest (e, portanto, JSDOM), não consigo fazer com que offsetParent
seja definido de forma alguma.
Este é um atributo sem suporte de um HTMLElement?
Veja # 1013, é basicamente o mesmo problema. Provavelmente não seremos capazes de fazer isso.
Poderia ser corrigido ad hoc? Algo como HTMLElement.prototype.offsetParent = document.createElement('div')
Eu testei isso e não pareceu afetar o e.target
Alguma ideia de como eu poderia fazer algo assim?
Isso pode funcionar, quando você vai fazer isso? O melhor lugar para colocar o código de correção é o retorno de chamada created
em jsdom.env
, já que ele será executado antes que o documento seja realmente carregado.
Então, como eu disse. Estou usando isso no Jest. Portanto, ele lida com jsdom.env
nos bastidores. Estou efetivamente fazendo isso em tempo de execução:
//patch
HTMLElement.prorotype.offsetParent = div;
// handle event
window.addEventListener('mousemove', function event(e) {
console.log(e.target.offsetParent); // undefined
});
// dispatchEvent
window.dispatchEvent(windowEvent)
Eu sei que isso é antigo, mas se alguém descobrir isso e tiver problemas, resolvi fazer algo semelhante ao acima:
Object.defineProperty(HTMLElement.prototype, 'offsetParent', {
get() { return this.parentNode; },
});
@panganibanpj Obrigado pelo código cortado. Eu o aprimorei com algumas das especificações do
Object.defineProperty(HTMLElement.prototype, 'offsetParent', {
get() {
let element = this;
while (!isNullOrUndefined(element) &&
(isNullOrUndefined(element.style) ||
isNullOrUndefined(element.style.display) ||
element.style.display.toLowerCase() !== 'none')) {
element = element.parentNode;
}
if (!isNullOrUndefined(element)) {
return null;
}
if (!isNullOrUndefined(this.style) && !isNullOrUndefined(this.style.position) && this.style.position.toLowerCase() === 'fixed') {
return null;
}
if (this.tagName.toLowerCase() === 'html' || this.tagName.toLowerCase() === 'body') {
return null;
}
return this.parentNode;
},
});
Comentários muito úteis
Eu sei que isso é antigo, mas se alguém descobrir isso e tiver problemas, resolvi fazer algo semelhante ao acima: