1/* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { BaseElement, element } from '../BaseElement'; 17import { LitSelectOption } from './LitSelectOption'; 18import { selectHtmlStr, selectVHtmlStr } from './LitSelectHtml'; 19 20@element('lit-select-v') 21export class LitSelectV extends BaseElement { 22 showItems: Array<string> = []; 23 ignoreValues: Array<string> = []; 24 itemValue: Array<string> = []; 25 customItem: Array<string> = []; 26 private focused: unknown; 27 private selectVInputEl: unknown; 28 private selectVSearchInputEl: unknown; 29 private selectVIconEl: unknown; 30 private selectVOptions: HTMLDivElement | undefined; 31 private selectVBody: HTMLDivElement | undefined; 32 33 private valueStr: string = ''; 34 private currentvalueStr: string = ''; 35 36 static get observedAttributes(): string[] { 37 return ['value', 'default-value', 'placeholder', 'disabled', 'show-search', 'border', 'mode']; 38 } 39 40 get value(): string { 41 // @ts-ignore 42 return this.selectVInputEl!.value || this.defaultValue; 43 } 44 45 get rounded(): boolean { 46 return this.hasAttribute('rounded'); 47 } 48 49 set rounded(selectVRounded: boolean) { 50 if (selectVRounded) { 51 this.setAttribute('rounded', ''); 52 } else { 53 this.removeAttribute('rounded'); 54 } 55 } 56 57 get placement(): string { 58 return this.getAttribute('placement') || ''; 59 } 60 61 set placement(selectVPlacement: string) { 62 if (selectVPlacement) { 63 this.setAttribute('placement', selectVPlacement); 64 } else { 65 this.removeAttribute('placement'); 66 } 67 } 68 69 get border(): string { 70 return this.getAttribute('border') || 'true'; 71 } 72 73 set border(selectVBorder) { 74 if (selectVBorder) { 75 this.setAttribute('border', 'true'); 76 } else { 77 this.setAttribute('border', 'false'); 78 } 79 } 80 81 get defaultPlaceholder(): string { 82 return this.getAttribute('placeholder') || ''; 83 } 84 85 get defaultValue(): string { 86 return this.getAttribute('default-value') || ''; 87 } 88 89 set defaultValue(selectVDefaultValue) { 90 this.setAttribute('default-value', selectVDefaultValue); 91 } 92 93 get placeholder(): string { 94 return this.getAttribute('placeholder') || this.defaultPlaceholder; 95 } 96 97 set placeholder(selectVPlaceholder) { 98 this.setAttribute('placeholder', selectVPlaceholder); 99 } 100 101 set all(isAll: boolean) { 102 if (isAll) { 103 this.setAttribute('is-all', ''); 104 } else { 105 this.removeAttribute('is-all'); 106 } 107 } 108 109 get all(): boolean { 110 return this.hasAttribute('is-all'); 111 } 112 113 dataSource(selectVData: Array<string>, valueStr: string, isSingle?: boolean): void { 114 this.selectVOptions!.innerHTML = ''; 115 if (selectVData.length > 0) { 116 this.selectVBody!.style.display = 'block'; 117 this.valueStr = valueStr; 118 this.itemValue = selectVData; 119 if (valueStr !== '') { 120 let option = document.createElement('lit-select-option'); 121 if (this.all) { 122 option.setAttribute('selected', ''); 123 this.showItems = selectVData; 124 } 125 option.setAttribute('value', valueStr); 126 option.textContent = valueStr; 127 this.selectVOptions!.appendChild(option); 128 this.initDataItem(selectVData); 129 if (isSingle) { 130 this.initSingleCustomOptions(); 131 } else { 132 this.initCustomOptions(); 133 } 134 } else { 135 this.initDataItem(selectVData); 136 if (isSingle) { 137 this.initSingleCustomOptions(); 138 } else { 139 this.initOptions(); 140 } 141 } 142 } else { 143 this.selectVBody!.style.display = 'none'; 144 } 145 if (this.title === 'Event List') { 146 let inputElement = this.shadowRoot?.querySelector('input') as HTMLInputElement; 147 inputElement.readOnly = false; 148 } 149 } 150 151 setIgnoreValues(values: string[]) { 152 this.ignoreValues = values; 153 } 154 155 setSelectedOptions(selectArray: Array<string>) { 156 let allSelected = true; 157 this.shadowRoot?.querySelectorAll('lit-select-option').forEach((a) => { 158 if (selectArray.includes(a.textContent!)) { 159 a.setAttribute('selected', ''); 160 } else { 161 allSelected = false; 162 a.removeAttribute('selected'); 163 } 164 }); 165 this.all = allSelected; 166 selectArray.forEach((i) => { 167 this.showItems.push(i); 168 }); 169 // @ts-ignore 170 this.selectVInputEl.value = selectArray.filter(it => !this.ignoreValues.includes(it)); 171 } 172 173 initDataItem(selectVDataItem: Array<string>): void { 174 selectVDataItem.forEach((item) => { 175 let selectVOption = document.createElement('lit-select-option'); 176 if (this.showItems.indexOf(item) > -1 || this.all) { 177 selectVOption.setAttribute('selected', ''); 178 } 179 selectVOption.className = 'option'; 180 selectVOption.setAttribute('value', item); 181 selectVOption.textContent = item; 182 this.selectVOptions!.appendChild(selectVOption); 183 }); 184 } 185 186 initElements(): void { 187 this.tabIndex = 0; 188 this.focused = false; 189 this.selectVInputEl = this.shadowRoot!.querySelector('#select-input') as HTMLInputElement; 190 this.selectVSearchInputEl = this.shadowRoot!.querySelector('#search-input') as HTMLInputElement; 191 this.selectVBody = this.shadowRoot!.querySelector('.body') as HTMLDivElement; 192 this.selectVOptions = this.shadowRoot!.querySelector('.body-opt') as HTMLDivElement; 193 this.selectVIconEl = this.shadowRoot!.querySelector('.icon'); // @ts-ignore 194 this.selectVInputEl?.addEventListener('keyup', (e) => { 195 if (e.code === 'Enter' || e.code === 'NumpadEnter') {// @ts-ignore 196 this.selectVInputEl.blur(); 197 } 198 });// @ts-ignore 199 this.selectVInputEl!.oninput = (ev: InputEvent): void => { 200 // @ts-ignore 201 if (this.selectVInputEl!.value === '00') { 202 // @ts-ignore 203 this.selectVInputEl!.value = '0'; 204 ev.preventDefault(); 205 } // @ts-ignore 206 if (this.selectVInputEl!.value === '') { 207 this.shadowRoot?.querySelectorAll('lit-select-option').forEach((it) => { 208 it.removeAttribute('selected'); 209 this.showItems = []; 210 this.currentvalueStr = ''; 211 }); 212 } 213 }; // @ts-ignore 214 this.selectVSearchInputEl!.onkeydown = (ev: KeyboardEvent): void => { 215 // @ts-ignore 216 if (ev.key === '0' && ev.target.value.length === 1 && ev.target.value === '0') { 217 ev.preventDefault(); 218 } 219 }; 220 this.onclick = (ev: unknown): void => { 221 if (this.focused === false) { 222 this.focused = true; 223 } else { 224 this.focused = false; 225 } 226 }; // @ts-ignore 227 this.selectVSearchInputEl?.addEventListener('keyup', () => { 228 let options = [...this.shadowRoot!.querySelectorAll<LitSelectOption>('.option')]; 229 options.filter((a: LitSelectOption) => { 230 // @ts-ignore 231 if (a.textContent!.indexOf(this.selectVSearchInputEl!.value) <= -1) { 232 a.style.display = 'none'; 233 } else { 234 a.style.display = 'flex'; 235 } 236 }); 237 }); 238 this.setEvent(); 239 } 240 241 setEvent(): void { 242 this.onmouseout = this.onblur = (ev): void => { 243 this.focused = false; 244 }; // @ts-ignore 245 this.selectVInputEl.onfocus = (ev: unknown): void => { 246 if (this.hasAttribute('disabled')) { 247 return; 248 } 249 }; // @ts-ignore 250 this.selectVInputEl.onblur = (ev: unknown): void => { 251 if (this.hasAttribute('disabled')) { 252 return; 253 } 254 }; 255 } 256 257 initHtml(): string { 258 return ` 259 ${selectVHtmlStr} 260 <div class="root noSelect" tabindex="0" hidefocus="true"> 261 <input id="select-input" placeholder="${this.placeholder}" tabindex="0" readonly="readonly"> 262 <lit-icon class="icon" name='down' color="#c3c3c3"></lit-icon> 263 </div> 264 <div class="body"> 265 <div class="body-select"> 266 <input id="search-input" placeholder="Search"> 267 </div> 268 <div class="body-opt"> 269 <slot></slot> 270 <slot name="footer"></slot> 271 </div> 272 </div> 273 `; 274 } 275 276 connectedCallback(): void { } 277 278 initCustomOptions(): void { 279 let querySelector = this.shadowRoot?.querySelector( 280 `lit-select-option[value="${this.valueStr}"]` 281 ) as LitSelectOption; 282 this.shadowRoot?.querySelectorAll('lit-select-option').forEach((a) => { 283 a.setAttribute('check', ''); 284 a.addEventListener('onSelected', (e: unknown) => { 285 if (a.hasAttribute('selected')) { 286 let number = this.showItems.indexOf(a.textContent!); 287 if (number > -1) { 288 this.showItems!.splice(number, 1); // @ts-ignore 289 this.selectVInputEl!.value = this.showItems.filter(it => !this.ignoreValues.includes(it)); 290 } 291 this.all = false; 292 querySelector.removeAttribute('selected'); 293 a.removeAttribute('selected'); 294 return; 295 } else { 296 let index = this.itemValue.indexOf(a.textContent!); 297 let value = this.showItems.indexOf(a.textContent!); 298 if (index > -1 && value === -1) { 299 this.showItems.push(a.textContent!); // @ts-ignore 300 this.selectVInputEl!.value = this.showItems.filter(it => !this.ignoreValues.includes(it)); 301 } 302 if (this.showItems.length >= this.itemValue.length) { 303 querySelector.setAttribute('selected', ''); 304 this.all = true; 305 } else { 306 querySelector.removeAttribute('selected'); 307 this.all = false; 308 } 309 a.setAttribute('selected', ''); 310 } 311 }); 312 }); 313 this.selectAll(querySelector); 314 } 315 316 initSingleCustomOptions(): void { 317 let selectedOption = this.shadowRoot?.querySelector( 318 `lit-select-option[value="${this.currentvalueStr}"]` 319 ) as LitSelectOption | null; 320 if (selectedOption) { 321 selectedOption.setAttribute('selected', ''); 322 } 323 this.shadowRoot?.querySelectorAll('lit-select-option').forEach((option) => { 324 option.addEventListener('onSelected', () => { 325 this.shadowRoot?.querySelectorAll('lit-select-option').forEach((o) => { 326 o.removeAttribute('selected'); 327 }); 328 option.setAttribute('selected', ''); 329 this.dispatchEvent(new CustomEvent('valueChange', { 330 detail: { value: option.textContent! }, 331 bubbles: true, 332 composed: true 333 })); 334 //@ts-ignore 335 this.selectVInputEl!.value = option.textContent!; 336 this.currentvalueStr = option.textContent!; 337 }); 338 }); 339 } 340 341 initOptions(): void { 342 this.shadowRoot?.querySelectorAll('lit-select-option').forEach((a) => { 343 a.setAttribute('check', ''); 344 a.addEventListener('onSelected', (e: unknown) => { 345 if (a.hasAttribute('selected')) { 346 let number = this.showItems.indexOf(a.textContent!); 347 if (number > -1) { 348 this.showItems.splice(number, 1); 349 } 350 a.removeAttribute('selected'); 351 } else { 352 let index = this.itemValue.indexOf(a.textContent!); 353 if (index > -1) { 354 this.showItems.push(a.textContent!); 355 } 356 a.setAttribute('selected', ''); 357 } // @ts-ignore 358 let items = this.selectVInputEl!.value.split(','); 359 this.customItem = []; 360 items.forEach((item: string) => { 361 if (item.trim() !== '') { 362 let indexItem = this.itemValue.indexOf(item.trim()); 363 if (indexItem === -1) { 364 this.customItem.push(item.trim()); 365 } 366 } 367 }); 368 if (this.customItem.length > 0) { 369 // @ts-ignore 370 this.selectVInputEl.value = this.customItem.concat(this.showItems) 371 .filter(it => !this.ignoreValues.includes(it)); 372 } else { 373 // @ts-ignore 374 this.selectVInputEl.value = this.showItems.filter(it => !this.ignoreValues.includes(it)); 375 } 376 }); 377 }); 378 } 379 380 selectAll(querySelector: LitSelectOption): void { 381 querySelector?.addEventListener('click', (ev) => { 382 if (querySelector.hasAttribute('selected')) { 383 this.shadowRoot?.querySelectorAll('lit-select-option').forEach((a) => { 384 a.setAttribute('selected', ''); 385 this.all = true; 386 }); 387 this.itemValue.forEach((i) => { 388 this.showItems.push(i); 389 }); // @ts-ignore 390 this.selectVInputEl.value = this.itemValue.filter(it => !this.ignoreValues.includes(it));; 391 } else { 392 this.shadowRoot?.querySelectorAll('lit-select-option').forEach((i) => { 393 i.removeAttribute('selected'); 394 this.all = false; 395 }); 396 this.showItems = []; // @ts-ignore 397 this.selectVInputEl.value = ''; 398 } 399 }); 400 } 401 402 clearVal(): void {// @ts-ignore 403 this.selectVInputEl!.value = ''; 404 this.shadowRoot?.querySelectorAll('lit-select-option').forEach((a) => { 405 if (a.hasAttribute('selected')) { 406 a.removeAttribute('selected'); 407 } 408 }); 409 this.dataSource([], ''); 410 } 411 412 attributeChangedCallback(name: unknown, oldValue: unknown, newValue: unknown): void { } 413} 414