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