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