I am developing a JavaScript module, which knows nothing about the environment in which it will be used in.
And, technically speaking, I want to implement the next function:
onceAppended(element, callback);
element is an HTMLElement and the parent of this element may be unknown during the module initialization. callback is a function, which must be triggered once element appears on the page.
Callback must be called immediately if the element is appended to the document. In case element is not appended yet, function will trigger callback once element appears on the document.
The problem is, we can detect element append event with using DOMNodeInserted mutation event. But mutation events are now deprecated. And it seems that MutationObserver can't handle this task, can it?
Here is my code snippet:
function onceAppended (element, callback) {
let el = element,
listener;
while (el.parentNode)
el = el.parentNode;
if (el instanceof Document) {
callback();
return;
}
if (typeof MutationObserver === "undefined") { // use deprecated method
element.addEventListener("DOMNodeInserted", listener = (ev) => {
if (ev.path.length > 1 && ev.path[ev.length - 2] instanceof Document) {
element.removeEventListener("DOMNodeInserted", listener);
callback();
}
}, false);
return;
}
// Can't MutationObserver detect append event for the case?
}
By taking a wOxxOm's hint about the Alternative to DOMNodeInserted, and skyline3000's answer I have developed two methods of this task solution. The first method
onceAppendedis fast, but it has a delay of around 25ms beforecallbackis triggered. The second method triggerscallbackright after the element is inserted, but it may be slow when a lot of elements append in the application.The solution is available on GitHub and as an npm ES6 module. Below are the plain code of the two solutions.
Method 1 (using CSS animations)
Method 2 (using MutationObserver)
Both of this methods has the same usage, which differs only in function names: