UNPKG

@jinntec/fore

Version:

Fore - declarative user interfaces in plain HTML

133 lines (112 loc) 3.54 kB
import { Fore } from '../fore.js'; // import ForeElementMixin from '../ForeElementMixin.js'; import { withDraggability } from '../withDraggability.js'; import { UIElement } from './UIElement.js'; /** * `fx-repeat` * an xformish form for eXist-db * * @customElement * @demo demo/index.html * * @extends {UIElement} */ export class FxRepeatitem extends withDraggability(UIElement, true) { static get properties() { return { ...super.properties, inited: { type: Boolean, }, }; } constructor() { super(); this.inited = false; this.addEventListener('click', this._dispatchIndexChange); // this.addEventListener('focusin', this._handleFocus); this.addEventListener('focusin', this._dispatchIndexChange); this.attachShadow({ mode: 'open', delegatesFocus: true }); this.dropTarget = null; // TODO: rename to position? this.index = -1; } connectedCallback() { super.connectedCallback(); this.display = this.style.display; const html = ` <slot></slot> `; this.shadowRoot.innerHTML = ` ${html} `; this.getOwnerForm().registerLazyElement(this); // Keep ref as a *property only* so repeatitem does not become the nearest [ref] for its children. // Its children already get their context from the repeatitem via getInScopeContext(). this.ref = `${this.parentNode.ref}`; this.tabindex = 0; } disconnectedCallback() { super.disconnectedCallback(); this.removeEventListener('click', this._dispatchIndexChange); this.removeEventListener('focusin', this._dispatchIndexChange); } init() { // console.log('repeatitem init model ', this.nodeset); // this._initializeChildren(this); this.inited = true; } /* getModelItem() { super.getModelItem(); // console.log('modelItem in repeatitem ', this.getModelItem()[this.index]); return this.getModelItem()[this.index]; } */ async _dispatchIndexChange() { /** * @type {import('./fx-repeat.js').FxRepeat} */ const repeat = this.parentNode; if (repeat.index === this.index) { // The index did not really change if it did not change :wink: return; } await this.dispatchEvent( new CustomEvent('item-changed', { composed: false, bubbles: true, detail: { item: this, index: this.index }, }), ); // Refresh after all of the listeners for that item-changed have had their turn to update! this.getOwnerForm().refresh(); } update(_modelItem) { // Repeatitems must refresh when their ModelItem facets (e.g. relevant) change, // but they should NOT have a `ref` attribute (that would change inscope context resolution). const fore = this.getOwnerForm(); if (!fore) return; if (fore.isRefreshPhase) { fore.addToBatchedNotifications(this); } else { this.refresh(); } } async refresh(force = false) { // this.modelItem = this.getModelItem(); this.attachObserver(); // console.log('🔄 repeatitem modelitem', this.getModelItem()); if (this.modelItem && !this.modelItem.relevant) { this.removeAttribute('relevant'); this.setAttribute('nonrelevant', ''); } else { this.removeAttribute('nonrelevant'); this.setAttribute('relevant', ''); } await Fore.refreshChildren(this, force); } } if (!customElements.get('fx-repeatitem')) { window.customElements.define('fx-repeatitem', FxRepeatitem); }