diff --git a/src/BookReader.js b/src/BookReader.js index a7e6dea1b..b4f5250aa 100644 --- a/src/BookReader.js +++ b/src/BookReader.js @@ -788,6 +788,24 @@ BookReader.prototype.unbind = function(name, callback) { return this.off(name, callback); }; +/** + * Resolves `this.el` to a DOM Element, whether it was provided as an + * Element reference or a CSS selector string. + * + * This is needed because some consumers (e.g. apps using shadow DOM) + * must pass a DOM element directly — `document.querySelector` cannot + * cross shadow boundaries. jQuery's `$()` already handles both forms, + * but code that calls `document.querySelector(br.el)` will fail when + * `el` is an Element or when the target is inside a shadow root. + * + * @returns {Element|null} + */ +BookReader.prototype.resolveEl = function() { + if (this.el instanceof Element) return this.el; + if (typeof this.el === 'string') return document.querySelector(this.el); + return null; +}; + /** * Resizes based on the container width and height */ diff --git a/src/ia-bookreader/ia-bookreader.js b/src/ia-bookreader/ia-bookreader.js index 728645ea5..4937775cd 100644 --- a/src/ia-bookreader/ia-bookreader.js +++ b/src/ia-bookreader/ia-bookreader.js @@ -337,7 +337,7 @@ export class IaBookReader extends LitElement { /** gets element that houses the bookreader in light dom */ get mainBRContainer() { - return document.querySelector(this.bookreader?.el); + return this.bookreader?.resolveEl?.() ?? document.querySelector(this.bookreader?.el); } get baseProviderConfig() { diff --git a/src/plugins/search/view.js b/src/plugins/search/view.js index fdf3be7a5..50df2e184 100644 --- a/src/plugins/search/view.js +++ b/src/plugins/search/view.js @@ -331,7 +331,8 @@ class SearchView { const modal = document.createElement('div'); modal.classList.add('BRprogresspopup', 'search_modal'); modal.innerHTML = messageHTML; - document.querySelector(this.br.el).append(modal); + const container = this.br.resolveEl?.() ?? document.querySelector(this.br.el); + container?.append(modal); } /**