Skip to content

Commit 0c9c446

Browse files
committed
Rework previous changes, use shadowRoot instead
1 parent 2fad234 commit 0c9c446

File tree

1 file changed

+34
-61
lines changed

1 file changed

+34
-61
lines changed

webroot/js/inject-iframe.js

Lines changed: 34 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -7,45 +7,43 @@ if (elem) {
77

88
((win, doc) => {
99
let iframe;
10-
let bodyOverflow;
10+
let shadowHost;
11+
let shadowRoot;
1112

1213
const onMessage = (event) => {
14+
if (!iframe) return;
1315
if (event.data === 'collapse') {
1416
iframe.height = 40;
1517
iframe.width = 40;
16-
doc.body.style.overflow = bodyOverflow;
1718
return;
1819
}
1920
if (event.data === 'toolbar') {
2021
iframe.height = 40;
2122
iframe.width = '100%';
22-
doc.body.style.overflow = bodyOverflow;
2323
return;
2424
}
2525
if (event.data === 'expand') {
2626
iframe.width = '100%';
2727
iframe.height = '100%';
28-
doc.body.style.overflow = 'hidden';
2928
}
3029
if (event.data === 'error') {
3130
iframe.width = '40%';
3231
iframe.height = '40%';
33-
doc.body.style.overflow = bodyOverflow;
3432
}
3533
};
3634

37-
let observer;
38-
3935
function injectDebugKitIframe() {
4036
if (!win.debugKitId) {
4137
return;
4238
}
43-
44-
const { body } = doc;
45-
46-
// Remove the old iframe if it exists (in case of ajax swaps).
47-
if (iframe && iframe.parentNode) {
48-
iframe.parentNode.removeChild(iframe);
39+
if (!shadowHost) {
40+
shadowHost = doc.getElementById('debugkit-shadow-host');
41+
if (!shadowHost) {
42+
shadowHost = doc.createElement('div');
43+
shadowHost.id = 'debugkit-shadow-host';
44+
doc.documentElement.appendChild(shadowHost);
45+
}
46+
shadowRoot = shadowHost.shadowRoot || shadowHost.attachShadow({ mode: 'open' });
4947
}
5048

5149
iframe = doc.createElement('iframe');
@@ -59,33 +57,17 @@ if (elem) {
5957
iframe.height = 40;
6058
iframe.width = 40;
6159
iframe.src = `${window.debugKitBaseUrl}debug-kit/toolbar/${window.debugKitId}`;
62-
63-
body.appendChild(iframe);
64-
bodyOverflow = body.style.overflow;
65-
60+
shadowRoot.appendChild(iframe);
6661
if (!win.debugKitMessageListenerApplied) {
6762
window.addEventListener('message', onMessage, false);
6863
win.debugKitMessageListenerApplied = true;
6964
}
7065
}
7166

72-
const onReady = () => {
73-
injectDebugKitIframe();
74-
if (!observer) {
75-
observer = new MutationObserver(() => {
76-
if (!doc.body.querySelector('iframe[src*="debug-kit/toolbar/"]')) {
77-
injectDebugKitIframe();
78-
}
79-
});
80-
if (doc.body) {
81-
observer.observe(doc.body, { childList: true });
82-
}
83-
}
84-
};
85-
8667
const logAjaxRequest = (original) => function ajaxRequest() {
8768
if (this.readyState === 4 && this.getResponseHeader('X-DEBUGKIT-ID')) {
8869
const newId = this.getResponseHeader('X-DEBUGKIT-ID');
70+
8971
window.debugKitId = newId;
9072
const params = {
9173
requestId: newId,
@@ -98,8 +80,9 @@ if (elem) {
9880

9981
if (iframe && iframe.contentWindow) {
10082
iframe.contentWindow.postMessage(`ajax-completed$$${JSON.stringify(params)}`, window.location.origin);
101-
} else {
102-
console.warn('DebugKit: Unable to send ajax completion message - iframe not available');
83+
}
84+
else {
85+
console.warn('DebugKit iframe not found.');
10386
}
10487
}
10588
if (original) {
@@ -109,51 +92,41 @@ if (elem) {
10992
};
11093

11194
const proxyAjaxOpen = () => {
112-
if (window.XMLHttpRequest.prototype._debugKitOpenProxied) {
113-
return;
114-
}
11595
const proxied = window.XMLHttpRequest.prototype.open;
11696
window.XMLHttpRequest.prototype.open = function ajaxCall(...args) {
11797
this._arguments = args;
11898
return proxied.apply(this, [].slice.call(args));
11999
};
120-
window.XMLHttpRequest.prototype._debugKitOpenProxied = true;
121100
};
122101

123102
const proxyAjaxSend = () => {
124-
if (window.XMLHttpRequest.prototype._debugKitSendProxied) {
125-
return;
126-
}
127103
const proxied = window.XMLHttpRequest.prototype.send;
128104
window.XMLHttpRequest.prototype.send = function ajaxCall(...args) {
129105
this.onreadystatechange = logAjaxRequest(this.onreadystatechange);
130106
return proxied.apply(this, [].slice.call(args));
131107
};
132-
window.XMLHttpRequest.prototype._debugKitSendProxied = true;
133108
};
134109

135-
// Bind on ready callbacks to DOMContentLoaded (native js)
136-
// Since the body is already loaded (DOMContentLoaded), the event is not triggered.
137-
if (doc.addEventListener) {
138-
// This ensures that all event listeners get applied only once.
139-
if (!win.debugKitListenersApplied) {
140-
if (!win.debugKitAjaxProxied) {
141-
doc.addEventListener('DOMContentLoaded', proxyAjaxOpen, false);
142-
doc.addEventListener('DOMContentLoaded', proxyAjaxSend, false);
143-
if (doc.readyState === 'interactive' || doc.readyState === 'complete') {
144-
proxyAjaxOpen();
145-
proxyAjaxSend();
146-
}
147-
win.debugKitAjaxProxied = true;
148-
}
149-
doc.addEventListener('DOMContentLoaded', onReady, false);
150-
if (doc.readyState === 'interactive' || doc.readyState === 'complete') {
151-
onReady();
152-
}
153-
win.debugKitListenersApplied = true;
110+
// Improved: Setup listeners and proxies only once, using closure variables
111+
let listenersSetup = false;
112+
function setupDebugKitListeners() {
113+
if (listenersSetup) return;
114+
// Set up AJAX proxying
115+
proxyAjaxOpen();
116+
proxyAjaxSend();
117+
// Set up ready handler
118+
if (doc.readyState === 'loading') {
119+
doc.addEventListener('DOMContentLoaded', injectDebugKitIframe, false);
120+
} else {
121+
injectDebugKitIframe();
154122
}
123+
listenersSetup = true;
124+
}
125+
126+
if (doc.addEventListener) {
127+
setupDebugKitListeners();
155128
} else {
156129
throw new Error('Unable to add event listener for DebugKit. Please use a browser'
157-
+ ' that supports addEventListener().');
130+
+ ' that supports addEventListener().');
158131
}
159132
})(window, document);

0 commit comments

Comments
 (0)