|
| 1 | +/** |
| 2 | + * @param {Set<HTMLElement>} elems |
| 3 | + */ |
| 4 | +function handleElementsTeleport(elems) { |
| 5 | + const teleportTargets = new Map(); |
| 6 | + for (const elem of elems) { |
| 7 | + const teleportTo = elem.dataset.atk4TeleportTo; |
| 8 | + if (!teleportTo) { |
| 9 | + continue; |
| 10 | + } |
| 11 | + |
| 12 | + if (!teleportTargets.has(teleportTo)) { |
| 13 | + const targets = window.document.querySelectorAll(teleportTo); |
| 14 | + if (targets.length !== 1) { |
| 15 | + throw new Error('Target DOM element not found'); |
| 16 | + } |
| 17 | + |
| 18 | + teleportTargets.set(teleportTo, targets[0]); |
| 19 | + } |
| 20 | + |
| 21 | + const target = teleportTargets.get(teleportTo); |
| 22 | + if (elem.parentElement === target) { |
| 23 | + continue; |
| 24 | + } |
| 25 | + |
| 26 | + const elemId = elem.id; |
| 27 | + if (!elemId) { |
| 28 | + throw new Error('DOM element ID is required'); |
| 29 | + } |
| 30 | + |
| 31 | + for (const elemOrig of target.querySelectorAll(':scope > *[id="' + CSS.escape(elemId) + '"]')) { |
| 32 | + elemOrig.remove(); |
| 33 | + } |
| 34 | + |
| 35 | + target.append(elem); |
| 36 | + } |
| 37 | +} |
| 38 | + |
1 | 39 | function handleObserverRecords(mutationRecords) {
|
| 40 | + const elems = new Set(); |
| 41 | + for (const mutationRecord of mutationRecords) { |
| 42 | + for (const addedNode of mutationRecord.addedNodes) { |
| 43 | + if (addedNode instanceof Element) { |
| 44 | + if (addedNode.matches('*[data-atk4-teleport-to]')) { |
| 45 | + elems.add(addedNode); |
| 46 | + } |
| 47 | + for (const elem of addedNode.querySelectorAll('*[data-atk4-teleport-to]')) { |
| 48 | + elems.add(elem); |
| 49 | + } |
| 50 | + } |
| 51 | + } |
| 52 | + if (mutationRecord.type === 'attributes') { |
| 53 | + elems.add(mutationRecord.target); |
| 54 | + } |
| 55 | + } |
| 56 | + |
| 57 | + handleElementsTeleport(elems); |
2 | 58 | }
|
3 | 59 |
|
4 | 60 | const observer = new MutationObserver((mutationRecords) => handleObserverRecords(mutationRecords));
|
| 61 | +observer.observe(window.document, { subtree: true, childList: true, attributeFilter: ['data-atk4-teleport-to'] }); |
| 62 | + |
| 63 | +handleElementsTeleport(new Set(window.document.querySelectorAll('*[data-atk4-teleport-to]'))); |
5 | 64 |
|
6 | 65 | export default {
|
7 | 66 | handleMutationQueueImmediately: function () { // TODO remove this method once evalJsCode() in apiService is called at least thru JS microtask
|
|
0 commit comments