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 itemValue: Array<string> = []; 24 customItem: Array<string> = []; 25 private focused: unknown; 26 private selectVInputEl: unknown; 27 private selectVSearchInputEl: unknown; 28 private selectVIconEl: unknown; 29 private selectVOptions: HTMLDivElement | undefined; 30 private selectVBody: HTMLDivElement | undefined; 31 32 private valueStr: string = ''; 33 private currentvalueStr: string = ''; 34 35 static get observedAttributes(): string[] { 36 return ['value', 'default-value', 'placeholder', 'disabled', 'show-search', 'border', 'mode']; 37 } 38 39 get value(): string { 40 // @ts-ignore 41 return this.selectVInputEl!.value || this.defaultValue; 42 } 43 44 get rounded(): boolean { 45 return this.hasAttribute('rounded'); 46 } 47 48 set rounded(selectVRounded: boolean) { 49 if (selectVRounded) { 50 this.setAttribute('rounded', ''); 51 } else { 52 this.removeAttribute('rounded'); 53 } 54 } 55 56 get placement(): string { 57 return this.getAttribute('placement') || ''; 58 } 59 60 set placement(selectVPlacement: string) { 61 if (selectVPlacement) { 62 this.setAttribute('placement', selectVPlacement); 63 } else { 64 this.removeAttribute('placement'); 65 } 66 } 67 68 get border(): string { 69 return this.getAttribute('border') || 'true'; 70 } 71 72 set border(selectVBorder) { 73 if (selectVBorder) { 74 this.setAttribute('border', 'true'); 75 } else { 76 this.setAttribute('border', 'false'); 77 } 78 } 79 80 get defaultPlaceholder(): string { 81 return this.getAttribute('placeholder') || ''; 82 } 83 84 get defaultValue(): string { 85 return this.getAttribute('default-value') || ''; 86 } 87 88 set defaultValue(selectVDefaultValue) { 89 this.setAttribute('default-value', selectVDefaultValue); 90 } 91 92 get placeholder(): string { 93 return this.getAttribute('placeholder') || this.defaultPlaceholder; 94 } 95 96 set placeholder(selectVPlaceholder) { 97 this.setAttribute('placeholder', selectVPlaceholder); 98 } 99 100 set all(isAll: boolean) { 101 if (isAll) { 102 this.setAttribute('is-all', ''); 103 } else { 104 this.removeAttribute('is-all'); 105 } 106 } 107 108 get all(): boolean { 109 return this.hasAttribute('is-all'); 110 } 111 112 dataSource(selectVData: Array<string>, valueStr: string, isSingle?: boolean): void { 113 this.selectVOptions!.innerHTML = ''; 114 if (selectVData.length > 0) { 115 this.selectVBody!.style.display = 'block'; 116 this.valueStr = valueStr; 117 this.itemValue = selectVData; 118 if (valueStr !== '') { 119 let option = document.createElement('lit-select-option'); 120 if (this.all) { 121 option.setAttribute('selected', ''); 122 this.showItems = selectVData; 123 } 124 option.setAttribute('value', valueStr); 125 option.textContent = valueStr; 126 this.selectVOptions!.appendChild(option); 127 this.initDataItem(selectVData); 128 if (isSingle) { 129 this.initSingleCustomOptions(); 130 } else { 131 this.initCustomOptions(); 132 } 133 } else { 134 this.initDataItem(selectVData); 135 if (isSingle) { 136 this.initSingleCustomOptions(); 137 } else { 138 this.initOptions(); 139 } 140 } 141 } else { 142 this.selectVBody!.style.display = 'none'; 143 } 144 if (this.title === 'Event List') { 145 let inputElement = this.shadowRoot?.querySelector('input') as HTMLInputElement; 146 inputElement.readOnly = false; 147 } 148 } 149 150 initDataItem(selectVDataItem: Array<string>): void { 151 selectVDataItem.forEach((item) => { 152 let selectVOption = document.createElement('lit-select-option'); 153 if (this.showItems.indexOf(item) > -1 || this.all) { 154 selectVOption.setAttribute('selected', ''); 155 } 156 selectVOption.className = 'option'; 157 selectVOption.setAttribute('value', item); 158 selectVOption.textContent = item; 159 this.selectVOptions!.appendChild(selectVOption); 160 }); 161 } 162 163 initElements(): void { 164 this.tabIndex = 0; 165 this.focused = false; 166 this.selectVInputEl = this.shadowRoot!.querySelector('#select-input') as HTMLInputElement; 167 this.selectVSearchInputEl = this.shadowRoot!.querySelector('#search-input') as HTMLInputElement; 168 this.selectVBody = this.shadowRoot!.querySelector('.body') as HTMLDivElement; 169 this.selectVOptions = this.shadowRoot!.querySelector('.body-opt') as HTMLDivElement; 170 this.selectVIconEl = this.shadowRoot!.querySelector('.icon'); // @ts-ignore 171 this.selectVInputEl?.addEventListener('keyup', (e) => { 172 if (e.code === 'Enter' || e.code === 'NumpadEnter') {// @ts-ignore 173 this.selectVInputEl.blur(); 174 } 175 });// @ts-ignore 176 this.selectVInputEl!.oninput = (ev: InputEvent): void => { 177 // @ts-ignore 178 if (this.selectVInputEl!.value === '00') { 179 // @ts-ignore 180 this.selectVInputEl!.value = '0'; 181 ev.preventDefault(); 182 } // @ts-ignore 183 if (this.selectVInputEl!.value === '') { 184 this.shadowRoot?.querySelectorAll('lit-select-option').forEach((it) => { 185 it.removeAttribute('selected'); 186 this.showItems = []; 187 this.currentvalueStr = ''; 188 }); 189 } 190 }; // @ts-ignore 191 this.selectVSearchInputEl!.onkeydown = (ev: KeyboardEvent): void => { 192 // @ts-ignore 193 if (ev.key === '0' && ev.target.value.length === 1 && ev.target.value === '0') { 194 ev.preventDefault(); 195 } 196 }; 197 this.onclick = (ev: unknown): void => { 198 if (this.focused === false) { 199 this.focused = true; 200 } else { 201 this.focused = false; 202 } 203 }; // @ts-ignore 204 this.selectVSearchInputEl?.addEventListener('keyup', () => { 205 let options = [...this.shadowRoot!.querySelectorAll<LitSelectOption>('.option')]; 206 options.filter((a: LitSelectOption) => { 207 // @ts-ignore 208 if (a.textContent!.indexOf(this.selectVSearchInputEl!.value) <= -1) { 209 a.style.display = 'none'; 210 } else { 211 a.style.display = 'flex'; 212 } 213 }); 214 }); 215 this.setEvent(); 216 } 217 218 setEvent(): void { 219 this.onmouseout = this.onblur = (ev): void => { 220 this.focused = false; 221 }; // @ts-ignore 222 this.selectVInputEl.onfocus = (ev: unknown): void => { 223 if (this.hasAttribute('disabled')) { 224 return; 225 } 226 }; // @ts-ignore 227 this.selectVInputEl.onblur = (ev: unknown): void => { 228 if (this.hasAttribute('disabled')) { 229 return; 230 } 231 }; 232 } 233 234 initHtml(): string { 235 return ` 236 ${selectVHtmlStr} 237 <div class="root noSelect" tabindex="0" hidefocus="true"> 238 <input id="select-input" placeholder="${this.placeholder}" tabindex="0" readonly="readonly"> 239 <lit-icon class="icon" name='down' color="#c3c3c3"></lit-icon> 240 </div> 241 <div class="body"> 242 <div class="body-select"> 243 <input id="search-input" placeholder="Search"> 244 </div> 245 <div class="body-opt"> 246 <slot></slot> 247 <slot name="footer"></slot> 248 </div> 249 </div> 250 `; 251 } 252 253 connectedCallback(): void { } 254 255 initCustomOptions(): void { 256 let querySelector = this.shadowRoot?.querySelector( 257 `lit-select-option[value="${this.valueStr}"]` 258 ) as LitSelectOption; 259 this.shadowRoot?.querySelectorAll('lit-select-option').forEach((a) => { 260 a.setAttribute('check', ''); 261 a.addEventListener('onSelected', (e: unknown) => { 262 if (a.hasAttribute('selected')) { 263 let number = this.showItems.indexOf(a.textContent!); 264 if (number > -1) { 265 this.showItems!.splice(number, 1); // @ts-ignore 266 this.selectVInputEl!.value = this.showItems; 267 } 268 this.all = false; 269 querySelector.removeAttribute('selected'); 270 a.removeAttribute('selected'); 271 return; 272 } else { 273 let index = this.itemValue.indexOf(a.textContent!); 274 let value = this.showItems.indexOf(a.textContent!); 275 if (index > -1 && value === -1) { 276 this.showItems.push(a.textContent!); // @ts-ignore 277 this.selectVInputEl!.value = this.showItems; 278 } 279 if (this.showItems.length >= this.itemValue.length) { 280 querySelector.setAttribute('selected', ''); 281 this.all = true; 282 } else { 283 querySelector.removeAttribute('selected'); 284 this.all = false; 285 } 286 a.setAttribute('selected', ''); 287 } 288 }); 289 }); 290 this.selectAll(querySelector); 291 } 292 293 initSingleCustomOptions(): void { 294 let selectedOption = this.shadowRoot?.querySelector( 295 `lit-select-option[value="${this.currentvalueStr}"]` 296 ) as LitSelectOption | null; 297 if (selectedOption) { 298 selectedOption.setAttribute('selected', ''); 299 } 300 this.shadowRoot?.querySelectorAll('lit-select-option').forEach((option) => { 301 option.addEventListener('onSelected', () => { 302 this.shadowRoot?.querySelectorAll('lit-select-option').forEach((o) => { 303 o.removeAttribute('selected'); 304 }); 305 option.setAttribute('selected', ''); 306 //@ts-ignore 307 this.selectVInputEl!.value = option.textContent!; 308 this.currentvalueStr = option.textContent!; 309 }); 310 }); 311 } 312 313 initOptions(): void { 314 this.shadowRoot?.querySelectorAll('lit-select-option').forEach((a) => { 315 a.setAttribute('check', ''); 316 a.addEventListener('onSelected', (e: unknown) => { 317 if (a.hasAttribute('selected')) { 318 let number = this.showItems.indexOf(a.textContent!); 319 if (number > -1) { 320 this.showItems.splice(number, 1); 321 } 322 a.removeAttribute('selected'); 323 } else { 324 let index = this.itemValue.indexOf(a.textContent!); 325 if (index > -1) { 326 this.showItems.push(a.textContent!); 327 } 328 a.setAttribute('selected', ''); 329 } // @ts-ignore 330 let items = this.selectVInputEl!.value.split(','); 331 this.customItem = []; 332 items.forEach((item: string) => { 333 if (item.trim() !== '') { 334 let indexItem = this.itemValue.indexOf(item.trim()); 335 if (indexItem === -1) { 336 this.customItem.push(item.trim()); 337 } 338 } 339 }); 340 if (this.customItem.length > 0) { 341 // @ts-ignore 342 this.selectVInputEl.value = this.customItem.concat(this.showItems); 343 } else { 344 // @ts-ignore 345 this.selectVInputEl.value = this.showItems; 346 } 347 }); 348 }); 349 } 350 351 selectAll(querySelector: LitSelectOption): void { 352 querySelector?.addEventListener('click', (ev) => { 353 if (querySelector.hasAttribute('selected')) { 354 this.shadowRoot?.querySelectorAll('lit-select-option').forEach((a) => { 355 a.setAttribute('selected', ''); 356 this.all = true; 357 }); 358 this.itemValue.forEach((i) => { 359 this.showItems.push(i); 360 }); // @ts-ignore 361 this.selectVInputEl.value = this.itemValue; 362 } else { 363 this.shadowRoot?.querySelectorAll('lit-select-option').forEach((i) => { 364 i.removeAttribute('selected'); 365 this.all = false; 366 }); 367 this.showItems = []; // @ts-ignore 368 this.selectVInputEl.value = ''; 369 } 370 }); 371 } 372 373 attributeChangedCallback(name: unknown, oldValue: unknown, newValue: unknown): void { } 374} 375