From 166a3a1b88335350b8ed69f756d4c6d3a7faeda9 Mon Sep 17 00:00:00 2001 From: Ferdinand Kuhl Date: Sun, 26 May 2024 21:08:01 +0200 Subject: [PATCH] first release --- package.json | 18 ++++++++++++++++ src/nowAndLater.js | 52 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 package.json create mode 100644 src/nowAndLater.js diff --git a/package.json b/package.json new file mode 100644 index 0000000..dc5095b --- /dev/null +++ b/package.json @@ -0,0 +1,18 @@ +{ + "name": "@digicomp/now-and-later", + "version": "1.0.0", + "description": "an easy API for DOM MutationObserver", + "main": "src/nowAndLater.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git@digital-competence.de:npm/now-and-later.git" + }, + "keywords": [ + "MutationObserver" + ], + "author": "Ferdinand Kuhl", + "license": "MIT" +} diff --git a/src/nowAndLater.js b/src/nowAndLater.js new file mode 100644 index 0000000..580ea6f --- /dev/null +++ b/src/nowAndLater.js @@ -0,0 +1,52 @@ +const lateInits = []; + +/** + * @callback NowAndLaterCallback + * @param {HTMLElement} element + * @param {string|undefined} selector + * @return void + */ + +/** + * @param {string} selector + * @param {NowAndLaterCallback} callback + */ +export default function nowAndLater(selector, callback) +{ + const nodes = document.querySelectorAll(selector); + const id = Date.now() + '_' + lateInits.length; + const wrappedCallback = (node) => { + node.dataset['nowAndLater' + id] = ''; + callback(node, selector); + }; + if (nodes.length > 0) { + [...nodes].forEach(node => { + wrappedCallback(node); + }); + } + lateInits.push({selector: selector, callback: wrappedCallback, id: id}); +} + +const observer = new MutationObserver(function (mutationsList) +{ + for (const mutation of mutationsList) { + for (const addedNode of mutation.addedNodes) { + for (const lateInit of lateInits) { + if (addedNode['querySelector'] === undefined) { // lets filter out text and comment nodes + continue; + } + const selector = lateInit.selector + ':not([data-now-and-later' + lateInit.id + '])'; + // If the added node matches itself, it will not be found by querySelectorAll, so we have to check first + if (addedNode.matches(selector)) { + lateInit.callback(addedNode); + } + // NOTE: the added not selector prevents double calls + const nodes = addedNode.querySelectorAll(selector); + if (nodes.length > 0) { + [...nodes].forEach(node => lateInit.callback(node)); + } + } + } + } +}); +observer.observe(document.documentElement, {childList: true, subtree: true});