Skip to content

Commit ccdc3a8

Browse files
Improve flexibility for relative positioning
1 parent 7ea1b8a commit ccdc3a8

File tree

1 file changed

+23
-14
lines changed

1 file changed

+23
-14
lines changed

highlight-helper.js

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ function Highlighter(options = hhDefaultOptions) {
88
options[key] = options[key] ?? hhDefaultOptions[key];
99
}
1010

11-
this.annotatableContainer, this.annotatableParagraphs;
11+
this.annotatableContainer, this.relativeAncestorElement, this.annotatableParagraphs;
1212
let generalStylesheet, appearanceStylesheet, highlightApiStylesheet, selectionStylesheet;
1313
let annotatableParagraphIds, hyperlinkElements;
1414
let svgBackground, svgActiveOverlay, selectionHandles;
@@ -33,6 +33,16 @@ function Highlighter(options = hhDefaultOptions) {
3333
return false;
3434
}
3535

36+
// Get the closest ancestor element with `position: relative`, or the root element (this is used to calculate the position of selection handles and SVG highlights)
37+
let ancestorElement = this.annotatableContainer;
38+
while (ancestorElement) {
39+
if (ancestorElement === document.documentElement || window.getComputedStyle(ancestorElement).position === 'relative') {
40+
this.relativeAncestorElement = ancestorElement;
41+
break;
42+
}
43+
ancestorElement = ancestorElement.parentElement;
44+
}
45+
3646
// Abort controller can be used to cancel event listeners if the highlighter is removed
3747
controller = new AbortController;
3848

@@ -50,7 +60,6 @@ function Highlighter(options = hhDefaultOptions) {
5060
document.adoptedStyleSheets.push(selectionStylesheet);
5161
generalStylesheet.replaceSync(`
5262
${options.containerSelector} {
53-
position: relative;
5463
-webkit-tap-highlight-color: transparent;
5564
}
5665
.hh-wrapper-start, .hh-wrapper-end, .hh-selection-handle {
@@ -860,7 +869,7 @@ function Highlighter(options = hhDefaultOptions) {
860869
const selectionRangeRects = selectionRange.getClientRects();
861870
const startRect = selectionRangeRects[0];
862871
const endRect = selectionRangeRects[selectionRangeRects.length-1];
863-
const annotatableContainerClientRect = this.annotatableContainer.getBoundingClientRect();
872+
const relativeAncestorClientRect = this.relativeAncestorElement.getBoundingClientRect();
864873
const startNodeIsRtl = window.getComputedStyle(selectionRange.startContainer.parentElement).direction === 'rtl';
865874
const endNodeIsRtl = window.getComputedStyle(selectionRange.endContainer.parentElement).direction === 'rtl';
866875

@@ -869,14 +878,14 @@ function Highlighter(options = hhDefaultOptions) {
869878
let side;
870879
if (selectionHandle.dataset.position === 'start') {
871880
side = startNodeIsRtl ? 'right' : 'left';
872-
selectionHandle.style.left = startRect[side] - annotatableContainerClientRect.left + 'px';
881+
selectionHandle.style.left = startRect[side] - relativeAncestorClientRect.left + 'px';
873882
selectionHandle.style.height = startRect.height + 'px';
874-
selectionHandle.style.top = startRect.top - annotatableContainerClientRect.top + 'px';
883+
selectionHandle.style.top = startRect.top - relativeAncestorClientRect.top + 'px';
875884
} else {
876885
side = endNodeIsRtl ? 'left' : 'right';
877-
selectionHandle.style.left = endRect[side] - annotatableContainerClientRect.left + 'px';
886+
selectionHandle.style.left = endRect[side] - relativeAncestorClientRect.left + 'px';
878887
selectionHandle.style.height = endRect.height + 'px';
879-
selectionHandle.style.top = endRect.top - annotatableContainerClientRect.top + 'px';
888+
selectionHandle.style.top = endRect.top - relativeAncestorClientRect.top + 'px';
880889
}
881890
if (selectionHandle.dataset.side !== side) {
882891
selectionHandle.dataset.side = side;
@@ -1031,16 +1040,16 @@ function Highlighter(options = hhDefaultOptions) {
10311040
return;
10321041
}
10331042
if (type === 'svg' && clientRect) {
1034-
const annotatableContainerClientRect = this.annotatableContainer.getBoundingClientRect();
1043+
const relativeAncestorClientRect = this.relativeAncestorElement.getBoundingClientRect();
10351044
styleTemplate = styleTemplate
1036-
.replaceAll('{x}', clientRect.x - annotatableContainerClientRect.x)
1037-
.replaceAll('{y}', clientRect.y - annotatableContainerClientRect.y)
1045+
.replaceAll('{x}', clientRect.x - relativeAncestorClientRect.x)
1046+
.replaceAll('{y}', clientRect.y - relativeAncestorClientRect.y)
10381047
.replaceAll('{width}', clientRect.width)
10391048
.replaceAll('{height}', clientRect.height)
1040-
.replaceAll('{top}', clientRect.top - annotatableContainerClientRect.top)
1041-
.replaceAll('{right}', clientRect.right - annotatableContainerClientRect.right)
1042-
.replaceAll('{bottom}', clientRect.bottom - annotatableContainerClientRect.bottom)
1043-
.replaceAll('{left}', clientRect.left - annotatableContainerClientRect.left);
1049+
.replaceAll('{top}', clientRect.top - relativeAncestorClientRect.top)
1050+
.replaceAll('{right}', clientRect.right - relativeAncestorClientRect.right)
1051+
.replaceAll('{bottom}', clientRect.bottom - relativeAncestorClientRect.bottom)
1052+
.replaceAll('{left}', clientRect.left - relativeAncestorClientRect.left);
10441053
}
10451054
return styleTemplate;
10461055
}

0 commit comments

Comments
 (0)