UNPKG

@dcloudio/uni-debugger

Version:

uni-app debugger

185 lines (164 loc) 4.65 kB
// Copyright 2017 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. /** * @extends {UI.XElement} */ UI.XWidget = class extends UI.XElement { constructor() { super(); this.style.setProperty('display', 'flex'); this.style.setProperty('flex-direction', 'column'); this.style.setProperty('align-items', 'stretch'); this.style.setProperty('justify-content', 'flex-start'); this.style.setProperty('contain', 'layout style'); this._visible = false; /** @type {?DocumentFragment} */ this._shadowRoot; /** @type {?Element} */ this._defaultFocusedElement = null; /** @type {!Array<!Element>} */ this._elementsToRestoreScrollPositionsFor = []; /** @type {?function()} */ this._onShownCallback; /** @type {?function()} */ this._onHiddenCallback; /** @type {?function()} */ this._onResizedCallback; if (!UI.XWidget._observer) { UI.XWidget._observer = new ResizeObserver(entries => { for (const entry of entries) { if (entry.target._visible && entry.target._onResizedCallback) entry.target._onResizedCallback.call(null); } }); } UI.XWidget._observer.observe(this); this.setElementsToRestoreScrollPositionsFor([this]); } /** * @param {?Node} node */ static focusWidgetForNode(node) { node = node && node.parentNodeOrShadowHost(); let widget = null; while (node) { if (node instanceof UI.XWidget) { if (widget) node._defaultFocusedElement = widget; widget = node; } node = node.parentNodeOrShadowHost(); } } /** * @return {boolean} */ isShowing() { return this._visible; } /** * @param {string} cssFile */ registerRequiredCSS(cssFile) { UI.appendStyle(this._shadowRoot || this, cssFile); } /** * @param {?function()} callback */ setOnShown(callback) { this._onShownCallback = callback; } /** * @param {?function()} callback */ setOnHidden(callback) { this._onHiddenCallback = callback; } /** * @param {?function()} callback */ setOnResized(callback) { this._onResizedCallback = callback; } /** * @param {!Array<!Element>} elements */ setElementsToRestoreScrollPositionsFor(elements) { for (const element of this._elementsToRestoreScrollPositionsFor) element.removeEventListener('scroll', UI.XWidget._storeScrollPosition, {passive: true, capture: false}); this._elementsToRestoreScrollPositionsFor = elements; for (const element of this._elementsToRestoreScrollPositionsFor) element.addEventListener('scroll', UI.XWidget._storeScrollPosition, {passive: true, capture: false}); } restoreScrollPositions() { for (const element of this._elementsToRestoreScrollPositionsFor) { if (element._scrollTop) element.scrollTop = element._scrollTop; if (element._scrollLeft) element.scrollLeft = element._scrollLeft; } } /** * @param {!Event} event */ static _storeScrollPosition(event) { const element = event.currentTarget; element._scrollTop = element.scrollTop; element._scrollLeft = element.scrollLeft; } /** * @param {?Element} element */ setDefaultFocusedElement(element) { if (element && !this.isSelfOrAncestor(element)) throw new Error('Default focus must be descendant'); this._defaultFocusedElement = element; } /** * @override */ focus() { if (!this._visible) return; let element; if (this._defaultFocusedElement && this.isSelfOrAncestor(this._defaultFocusedElement)) { element = this._defaultFocusedElement; } else if (this.tabIndex !== -1) { element = this; } else { let child = this.traverseNextNode(this); while (child) { if ((child instanceof UI.XWidget) && child._visible) { element = child; break; } child = child.traverseNextNode(this); } } if (!element || element.hasFocus()) return; if (element === this) HTMLElement.prototype.focus.call(this); else element.focus(); } /** * @override */ connectedCallback() { this._visible = true; this.restoreScrollPositions(); if (this._onShownCallback) this._onShownCallback.call(null); } /** * @override */ disconnectedCallback() { this._visible = false; if (this._onHiddenCallback) this._onHiddenCallback.call(null); } }; self.customElements.define('x-widget', UI.XWidget);