Skip to content

Commit eb45359

Browse files
devvaannshabose
authored andcommitted
feat: move element highlighting inside shadow dom
1 parent c0d3a43 commit eb45359

2 files changed

Lines changed: 88 additions & 39 deletions

File tree

src/LiveDevelopment/BrowserScripts/RemoteFunctions.js

Lines changed: 68 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,47 @@ function RemoteFunctions(config = {}) {
263263
return element.offsetTop + (element.offsetParent ? getDocumentOffsetTop(element.offsetParent) : 0);
264264
}
265265

266+
// Shadow DOM host for highlight overlays — isolates our UI from user page CSS.
267+
let _highlightShadowHost = null;
268+
let _highlightShadowRoot = null;
269+
270+
const HIGHLIGHT_CSS = `:host {
271+
all: initial !important;
272+
}
273+
274+
.overlay-container {
275+
position: absolute !important;
276+
z-index: 2147483645 !important;
277+
margin: 0 !important;
278+
padding: 0 !important;
279+
border: none !important;
280+
pointer-events: none !important;
281+
box-sizing: border-box !important;
282+
}
283+
284+
.rect {
285+
position: absolute !important;
286+
}
287+
288+
.outline {
289+
position: absolute !important;
290+
box-sizing: border-box !important;
291+
pointer-events: none !important;
292+
}`;
293+
294+
function _ensureHighlightShadowRoot() {
295+
if (_highlightShadowRoot) {
296+
return _highlightShadowRoot;
297+
}
298+
_highlightShadowHost = window.document.createElement("div");
299+
_highlightShadowHost.className = GLOBALS.HIGHLIGHT_CLASSNAME;
300+
_highlightShadowHost.setAttribute(GLOBALS.PHCODE_INTERNAL_ATTR, "true");
301+
_highlightShadowRoot = _highlightShadowHost.attachShadow({ mode: "open" });
302+
_highlightShadowRoot.innerHTML = `<style>${HIGHLIGHT_CSS}</style>`;
303+
window.document.body.appendChild(_highlightShadowHost);
304+
return _highlightShadowRoot;
305+
}
306+
266307
function Highlight(trigger) {
267308
this.trigger = !!trigger;
268309
this.elements = [];
@@ -358,27 +399,18 @@ function RemoteFunctions(config = {}) {
358399

359400
// Container div — sized to the margin box so all rects fit inside it
360401
const div = window.document.createElement("div");
361-
div.className = GLOBALS.HIGHLIGHT_CLASSNAME;
362-
div.setAttribute(GLOBALS.PHCODE_INTERNAL_ATTR, "true");
402+
div.className = "overlay-container";
363403
div.trackingElement = element;
364-
const divStyle = div.style;
365-
divStyle.position = "absolute";
366-
divStyle.left = marginBox.left + "px";
367-
divStyle.top = marginBox.top + "px";
368-
divStyle.width = marginBox.width + "px";
369-
divStyle.height = marginBox.height + "px";
370-
divStyle.zIndex = 2147483645;
371-
divStyle.margin = "0";
372-
divStyle.padding = "0";
373-
divStyle.border = "none";
374-
divStyle.pointerEvents = "none";
375-
divStyle.boxSizing = "border-box";
404+
div.style.left = marginBox.left + "px";
405+
div.style.top = marginBox.top + "px";
406+
div.style.width = marginBox.width + "px";
407+
div.style.height = marginBox.height + "px";
376408

377409
// Helper to create a colored rect at absolute page coordinates, offset by the container origin
378410
function makeRect(left, top, width, height, color) {
379411
if (width <= 0 || height <= 0) { return; }
380412
const r = window.document.createElement("div");
381-
r.style.position = "absolute";
413+
r.className = "rect";
382414
r.style.left = (left - marginBox.left) + "px";
383415
r.style.top = (top - marginBox.top) + "px";
384416
r.style.width = width + "px";
@@ -421,17 +453,15 @@ function RemoteFunctions(config = {}) {
421453
const isEditable = element.hasAttribute(GLOBALS.DATA_BRACKETS_ID_ATTR);
422454
const outlineColor = isEditable ? COLORS.outlineEditable : COLORS.outlineNonEditable;
423455
const outlineDiv = window.document.createElement("div");
424-
outlineDiv.style.position = "absolute";
456+
outlineDiv.className = "outline";
425457
outlineDiv.style.left = (borderBox.left - marginBox.left) + "px";
426458
outlineDiv.style.top = (borderBox.top - marginBox.top) + "px";
427459
outlineDiv.style.width = borderBox.width + "px";
428460
outlineDiv.style.height = borderBox.height + "px";
429461
outlineDiv.style.border = `1px solid ${outlineColor}`;
430-
outlineDiv.style.boxSizing = "border-box";
431-
outlineDiv.style.pointerEvents = "none";
432462
div.appendChild(outlineDiv);
433463

434-
window.document.body.appendChild(div);
464+
_ensureHighlightShadowRoot().appendChild(div);
435465
this._divs.push(div);
436466
}
437467
};
@@ -1464,6 +1494,25 @@ function RemoteFunctions(config = {}) {
14641494
"getMode": function() { return config.mode; },
14651495
"isSyncEnabled": function() { return config.syncSourceAndPreview !== false; },
14661496
"suppressDOMEditDismissal": suppressDOMEditDismissal,
1497+
"getHighlightCount": function() {
1498+
if (!_highlightShadowRoot) { return 0; }
1499+
return _highlightShadowRoot.querySelectorAll('.overlay-container').length;
1500+
},
1501+
"getHighlightTrackingElement": function(index) {
1502+
if (!_highlightShadowRoot) { return null; }
1503+
const overlay = _highlightShadowRoot.querySelectorAll('.overlay-container')[index];
1504+
if (!overlay || !overlay.trackingElement) { return null; }
1505+
const el = overlay.trackingElement;
1506+
return {
1507+
id: el.id,
1508+
classList: Array.from(el.classList)
1509+
};
1510+
},
1511+
"getHighlightStyle": function(index, property) {
1512+
if (!_highlightShadowRoot) { return null; }
1513+
const overlay = _highlightShadowRoot.querySelectorAll('.overlay-container')[index];
1514+
return overlay ? overlay.style[property] : null;
1515+
},
14671516
"setHotCornerHidden": function(hidden) {
14681517
if (SHARED_STATE._hotCorner && SHARED_STATE._hotCorner.hotCorner) {
14691518
if (hidden) {

test/spec/LiveDevelopmentMultiBrowser-test.js

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,16 +1319,16 @@ define(function (require, exports, module) {
13191319
await waitsForLiveDevelopmentToOpen();
13201320
let editor = EditorManager.getActiveEditor();
13211321
editor.setCursorPos({ line: 0, ch: 0 });
1322-
await forRemoteExec(`document.getElementsByClassName("__brackets-ld-highlight").length`, (result) => {
1322+
await forRemoteExec(`_LD.getHighlightCount()`, (result) => {
13231323
return result === 0;
13241324
});
13251325

13261326
editor.setCursorPos({ line: 11, ch: 10 });
13271327

1328-
await forRemoteExec(`document.getElementsByClassName("__brackets-ld-highlight").length`, (result) => {
1328+
await forRemoteExec(`_LD.getHighlightCount()`, (result) => {
13291329
return result === 1;
13301330
});
1331-
await forRemoteExec(`document.getElementsByClassName("__brackets-ld-highlight")[0].trackingElement.id`,
1331+
await forRemoteExec(`_LD.getHighlightTrackingElement(0).id`,
13321332
(result) => {
13331333
return result === 'testId';
13341334
});
@@ -1341,7 +1341,7 @@ define(function (require, exports, module) {
13411341
"SpecRunnerUtils.openProjectFiles simple2.html");
13421342

13431343
await waitsForLiveDevelopmentToOpen();
1344-
await forRemoteExec(`document.getElementsByClassName("__brackets-ld-highlight").length`, (result) => {
1344+
await forRemoteExec(`_LD.getHighlightCount()`, (result) => {
13451345
return result === 0;
13461346
});
13471347

@@ -1351,11 +1351,11 @@ define(function (require, exports, module) {
13511351
editor.setCursorPos({ line: 2, ch: 6 });
13521352

13531353
await awaits(500);
1354-
await forRemoteExec(`document.getElementsByClassName("__brackets-ld-highlight").length`, (result) => {
1354+
await forRemoteExec(`_LD.getHighlightCount()`, (result) => {
13551355
return result === 3;
13561356
});
13571357
await forRemoteExec(
1358-
`document.getElementsByClassName("__brackets-ld-highlight")[0].trackingElement.classList[0]`,
1358+
`_LD.getHighlightTrackingElement(0).classList[0]`,
13591359
(result) => {
13601360
return result === 'testClass';
13611361
});
@@ -1366,11 +1366,11 @@ define(function (require, exports, module) {
13661366
editor.setCursorPos({ line: 0, ch: 1 });
13671367

13681368
await awaits(500);
1369-
await forRemoteExec(`document.getElementsByClassName("__brackets-ld-highlight").length`, (result) => {
1369+
await forRemoteExec(`_LD.getHighlightCount()`, (result) => {
13701370
return result === 2;
13711371
});
13721372
await forRemoteExec(
1373-
`document.getElementsByClassName("__brackets-ld-highlight")[0].trackingElement.classList[0]`,
1373+
`_LD.getHighlightTrackingElement(0).classList[0]`,
13741374
(result) => {
13751375
return result === 'testClass2';
13761376
});
@@ -1385,30 +1385,30 @@ define(function (require, exports, module) {
13851385

13861386
await waitsForLiveDevelopmentToOpen();
13871387
let editor = EditorManager.getActiveEditor();
1388-
await forRemoteExec(`document.getElementsByClassName("__brackets-ld-highlight").length`, (result) => {
1388+
await forRemoteExec(`_LD.getHighlightCount()`, (result) => {
13891389
return result === 0;
13901390
});
13911391

13921392
editor.setCursorPos({ line: 11, ch: 10 });
13931393

13941394
await awaits(500);
1395-
await forRemoteExec(`document.getElementsByClassName("__brackets-ld-highlight").length`, (result) => {
1395+
await forRemoteExec(`_LD.getHighlightCount()`, (result) => {
13961396
return result === 1;
13971397
});
13981398
let originalWidth;
1399-
await forRemoteExec(`document.getElementsByClassName("__brackets-ld-highlight")[0].style.width`, (result) => {
1399+
await forRemoteExec(`_LD.getHighlightStyle(0, 'width')`, (result) => {
14001400
originalWidth = result;
14011401
return true;
14021402
});
14031403

14041404
iFrame.style.width = "100px";
14051405
await awaits(500);
1406-
await forRemoteExec(`document.getElementsByClassName("__brackets-ld-highlight")[0].style.width`, (result) => {
1406+
await forRemoteExec(`_LD.getHighlightStyle(0, 'width')`, (result) => {
14071407
return originalWidth !== result;
14081408
});
14091409
iFrame.style.width = "100%";
14101410
await awaits(500);
1411-
await forRemoteExec(`document.getElementsByClassName("__brackets-ld-highlight")[0].style.width`, (result) => {
1411+
await forRemoteExec(`_LD.getHighlightStyle(0, 'width')`, (result) => {
14121412
return originalWidth === result;
14131413
});
14141414

@@ -1423,16 +1423,16 @@ define(function (require, exports, module) {
14231423
let editor = EditorManager.getActiveEditor();
14241424

14251425
await awaits(500);
1426-
await forRemoteExec(`document.getElementsByClassName("__brackets-ld-highlight").length`, (result) => {
1426+
await forRemoteExec(`_LD.getHighlightCount()`, (result) => {
14271427
return result === 0;
14281428
});
14291429
await forRemoteExec(`document.getElementById("testId2").click()`);
14301430

14311431
await awaits(500);
1432-
await forRemoteExec(`document.getElementsByClassName("__brackets-ld-highlight").length`, (result) => {
1432+
await forRemoteExec(`_LD.getHighlightCount()`, (result) => {
14331433
return result === 1;
14341434
});
1435-
await forRemoteExec(`document.getElementsByClassName("__brackets-ld-highlight")[0].trackingElement.id`,
1435+
await forRemoteExec(`_LD.getHighlightTrackingElement(0).id`,
14361436
(result) => {
14371437
return result === 'testId2';
14381438
});
@@ -1575,7 +1575,7 @@ define(function (require, exports, module) {
15751575
await waitsForLiveDevelopmentToOpen();
15761576

15771577
await awaits(1000);
1578-
await forRemoteExec(`document.getElementsByClassName("__brackets-ld-highlight").length`, (result) => {
1578+
await forRemoteExec(`_LD.getHighlightCount()`, (result) => {
15791579
return result === 0;
15801580
});
15811581

@@ -1593,10 +1593,10 @@ define(function (require, exports, module) {
15931593
await forRemoteExec(`document.getElementById("testId").click()`);
15941594
await awaits(1000);
15951595

1596-
await forRemoteExec(`document.getElementsByClassName("__brackets-ld-highlight").length`, (result) => {
1596+
await forRemoteExec(`_LD.getHighlightCount()`, (result) => {
15971597
return result === 1;
15981598
});
1599-
await forRemoteExec(`document.getElementsByClassName("__brackets-ld-highlight")[0].trackingElement.id`,
1599+
await forRemoteExec(`_LD.getHighlightTrackingElement(0).id`,
16001600
(result) => {
16011601
return result === 'testId';
16021602
});
@@ -1615,7 +1615,7 @@ define(function (require, exports, module) {
16151615
editor && editor.setCursorPos({ line: 0, ch: 0 });
16161616

16171617
await awaits(500);
1618-
await forRemoteExec(`document.getElementsByClassName("__brackets-ld-highlight").length`, (result) => {
1618+
await forRemoteExec(`_LD.getHighlightCount()`, (result) => {
16191619
return result === 0;
16201620
});
16211621
await forRemoteExec(`document.getElementById("testId2").click()`);

0 commit comments

Comments
 (0)