@jinntec/fore
Version:
Fore - declarative user interfaces in plain HTML
133 lines (112 loc) • 3.54 kB
JavaScript
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);
}