@3mo/select-field
Version:
A select field web component
77 lines (76 loc) • 2.96 kB
JavaScript
export class FieldSelectValueController {
get menuValue() { return this._menuValue; }
set menuValue(value) {
this.preventSync = true;
this._menuValue = value;
this.select.index = this.index;
this.select.value = this.value;
this.select.data = this.data;
this.select.requestValueUpdate();
this.select.updateComplete.then(() => setTimeout(() => this.preventSync = false, 5));
}
constructor(select) {
this.select = select;
this.preventSync = false;
this._menuValue = new Array();
}
get selectedOptions() { return this.select.options.filter(o => o.index !== undefined && this.menuValue.includes(o.index)); }
get multiple() { return this.select.multiple; }
get index() { return this.getSelectValue(this.menuValue); }
set index(value) {
this._index = value;
if (this.preventSync === false) {
this.selectionOrigin = 'index';
this.setSelectValue(value, (o, indices) => o.index !== undefined && indices.includes(o.index));
}
}
get value() { return this.getSelectValue(this.selectedOptions.map(o => o.normalizedValue)); }
set value(value) {
this._value = value;
if (this.preventSync === false) {
this.selectionOrigin = 'value';
this.setSelectValue(value, (o, values) => values.some(v => o.valueMatches(v)));
}
}
get data() { return this.getSelectValue(this.selectedOptions.map(o => o.data)); }
set data(value) {
this._data = value;
if (this.preventSync === false) {
this.selectionOrigin = 'data';
this.setSelectValue(value, (o, data) => o.data !== undefined && data.some(d => o.dataMatches(d)));
}
}
requestSync() {
this.select[FieldSelectValueController.requestSyncKey]++;
}
sync() {
switch (this.selectionOrigin) {
case 'index':
this.index = this._index;
break;
case 'data':
this.data = this._data;
break;
case 'value':
this.value = this._value;
break;
}
}
getSelectValue(value) {
const v = value instanceof Array ? value : [value];
return this.multiple ? v : v[0];
}
async setSelectValue(value, predicate) {
await new Promise(r => setTimeout(r, 0));
const array = value instanceof Array ? value : [value];
const newIndices = this.select.options
.filter(o => array.some(() => predicate(o, array)))
.map(o => o.index)
.filter(i => i !== undefined);
const equals = newIndices.length === this.menuValue.length && newIndices.every(i => this.menuValue.includes(i));
if (equals === false) {
this.menuValue = newIndices;
}
}
}
FieldSelectValueController.requestSyncKey = 'requestSync';