I'm using Polymer's ShadowDOM and MutationObserver
polyfills and need to:
HTMLCanvasElement
is inserted so that I can perform layout (its width and height are undetermined through offsetWidth
/ offsetHeight
when detached from the DOM tree)requestAnimationFrame
loopTraditionally, without Shadow DOM, this works as follows:
MutationObserver
to document.body
and perform querySelectorAll
for any canvas elementslayoutNode
on these elementsdocument.body.contains(node)
returns false
, then the node has been removed from the DOMWhen using Shadow DOM I can get around the shadow dom boundaries by performing (what seems to be very inefficient) scans across all elements in the DOM that have roots which have been added, and performing layoutNode
on any shadow dom nodes inheriting from HTMLCanvasElement
.
How do I check from the animation loop of the canvas that this node is still in the DOM tree?
Is there a better API to use for detecting when a DOM node has been inserted?
(NB. MutationEvents are unavailable using Polymer's CustomElements polyfill.)
First, define the callback function that will execute when the DOM changes: Second, create a MutationObserver object and pass the callback into the MutationObserver () constructor: Third, call the observe () method to start observing the DOM changes. The observe () method has two parameters.
The MutationObserver API allows you to monitor for changes being made to the DOM tree. When the DOM nodes change, you can invoke a callback function to react to the changes. First, define the callback function that will execute when the DOM changes:
Mutation observer. MutationObserver is a built-in object that observes a DOM element and fires a callback in case of changes. We’ll first take a look at the syntax, and then explore a real-world use case, to see where such thing may be useful.
The answer here is that MutationObserver works asynchronously. For example, if you change three items in the DOM at the same time — the subscriber will be called only once, but with three mutations, and each will represent each change you made.
I can use the following function attached to a Node to check whether the node is eventually rooted (through multiple shadow dom boundaries) at a given document, or the current document if no document is specified. This should be as efficient as a JS-based root.contains(node)
call.
Object.defineProperty(Node.prototype, 'isAttachedToDocument', {
configurable: true,
enumerable: false,
writable: true,
value: function(document) {
document = document || window.document;
var el = this;
while(el.parentNode || el.host) el = el.parentNode || el.host;
return (el.impl || el) === document;
}
});
Maybe you could also use one of these:
ResizeObserver
The ResizeObserver interface reports changes to the dimensions of an Element's content or border box, or the bounding box of an SVGElement.
When the contents of a Shadow DOM changes, the MutationObserver
is not notified, because it doesn't see any change in it's own DOM. But the change in the Shadow DOM might have an effect on the size of the Shadow DOM containing element. This size change can be observed with the ResizeObserver
.
This one could also be worth looking at:
Intersection Observer API
The Intersection Observer API provides a way to asynchronously observe changes in the intersection of a target element with an ancestor element or with a top-level document's viewport.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With