diff --git a/packages/app-shell/src/app-shell.js b/packages/app-shell/src/app-shell.js index fb573076a6088adace45958d2cc889cd80651ee0..5dadf1ad9090f3d2e44406fa4653226e0a48e211 100644 --- a/packages/app-shell/src/app-shell.js +++ b/packages/app-shell/src/app-shell.js @@ -2,7 +2,7 @@ import {createInstance} from './i18n.js'; import {html, css} from 'lit'; import {ScopedElementsMixin} from '@open-wc/scoped-elements'; import {LanguageSelect} from '@dbp-toolkit/language-select'; -import {Icon} from '@dbp-toolkit/common'; +import {Icon, getShadowRootDocument} from '@dbp-toolkit/common'; import {AuthKeycloak} from '@dbp-toolkit/auth'; import {AuthMenuButton} from './auth-menu-button.js'; import {Notification} from '@dbp-toolkit/notification'; @@ -829,13 +829,7 @@ export class AppShell extends ScopedElementsMixin(DBPLitElement) { this.defineScopedElement(activity.element, customElements.get(activity.element)); }); - // In case of "Scoped Custom Element Registries" polyfill we create a scoped element - let elm; - if (this.shadowRoot.createElement !== undefined) { - elm = this.shadowRoot.createElement(activity.element); - } else { - elm = document.createElement(activity.element); - } + let elm = getShadowRootDocument(this).createElement(activity.element); this._onActivityAdded(elm); this._lastElm = elm; diff --git a/packages/common/src/utils.js b/packages/common/src/utils.js index a2a2deb3fb70cb4eace08403baeddc1f74430ac5..7d4b7b9b8ebdeac4df140055cbb9db56a6161786 100644 --- a/packages/common/src/utils.js +++ b/packages/common/src/utils.js @@ -15,3 +15,23 @@ export const combineURLs = (baseURL, addedURL) => { } return new URL(addedURL.replace(/^\/+/, ''), baseURL).href; }; + +/** + * Returns a Document like thing that can be used to create elements. + * + * It provides createElement()/createElementNS()/importNode(). + * The Document type annotation, while not correct, is used here for simplicity. + * + * https://github.com/WICG/webcomponents/blob/gh-pages/proposals/Scoped-Custom-Element-Registries.md#scoped-element-creation-apis + * + * @param {HTMLElement} element + * @returns {Document|null} + */ +export function getShadowRootDocument(element) { + // In case the polyfill is loaded return the shadowRoot + // otherwise fall back to the global document + if (ShadowRoot.prototype.createElement !== undefined) { + return element.shadowRoot; + } + return document; +} diff --git a/packages/common/test/unit.js b/packages/common/test/unit.js index 7bf4ac4d4e1926cbb8cf727e25edecafb3712543..64c44c270fcb40817f3dd4be38b3eb3b42b4c1dc 100644 --- a/packages/common/test/unit.js +++ b/packages/common/test/unit.js @@ -1,7 +1,7 @@ import {expect, assert} from '@esm-bundle/chai'; import * as utils from '../utils'; import * as styles from '../styles'; -import {combineURLs} from '../'; +import {combineURLs, getShadowRootDocument} from '../'; import '../jsonld.js'; suite('utils', () => { @@ -34,6 +34,16 @@ suite('utils', () => { assert.isTrue(res); }); + test('getShadowRootDocument', () => { + class SomeElement3 extends HTMLElement {} + let res = utils.defineCustomElement('test-some-element-3', SomeElement3); + assert.isTrue(res); + let elm = new SomeElement3(); + elm.attachShadow({mode: 'open'}); + let doc = getShadowRootDocument(elm); + assert.isFunction(doc.createElement); + }); + test('getAssetURL', () => { // Backwards compat assert.equal(new URL(utils.getAssetURL('foo/bar')).pathname, '/foo/bar'); diff --git a/packages/file-handling/src/nextcloud-file-picker.js b/packages/file-handling/src/nextcloud-file-picker.js index 8736bc44a8219b642a64e1f25a53bdb93bdceb20..13610f683efe021d91686fcd8226e80bc85a644f 100644 --- a/packages/file-handling/src/nextcloud-file-picker.js +++ b/packages/file-handling/src/nextcloud-file-picker.js @@ -2,7 +2,7 @@ import {createInstance} from './i18n'; import {css, html} from 'lit'; import {ScopedElementsMixin} from '@open-wc/scoped-elements'; import DBPLitElement from '@dbp-toolkit/common/dbp-lit-element'; -import {Icon, MiniSpinner} from '@dbp-toolkit/common'; +import {Icon, MiniSpinner, getShadowRootDocument} from '@dbp-toolkit/common'; import * as commonUtils from '@dbp-toolkit/common/utils'; import * as commonStyles from '@dbp-toolkit/common/styles'; import {createClient, parseXML} from 'webdav/web'; @@ -217,7 +217,7 @@ export class NextcloudFilePicker extends ScopedElementsMixin(DBPLitElement) { cell.getValue() === 'directory' ? `<${icon_tag} name="folder" class="nextcloud-picker-icon"></${icon_tag}>` : icon; - let div = this.shadowRoot.createElement('div'); + let div = getShadowRootDocument(this).createElement('div'); div.innerHTML = html; return div; },