Skip to content

Commit 553af76

Browse files
committed
impl
1 parent 1279e4e commit 553af76

10 files changed

+267
-76
lines changed

js/src/Helper/elementRemoveObserver.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,10 @@ function handleObserverRecords(elem, mutationRecords) {
5959

6060
const removedElems = new Set();
6161
for (const mutationRecord of mutationRecords) {
62-
for (const removedElem of observedChildren.intersection(mutationRecord.removedNodes)) {
63-
removedElems.add(removedElem);
62+
for (const removedNode of mutationRecord.removedNodes) {
63+
if (observedChildren.has(removedNode)) {
64+
removedElems.add(removedNode);
65+
}
6466
}
6567
}
6668

js/src/Helper/elementTeleportObserver.js

+59
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,66 @@
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+
139
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);
258
}
359

460
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]')));
564

665
export default {
766
handleMutationQueueImmediately: function () { // TODO remove this method once evalJsCode() in apiService is called at least thru JS microtask

js/src/Service/apiService.js

-6
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,6 @@ class ApiService {
103103
}
104104
responseBody = null;
105105

106-
// prevent modal duplication
107-
const $modalsContainers = $('body > .ui.dimmer.modals.page, body > .atk-side-panels');
108-
$(responseElement).find('.ui.modal[id], .atk-right-panel[id]').each((i, e) => {
109-
$modalsContainers.find('#' + e.id).remove();
110-
});
111-
112106
if ($target.hasClass('ui modal') || $target.hasClass('atk-right-panel')) {
113107
$.each([...$target[0].childNodes], (i, node) => {
114108
if (node instanceof Element && node.classList.contains('ui') && node.classList.contains('dimmer')) {

js/src/Service/modalService.js

-10
Original file line numberDiff line numberDiff line change
@@ -101,16 +101,6 @@ class ModalService {
101101
method: 'GET',
102102
obj: $content,
103103
onComplete: function (response, content) {
104-
// prevent modal duplication
105-
// TODO deduplicate in favor of apiService.js code only
106-
if (response.html) {
107-
const responseBody = new DOMParser().parseFromString('<body>' + response.html.trim() + '</body>', 'text/html').body;
108-
const $modalsContainers = $('body > .ui.dimmer.modals.page, body > .atk-side-panels');
109-
$(responseBody.childNodes[0]).find('.ui.modal[id], .atk-right-panel[id]').each((i, e) => {
110-
$modalsContainers.find('#' + e.id).remove();
111-
});
112-
}
113-
114104
const result = content.html(response.html);
115105
if (result.length === 0) {
116106
// TODO this if should be removed

0 commit comments

Comments
 (0)