/* * Copyright (C) 2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { BaseElement, element } from '../BaseElement'; import { selectHtmlStr } from './LitSelectHtml'; import { LitSelectOption } from './LitSelectOption'; import { SpSystemTrace } from '../../trace/component/SpSystemTrace'; @element('lit-select') export class LitSelect extends BaseElement { private focused: unknown; private selectInputEl: unknown; private selectSearchInputEl: HTMLInputElement | null | undefined; private selectVInputEl: HTMLInputElement | null | undefined; private selectOptions: HTMLDivElement | null | undefined; private selectItem: string = ''; private selectClearEl: unknown; private selectIconEl: unknown; private bodyEl: unknown; private selectSearchEl: unknown; private selectMultipleRootEl: unknown; private currentSelectedValue: string = ''; static get observedAttributes(): string[] { return [ 'value', 'default-value', 'placeholder', 'disabled', 'loading', 'allow-clear', 'show-search', 'list-height', 'border', 'mode', 'showSearchInput', 'tabSelect' ]; } get value(): string { return this.getAttribute('value') || this.defaultValue; } set value(selectValue) { this.setAttribute('value', selectValue); } get rounded(): boolean { return this.hasAttribute('rounded'); } set rounded(selectRounded: boolean) { if (selectRounded) { this.setAttribute('rounded', ''); } else { this.removeAttribute('rounded'); } } get placement(): string { return this.getAttribute('placement') || ''; } set placement(selectPlacement: string) { if (selectPlacement) { this.setAttribute('placement', selectPlacement); } else { this.removeAttribute('placement'); } } get border(): string { return this.getAttribute('border') || 'true'; } set border(selectBorder) { if (selectBorder) { this.setAttribute('border', 'true'); } else { this.setAttribute('border', 'false'); } } get listHeight(): string { return this.getAttribute('list-height') || '256px'; } set listHeight(selectListHeight) { this.setAttribute('list-height', selectListHeight); } get defaultPlaceholder(): string { return this.getAttribute('placeholder') || '请选择'; } set canInsert(can: boolean) { if (can) { this.setAttribute('canInsert', ''); } else { this.removeAttribute('canInsert'); } } get canInsert(): boolean { return this.hasAttribute('canInsert'); } get showSearch(): boolean { return this.hasAttribute('show-search'); } get defaultValue(): string { return this.getAttribute('default-value') || ''; } set defaultValue(selectDefaultValue) { this.setAttribute('default-value', selectDefaultValue); } get placeholder(): string { return this.getAttribute('placeholder') || this.defaultPlaceholder; } set placeholder(selectPlaceHolder) { this.setAttribute('placeholder', selectPlaceHolder); } get loading(): boolean { return this.hasAttribute('loading'); } set loading(selectLoading) { if (selectLoading) { this.setAttribute('loading', ''); } else { this.removeAttribute('loading'); } } get showSearchInput(): boolean { return this.hasAttribute('showSearchInput'); } set showSearchInput(isHide: boolean) { if (isHide) { this.setAttribute('showSearchInput', ''); } else { this.removeAttribute('showSearchInput'); } } set showItem(item: string) { this.selectItem = item; } set dataSource(selectDataSource: unknown) { this.innerHTML = ''; // @ts-ignore if (selectDataSource.length > 0) { // @ts-ignore this.bodyEl!.style.display = 'flex'; this.querySelectorAll('lit-select-option').forEach((a) => { this.removeChild(a); }); let valuesSet = new Set(); let flag = true; // 假设所有 value 都是唯一的 // @ts-ignore selectDataSource.forEach(item => { if (valuesSet.has(item.value)) { flag = false; // 如果value有重复,就设置flag为false return; } valuesSet.add(item.value); }); // @ts-ignore selectDataSource.forEach((dateSourceBean: unknown) => { if (dateSourceBean) { let selectOption = document.createElement('lit-select-option'); let optionData = { // @ts-ignore value: dateSourceBean.value ? dateSourceBean.value : dateSourceBean.name || dateSourceBean, // @ts-ignore name: dateSourceBean.name ? dateSourceBean.name : dateSourceBean, }; if (!flag) { // 如果数组的value值不是唯一的,就用name做为value值,避免多个选项被选中 optionData = { // @ts-ignore value: dateSourceBean.name ? dateSourceBean.name : dateSourceBean, // @ts-ignore name: dateSourceBean.name ? dateSourceBean.name : dateSourceBean, }; } selectOption.textContent = optionData.name; selectOption.setAttribute('value', optionData.value); if (this.currentSelectedValue === optionData.value) { selectOption.setAttribute('selected', ''); } // @ts-ignore this.selectInputEl!.value = ''; this.append(selectOption); } }); this.initOptions(); } else { // @ts-ignore this.bodyEl!.style.display = 'none'; } } initElements(): void { this.selectVInputEl = this.shadowRoot!.querySelector('#select-input') as HTMLInputElement; this.selectVInputEl?.addEventListener('keyup', (e) => { if (e.code === 'Enter' || e.code === 'NumpadEnter') {// @ts-ignore this.selectVInputEl.blur();// @ts-ignore this.selectInputEl.value = this.selectVInputEl.value; } }); if (this.showSearchInput) { this.shadowRoot!.querySelector('.body-select')!.style.display = 'block'; this.selectSearchInputEl = this.shadowRoot!.querySelector('#search-input') as HTMLInputElement; this.selectSearchInputEl?.addEventListener('keyup', (evt) => { let options = []; options = [...this.querySelectorAll('lit-select-option')]; options.filter((a: LitSelectOption) => { if (a.textContent!.indexOf(this.selectSearchInputEl!.value) <= -1) { a.style.display = 'none'; } else { a.style.display = 'flex'; } }); evt.preventDefault(); evt.stopPropagation(); }); } } initHtml(): string { return ` ${selectHtmlStr(this.listHeight)}
`; } isMultiple(): boolean { return this.hasAttribute('mode') && this.getAttribute('mode') === 'multiple'; } newTag(value: unknown, text: unknown): HTMLDivElement { let tag: unknown = document.createElement('div'); let icon: unknown = document.createElement('lit-icon'); // @ts-ignore icon.classList.add('tag-close'); // @ts-ignore icon.name = 'close'; let span = document.createElement('span'); // @ts-ignore tag.classList.add('tag'); // @ts-ignore span.dataset.value = value; // @ts-ignore span.textContent = text; // @ts-ignore tag.append(span); // @ts-ignore tag.append(icon); // @ts-ignore icon.onclick = (ev: unknown): void => { // @ts-ignore tag.parentElement.removeChild(tag); this.querySelector(`lit-select-option[value=${value}]`)!.removeAttribute('selected'); if (this.shadowRoot!.querySelectorAll('.tag').length === 0) { // @ts-ignore this.selectInputEl.style.width = 'auto'; // @ts-ignore this.selectInputEl.placeholder = this.defaultPlaceholder; } // @ts-ignore ev.stopPropagation(); }; // @ts-ignore tag.value = value; // @ts-ignore tag.dataset.value = value; // @ts-ignore tag.text = text; // @ts-ignore tag.dataset.text = text; // @ts-ignore return tag; } connectedCallback(): void { this.tabIndex = 0; this.focused = false; this.bodyEl = this.shadowRoot!.querySelector('.body'); this.selectInputEl = this.shadowRoot!.querySelector('input'); this.selectClearEl = this.shadowRoot!.querySelector('.clear'); this.selectIconEl = this.shadowRoot!.querySelector('.icon'); this.selectSearchEl = this.shadowRoot!.querySelector('.search'); this.selectMultipleRootEl = this.shadowRoot!.querySelector('.multipleRoot'); this.selectOptions = this.shadowRoot!.querySelector('.body-opt') as HTMLDivElement; this.setEventClick(); this.setEvent(); // @ts-ignore this.selectInputEl.onblur = (ev: unknown): void => { if (this.hasAttribute('disabled')) { return; } if (this.isMultiple()) { if (this.hasAttribute('show-search')) { // @ts-ignore this.selectSearchEl.style.display = 'none'; // @ts-ignore this.selectIconEl.style.display = 'flex'; } } else { // @ts-ignore if (this.selectInputEl.placeholder !== this.defaultPlaceholder) { // @ts-ignore this.selectInputEl.value = this.selectInputEl.placeholder; // @ts-ignore this.selectInputEl.placeholder = this.defaultPlaceholder; } if (this.hasAttribute('show-search')) { // @ts-ignore this.selectSearchEl.style.display = 'none'; // @ts-ignore this.selectIconEl.style.display = 'flex'; } } }; this.setOninput(); this.setOnkeydown(); } setOninput(): void { // @ts-ignore this.selectInputEl.oninput = (ev: unknown): void => { let els: Element[] = [...this.querySelectorAll('lit-select-option')]; if (this.hasAttribute('show-search')) { // @ts-ignore if (!ev.target.value) { // @ts-ignore els.forEach((a: unknown) => (a.style.display = 'flex')); } else { this.setSelectItem(els, ev); } } else { // @ts-ignore this.value = ev.target.value; } }; } setSelectItem(els: Element[], ev: unknown): void { els.forEach((a: unknown) => { // @ts-ignore let value = a.getAttribute('value'); if ( // @ts-ignore value.toLowerCase().indexOf(ev.target.value.toLowerCase()) !== -1 || // @ts-ignore a.textContent.toLowerCase().indexOf(ev.target.value.toLowerCase()) !== -1 ) { // @ts-ignore a.style.display = 'flex'; } else { // @ts-ignore a.style.display = 'none'; } }); } setEventClick(): void { // @ts-ignore this.selectClearEl.onclick = (ev: unknown): void => { if (this.isMultiple()) { let delNodes: Array = []; // @ts-ignore this.selectMultipleRootEl.childNodes.forEach((a: unknown) => { // @ts-ignore if (a.tagName === 'DIV') { delNodes.push(a); } }); for (let i = 0; i < delNodes.length; i++) { // @ts-ignore delNodes[i].remove(); } if (this.shadowRoot!.querySelectorAll('.tag').length === 0) { // @ts-ignore this.selectInputEl.style.width = 'auto'; // @ts-ignore this.selectInputEl.placeholder = this.defaultPlaceholder; } } this.querySelectorAll('lit-select-option').forEach((a) => a.removeAttribute('selected')); // @ts-ignore this.selectInputEl.value = ''; // @ts-ignore this.selectClearEl.style.display = 'none'; // @ts-ignore this.selectIconEl.style.display = 'flex'; this.blur(); // @ts-ignore ev.stopPropagation(); this.dispatchEvent(new CustomEvent('onClear', { detail: ev })); }; this.initOptions(); this.onclick = (ev: unknown): void => { // @ts-ignore if (ev.target.tagName === 'LIT-SELECT') { if (this.focused === false) { // @ts-ignore this.selectInputEl.focus(); this.focused = true; // @ts-ignore this.bodyEl!.style.display = 'flex'; } else { this.focused = false; } } }; } setEvent(): void { this.onmouseover = this.onfocus = (ev): void => { if (this.focused === false && this.hasAttribute('adaptive-expansion')) { // @ts-ignore if (this.parentElement!.offsetTop < this.bodyEl!.clientHeight) { // @ts-ignore this.bodyEl!.classList.add('body-bottom'); } else { // @ts-ignore this.bodyEl!.classList.remove('body-bottom'); } } if (this.hasAttribute('allow-clear')) { // @ts-ignore if (this.selectInputEl.value.length > 0 || this.selectInputEl.placeholder !== this.defaultPlaceholder) { // @ts-ignore this.selectClearEl.style.display = 'flex'; // @ts-ignore this.selectIconEl.style.display = 'none'; } else { // @ts-ignore this.selectClearEl.style.display = 'none'; // @ts-ignore this.selectIconEl.style.display = 'flex'; } } }; this.onmouseout = this.onblur = (ev): void => { if (this.hasAttribute('allow-clear')) { // @ts-ignore this.selectClearEl.style.display = 'none'; // @ts-ignore this.selectIconEl.style.display = 'flex'; } this.focused = false; }; // @ts-ignore this.selectInputEl.onfocus = (ev: unknown): void => { if (this.hasAttribute('disabled')) { return; } if (this.hasAttribute('show-search')) { // @ts-ignore this.selectSearchEl.style.display = 'flex'; // @ts-ignore this.selectIconEl.style.display = 'none'; } this.querySelectorAll('lit-select-option').forEach((a) => { // @ts-ignore a.style.display = 'flex'; }); }; } setOnkeydown(): void { // @ts-ignore this.selectInputEl.onkeydown = (ev: KeyboardEvent): void => { ev.stopPropagation(); if (this.hasAttribute('tabselect')) { // @ts-ignore this.selectInputEl.readOnly = true; } else { // @ts-ignore if (ev.key === 'Backspace') { if (this.isMultiple()) { // @ts-ignore let tag = this.selectMultipleRootEl.lastElementChild.previousElementSibling; if (tag) { this.querySelector(`lit-select-option[value=${tag.value}]`)?.removeAttribute('selected'); tag.remove(); if (this.shadowRoot!.querySelectorAll('.tag').length === 0) { // @ts-ignore this.selectInputEl.style.width = 'auto'; // @ts-ignore this.selectInputEl.placeholder = this.defaultPlaceholder; } } } else { this.clear(); this.dispatchEvent(new CustomEvent('onClear', { detail: ev })); //向外派发清理事件 } // @ts-ignore } else if (ev.key === 'Enter') { if (!this.canInsert) { let filter = [...this.querySelectorAll('lit-select-option')].filter( // @ts-ignore (a: unknown) => a.style.display !== 'none' ); if (filter.length > 0) { // @ts-ignore this.selectInputEl.value = filter[0].textContent; // @ts-ignore this.selectInputEl.placeholder = filter[0].textContent; this.blur(); // @ts-ignore this.value = filter[0].getAttribute('value'); this.dispatchEvent( new CustomEvent('change', { detail: { selected: true, value: filter[0].getAttribute('value'), text: filter[0].textContent, }, }) ); } }// @ts-ignore } else if (ev.key === '0' && ev.target.value.length === 1 && ev.target.value === '0') { // @ts-ignore ev.preventDefault(); } } }; } initOptions(): void { this.querySelectorAll('lit-select-option').forEach((a) => { if (this.isMultiple()) { a.setAttribute('check', ''); if (a.getAttribute('value') === this.defaultValue) { let tag = this.newTag(a.getAttribute('value'), a.textContent); // @ts-ignore this.selectMultipleRootEl.insertBefore(tag, this.selectInputEl); // @ts-ignore this.selectInputEl.placeholder = ''; // @ts-ignore this.selectInputEl.value = ''; // @ts-ignore this.selectInputEl.style.width = '1px'; a.setAttribute('selected', ''); } } else { if (a.hasAttribute('selected')) { a.removeAttribute('selected'); } if (a.getAttribute('value') === this.defaultValue) { // @ts-ignore this.selectInputEl.value = a.textContent; a.setAttribute('selected', ''); } } a.addEventListener('mouseup', (e) => { e.stopPropagation(); }); a.addEventListener('mousedown', (e) => { e.stopPropagation(); }); this.onSelectedEvent(a); }); } onSelectedEvent(a: Element): void { a.addEventListener('onSelected', (e: unknown) => { if (this.isMultiple()) { if (a.hasAttribute('selected')) { // @ts-ignore let tag = this.shadowRoot!.querySelector(`div[data-value=${e.detail.value}]`) as HTMLElement; if (tag) { tag.parentElement!.removeChild(tag); } // @ts-ignore e.detail.selected = false; } else { // @ts-ignore let tag = this.newTag(e.detail.value, e.detail.text); // @ts-ignore this.selectMultipleRootEl.insertBefore(tag, this.selectInputEl); // @ts-ignore this.selectInputEl.placeholder = ''; // @ts-ignore this.selectInputEl.value = ''; // @ts-ignore this.selectInputEl.style.width = '1px'; } if (this.shadowRoot!.querySelectorAll('.tag').length === 0) { // @ts-ignore this.selectInputEl.style.width = 'auto'; // @ts-ignore this.selectInputEl.placeholder = this.defaultPlaceholder; } // @ts-ignore this.selectInputEl.focus(); } else { [...this.querySelectorAll('lit-select-option')].forEach((item) => { if (item.hasAttribute('selected')) { this.currentSelectedValue = item.getAttribute('value') || ''; } item.removeAttribute('selected'); }); this.blur(); // @ts-ignore this.bodyEl!.style.display = 'none'; // @ts-ignore this.selectInputEl.value = e.detail.text; } if (a.getAttribute('value') === this.currentSelectedValue) { a.removeAttribute('selected'); this.currentSelectedValue = ''; // @ts-ignore this.selectInputEl.value = ''; // @ts-ignore this.selectInputEl.placeholder = this.defaultPlaceholder; } else { this.currentSelectedValue = a.getAttribute('value') || ''; a.setAttribute('selected', ''); } this.value = this.currentSelectedValue; // @ts-ignore this.dispatchEvent(new CustomEvent('change', { detail: { selectValue: this.currentSelectedValue, text: e.detail.text } })); //向外层派发change事件,返回当前选中项 }); } clear(): void { // @ts-ignore this.selectInputEl.value = ''; // @ts-ignore this.selectInputEl.placeholder = this.defaultPlaceholder; } reset(): void { this.querySelectorAll('lit-select-option').forEach((a) => { [...this.querySelectorAll('lit-select-option')].forEach((a) => a.removeAttribute('selected')); if (a.getAttribute('value') === this.defaultValue) { // @ts-ignore this.selectInputEl.value = a.textContent; a.setAttribute('selected', ''); } }); } disconnectedCallback(): void { } adoptedCallback(): void { } attributeChangedCallback(name: unknown, oldValue: unknown, newValue: unknown): void { if (name === 'value' && this.selectInputEl) { if (newValue) { [...this.querySelectorAll('lit-select-option')].forEach((a) => { if (a.getAttribute('value') === newValue) { this.currentSelectedValue = a.getAttribute('value') || ''; a.setAttribute('selected', ''); // @ts-ignore this.selectInputEl.value = a.textContent; } else { a.removeAttribute('selected'); } }); } else { this.clear(); } } } }