UNPKG

@ima/core

Version:

IMA.js framework for isomorphic javascript application

211 lines (210 loc) 6.38 kB
import { Window } from './Window'; /** * Client-side implementation of the {@link Window} utility API. */ export class ClientWindow extends Window { #scopedListeners = new WeakMap(); static get $dependencies() { return []; } /** * @inheritDoc */ isClient() { return true; } /** * @inheritDoc */ isCookieEnabled() { return navigator.cookieEnabled; } /** * @inheritDoc */ hasSessionStorage() { try { if (window.sessionStorage) { const sessionKey = 'IMA.jsTest'; sessionStorage.setItem(sessionKey, '1'); sessionStorage.removeItem(sessionKey); return true; } } catch (error) { if ($Debug) { console.warn('Session Storage is not accessible!', error); } return false; } return false; } /** * @inheritDoc */ setTitle(title) { document.title = title; } /** * @inheritDoc */ getWindow() { return window; } /** * @inheritDoc */ getDocument() { return document; } /** * @inheritDoc */ getScrollX() { const { pageXOffset } = window; const pageOffsetSupported = pageXOffset !== undefined; const isCSS1Compatible = (document.compatMode || '') === 'CSS1Compat'; return pageOffsetSupported ? pageXOffset : isCSS1Compatible ? document.documentElement.scrollLeft : document.body.scrollLeft; } /** * @inheritDoc */ getScrollY() { const { pageYOffset } = window; const pageOffsetSupported = pageYOffset !== undefined; const isCSS1Compatible = (document.compatMode || '') === 'CSS1Compat'; return pageOffsetSupported ? pageYOffset : isCSS1Compatible ? document.documentElement.scrollTop : document.body.scrollTop; } /** * @inheritDoc */ scrollTo(x, y) { window.scrollTo(x, y); } /** * @inheritDoc */ getDomain() { return window.location.protocol + '//' + window.location.host; } /** * @inheritDoc */ getHost() { return window.location.host; } /** * @inheritDoc */ getPath() { return window.location.pathname + window.location.search; } /** * @inheritDoc */ getUrl() { return window.location.href; } /** * @inheritDoc */ getBody() { return document.body; } /** * @inheritDoc */ getElementById(id) { return document.getElementById(id); } /** * @inheritDoc */ getHistoryState() { return window.history.state; } /** * @inheritDoc */ querySelector(selector) { return document.querySelector(selector); } /** * @inheritDoc */ querySelectorAll(selector) { return document.querySelectorAll(selector); } /** * @inheritDoc */ redirect(url) { window.location.href = url; } /** * @inheritDoc */ pushState(state, title, url) { if (window.history.pushState) { window.history.pushState(state, title, url); } } /** * @inheritDoc */ replaceState(state, title, url) { if (window.history.replaceState) { window.history.replaceState(state, title, url); } } /** * @inheritDoc */ createCustomEvent(name, options) { return new CustomEvent(name, options); } /** * @inheritDoc */ bindEventListener(eventTarget, event, listener, options = false, scope) { if (!eventTarget.addEventListener) { return; } let scopedListener; if (scope) { scopedListener = this._findScopedListener(eventTarget, event, listener, options, scope); if (!scopedListener) { scopedListener = listener.bind(scope); // Add scoped listener if (!this.#scopedListeners.has(eventTarget)) { this.#scopedListeners.set(eventTarget, new Map()); } const scopedListeners = this.#scopedListeners.get(eventTarget); scopedListeners.set([ event, listener, this._getListenerCapture(options), scope ], scopedListener); } } eventTarget.addEventListener(event, scopedListener ?? listener, options); } /** * @inheritDoc */ unbindEventListener(eventTarget, event, listener, options = false, scope) { if (!eventTarget.addEventListener) { return; } let scopedListener; if (scope) { scopedListener = this._findScopedListener(eventTarget, event, listener, options, scope, true); if ($Debug && !scopedListener) { console.warn('ima.core.window.ClientWindow.unbindEventListener(): the provided ' + `listener '${listener}' is not registered for the ` + `specified event '${event}' and scope '${scope}'. Check ` + `your workflow.`, { event, listener, scope }); } } eventTarget.removeEventListener(event, scopedListener ?? listener, options); } _findScopedListener(eventTarget, event, listener, options, scope, remove = false) { if (!this.#scopedListeners.has(eventTarget)) { return; } const scopedListeners = this.#scopedListeners.get(eventTarget); for (const key of scopedListeners.keys()){ const [scopedEvent, scopedListener, scopedCapture, scopedScope] = key; if (event === scopedEvent && listener === scopedListener && this._getListenerCapture(options) === scopedCapture && scope === scopedScope) { const usedListener = scopedListeners.get(key); if (remove) { scopedListeners.delete(key); if (!scopedListeners.size) { this.#scopedListeners.delete(eventTarget); } } return usedListener; } } } _getListenerCapture(options) { return typeof options === 'boolean' ? options : options.capture ?? false; } } //# sourceMappingURL=ClientWindow.js.map