Skip to content

Commit 39992e5

Browse files
First visible locator (EPUBS) improvements (#99)
1 parent eb61441 commit 39992e5

File tree

4 files changed

+34
-7
lines changed

4 files changed

+34
-7
lines changed

navigator-html-injectables/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
"devDependencies": {
5151
"@juggle/resize-observer": "^3.4.0",
5252
"@readium/shared": "workspace:*",
53-
"css-selector-generator": "^3.6.4",
53+
"css-selector-generator": "^3.6.9",
5454
"tslib": "^2.6.1",
5555
"typescript": "^5.4.5",
5656
"vite": "^4.5.5"

navigator-html-injectables/src/helpers/dom.ts

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,19 @@ export function nearestInteractiveElement(element: Element): Element | null {
6868
/// Returns the `Locator` object to the first block element that is visible on
6969
/// the screen.
7070
export function findFirstVisibleLocator(wnd: ReadiumWindow, scrolling: boolean) {
71-
const element = findElement(wnd, wnd.document.body, scrolling);
71+
const element = findElement(wnd, wnd.document.body, scrolling) as HTMLElement;
72+
73+
// Use only the allowed selectors to generate the cssSelector and avoid a crash
74+
const cssSelector = wnd._readium_cssSelectorGenerator.getCssSelector(element, {
75+
selectors: ["tag", "id", "class", "nthchild", "nthoftype", "attribute"]
76+
});
77+
7278
return new Locator({
7379
href: "#",
7480
type: "application/xhtml+xml",
7581
locations: new LocatorLocations({
7682
otherLocations: new Map([
77-
["cssSelector", wnd._readium_cssSelectorGenerator.getCssSelector(element)]
83+
["cssSelector", cssSelector]
7884
])
7985
}),
8086
text: new LocatorText({
@@ -87,6 +93,9 @@ function findElement(wnd: ReadiumWindow, rootElement: Element, scrolling: boolea
8793
for (var i = 0; i < rootElement.children.length; i++) {
8894
const child = rootElement.children[i];
8995
if (!shouldIgnoreElement(child) && isElementVisible(wnd, child, scrolling)) {
96+
// Once we get a fully visible element, return it
97+
if (isElementFullyVisible(wnd, child)) return child;
98+
// if the parent is not fully visible, search in the childs
9099
return findElement(wnd, child, scrolling);
91100
}
92101
}
@@ -111,11 +120,29 @@ function isElementVisible(wnd: ReadiumWindow, element: Element, scrolling: boole
111120
}
112121
}
113122

123+
/**
124+
* Check if an element is fully visible in the current viewport.
125+
* @param wnd Window instance to operate on
126+
* @param element Element to check visibility of
127+
* @returns True if the element is fully visible, false otherwise
128+
*/
129+
function isElementFullyVisible(wnd: ReadiumWindow, element: Element): boolean {
130+
const rect = element.getBoundingClientRect();
131+
const isFullyVisible =
132+
rect.top >= 0 &&
133+
rect.left >= 0 &&
134+
rect.bottom <= wnd.innerHeight &&
135+
rect.right <= wnd.innerWidth;
136+
return isFullyVisible;
137+
}
138+
114139
function shouldIgnoreElement(element: Element) {
115140
const elStyle = getComputedStyle(element);
116141
if (elStyle) {
117142
const display = elStyle.getPropertyValue("display");
118-
if (display != "block") {
143+
// Added list-item as it is a common display property for list items
144+
// TODO: Check if there are other display properties that should be ignored/considered
145+
if (display != "block" && display != "list-item") {
119146
return true;
120147
}
121148
// Cannot be relied upon, because web browser engine reports invisible when out of view in

navigator-html-injectables/src/modules/Peripherals.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export class Peripherals extends Module {
7171
targetFrameSrc: this.wnd.location.href,
7272
targetElement: (event.target as Element).outerHTML,
7373
interactiveElement: nearestInteractiveElement(event.target as Element)?.outerHTML,
74-
cssSelector: this.wnd._readium_cssSelectorGenerator.getCssSelector(event.target),
74+
cssSelector: this.wnd._readium_cssSelectorGenerator.getCssSelector(event.target as Element),
7575
} as FrameClickEvent);
7676

7777
this.pointerMoved = false;

pnpm-lock.yaml

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)