1/*
2 * Copyright (C) 2024 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 */
15import {SearchHtml} from './Search.html.js';
16
17const LOCAL_STORAGE_SEARCH_KEY = 'search_key';
18
19export class LitSearch extends HTMLElement {
20
21
22    constructor() {
23        super();
24        this._index = 0;
25        this._list = [];
26        this._value = false;
27        this.historyMaxCount = 100;
28        this.searchList = [];
29        this.searchELList = [];
30        this.attachShadow({mode: 'open'}).innerHTML = this.initHtml();
31        this.initElements();
32    }
33
34    get list() {
35        return this._list;
36    }
37
38    set list(value) {
39        this._list = value;
40    }
41
42    get index() {
43        return this._index;
44    }
45
46    set index(value) {
47        this._index = value;
48    }
49
50    get searchValue() {
51        return this.search?.value ?? '';
52    }
53
54    get isLoading() {
55        return this.hasAttribute('isLoading');
56    }
57
58    set isLoading(va) {
59        if (va) {
60            this.setAttribute('isLoading', '');
61        } else {
62            this.removeAttribute('isLoading');
63            window.localStorage.setItem(LOCAL_STORAGE_SEARCH_KEY, '');
64        }
65    }
66
67    set isClearValue(value) {
68        this._value = value;
69    }
70
71    get isClearValue() {
72        return this._value;
73    }
74
75    valueChangeHandler = () => {
76    };
77
78    setPercent(name = '', value) {
79        let searchHide = this.shadowRoot.querySelector('.root');
80        let searchIcon = this.shadowRoot.querySelector('#search-icon');
81        if (this.hasAttribute('textRoll')) {
82            this.removeAttribute('textRoll');
83        }
84        this.isLoading = false;
85        if (value > 0 && value <= 100) {
86            searchHide.style.display = 'flex';
87            searchHide.style.backgroundColor = '#e3e3e3';
88            searchIcon === null || searchIcon === void 0 ? void 0 : searchIcon.setAttribute('name', 'cloud-sync');
89            this.search.setAttribute('placeholder', `${name}${value}%`);
90            this.search.setAttribute('readonly', '');
91            this.search.className = 'readonly';
92            this.isLoading = true;
93        } else if (value > 100) {
94            searchHide.style.display = 'flex';
95            searchHide.style.backgroundColor = '#fff';
96            searchIcon?.setAttribute('name', 'search');
97            this.search?.setAttribute('placeholder', 'search');
98            this.search?.removeAttribute('readonly');
99            this.search.className = 'write';
100        } else if (value === -1) {
101            searchHide.style.display = 'flex';
102            searchHide.style.backgroundColor = '#e3e3e3';
103            searchIcon === null || searchIcon === void 0 ? void 0 : searchIcon.setAttribute('name', 'cloud-sync');
104            this.search.setAttribute('placeholder', `${name}`);
105            this.search.setAttribute('readonly', '');
106            this.search.className = 'readonly';
107        } else {
108            searchHide.style.display = 'none';
109        }
110    }
111
112    clear() {
113        this.search = this.shadowRoot.querySelector('input');
114        this.search.value = '';
115        this.list = [];
116    }
117
118    blur() {
119        this.search?.blur();
120    }
121
122    updateSearchList(searchStr) {
123        if (searchStr === null || searchStr.length === 0 || searchStr.trim().length === 0) {
124            return;
125        }
126        let searchInfo = this.searchList.find((searchInfo) => searchInfo.searchContent === searchStr);
127        if (searchInfo !== undefined) {
128            let index = this.searchList.indexOf(searchInfo);
129            this.searchList.splice(index, 1);
130            this.searchList.unshift({searchContent: searchStr, useCount: 1});
131        } else {
132            this.searchList.unshift({searchContent: searchStr, useCount: 1});
133        }
134    }
135
136    getSearchHistory() {
137        let searchString = window.localStorage.getItem(LOCAL_STORAGE_SEARCH_KEY);
138        if (searchString) {
139            let searHistory = JSON.parse(searchString);
140            if (Array.isArray(searHistory)) {
141                this.searchList = searHistory;
142                return searHistory;
143            }
144        }
145        return [];
146    }
147
148    searchFocusListener() {
149    }
150
151    searchBlurListener() {
152        this.dispatchEvent(new CustomEvent('blur', {
153            detail: {
154                value: this.search.value,
155            },
156        }));
157    }
158
159    searchKeyupListener(e) {
160        if (e.code === 'Enter' || e.code === 'NumpadEnter') {
161            this.updateSearchList(this.search.value);
162        } else {
163            this.updateSearchHistoryList(this.search.value);
164            this.valueChangeHandler?.call(this, this.trimSideSpace(this.search.value));
165        }
166        e.stopPropagation();
167    }
168
169    trimSideSpace(str) {
170        return str.replace(/(^\s*)|(\s*$)/g, '');
171    }
172
173    initElements() {
174        this.search = this.shadowRoot.querySelector('input');
175        this.searchHistoryListEL = this.shadowRoot.querySelector('.search-history-list');
176        this.retargetIndex = this.shadowRoot.querySelector('input[name="retarge_index"]');
177        this.search.addEventListener('focus', () => {
178        });
179        this.search.addEventListener('blur', () => {
180            this.searchBlurListener();
181        });
182        this.search.addEventListener('change', () => {
183            this.index = -1;
184            this.retargetIndex.value = '';
185        });
186        this.search.addEventListener('keyup', (e) => {
187            this.retargetIndex.value = '';
188            this.index = -1;
189            this.searchKeyupListener(e);
190        });
191        (this.shadowRoot?.querySelector('input[name="retarget_index"]'))?.addEventListener('keydown', (event) => {
192            if (event.key === 'Enter') {
193                event.stopPropagation();
194            }
195        });
196    }
197
198    initHtml() {
199        return SearchHtml;
200    }
201
202    hideSearchHistoryList() {
203        this.searchHistoryListEL.style.display = 'none';
204        if (this.searchList.length > this.historyMaxCount) {
205            this.searchList = this.searchList.slice(0, this.historyMaxCount);
206        }
207        if (this.searchList.length === 0) {
208            return;
209        }
210        let historyStr = JSON.stringify(this.searchList);
211        window.localStorage.setItem(LOCAL_STORAGE_SEARCH_KEY, historyStr);
212        this.searchList = [];
213        this.searchELList = [];
214    }
215
216    updateSearchHistoryList(searchValue) {
217        const keyword = searchValue.toLowerCase();
218        this.searchELList.forEach((item) => {
219            if (item.textContent.toLowerCase().includes(keyword)) {
220                item.style.display = 'block';
221            } else {
222                item.style.display = 'none';
223            }
224        });
225    }
226}
227
228if (!customElements.get('lit-search')) {
229    customElements.define('lit-search', LitSearch);
230}
231