vicowa-web-components
Version:
162 lines (142 loc) • 4.72 kB
JavaScript
import { WebComponentBaseClass } from '/third_party/web-component-base-class/src/web-component-base-class.js';
import '../vicowa-input/vicowa-input.js';
class VicowaMoveBetweenLists extends WebComponentBaseClass {
constructor() { super(); }
static get properties() {
return {
firstTitle: {
type: String,
value: '',
reflectToAttribute: true,
observer: (control) => control.#titleUpdated(),
},
secondTitle: {
type: String,
value: '',
reflectToAttribute: true,
observer: (control) => control.#titleUpdated(),
},
first: {
type: Array,
value: [],
observer: (control) => control.#updateFirst(),
},
second: {
type: Array,
value: [],
observer: (control) => control.#updateSecond(),
},
};
}
attached() {
this.$.firstFilter.onChange = () => { this.#updateFirst(); };
this.$.secondFilter.onChange = () => { this.#updateSecond(); };
const updateStates = () => {
this.$.secondToFirst.classList.toggle('disabled', !this.$.secondList.selectedOptions.length);
this.$.firstToSecond.classList.toggle('disabled', !this.$.firstList.selectedOptions.length);
};
this.addAutoEventListener(this.$.secondList, 'change', updateStates);
this.addAutoEventListener(this.$.firstList, 'change', updateStates);
updateStates();
this.addAutoEventListener(this.$.firstToSecond, 'click', () => {
const selected = Array.from(this.$.firstList.selectedOptions);
this.second = this.second.concat(selected.map((option) => option.item));
this.first = this.first.filter((item) => !selected.find((option) => option.item === item));
updateStates();
if (this.onChange) {
this.onChange();
}
});
this.addAutoEventListener(this.$.secondToFirst, 'click', () => {
const selected = Array.from(this.$.secondList.selectedOptions);
this.first = this.first.concat(selected.map((option) => option.item));
this.second = this.second.filter((item) => !selected.find((option) => option.item === item));
updateStates();
if (this.onChange) {
this.onChange();
}
});
}
#updateFirst() {
const regExp = (this.$.firstFilter.value.trim()) ? new RegExp(this.$.firstFilter.value.trim()) : null;
this.$.firstList.innerHTML = '';
this.first.filter((item) => !regExp || regExp.test(item.displayName)).sort().forEach((item) => {
const option = document.createElement('option');
option.item = item;
option.textContent = item.displayName;
this.$.firstList.appendChild(option);
});
}
#updateSecond() {
const regExp = (this.$.secondFilter.value.trim()) ? new RegExp(this.$.secondFilter.value.trim()) : null;
this.$.secondList.innerHTML = '';
this.second.filter((item) => !regExp || regExp.test(item.displayName)).sort().forEach((item) => {
const option = document.createElement('option');
option.item = item;
option.textContent = item.displayName;
this.$.secondList.appendChild(option);
});
}
#titleUpdated() {
this.$.firstTitle.string = this.firstTitle;
this.$.secondTitle.string = this.secondTitle;
}
static get template() {
return `
<style>
.list-container {
justify-content: stretch;
--vicowa-input-control-width: 200px;
}
.swap-button-container {
justify-content: center;
}
.swap-button-container button {
margin: 3px 2px;
}
.list-container,
.swap-button-container {
display: flex;
flex-direction: column;
}
select {
width: var(--vicowa-input-control-width);
height: 200px;
}
label {
margin: .2em 0;
}
.side-by-side {
display: flex;
}
.move {
cursor: pointer;
}
.disabled {
pointer-events: none;
opacity: 0.5;
cursor: default;
}
</style>
<div class="side-by-side">
<div class="list-container">
<label for="first-list"><vicowa-string id="first-title"></vicowa-string></label>
<vicowa-input id="first-filter" placeholder="Filter" hide-label></vicowa-input>
<select id="first-list" multiple>
</select>
</div>
<div class="swap-button-container">
<div class="move" id="first-to-second"><slot name="first-to-second-button"><button >-></button></slot></div>
<div class="move" id="second-to-first"><slot name="second-to-first-button"><button ><-</button></slot></div>
</div>
<div class="list-container">
<label for="second-list"><vicowa-string id="second-title"></vicowa-string></label>
<vicowa-input id="second-filter" placeholder="Filter" hide-label></vicowa-input>
<select id="second-list" multiple>
</select>
</div>
</div>
`;
}
}
window.customElements.define('vicowa-move-between-lists', VicowaMoveBetweenLists);