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"; 18 19@element('lit-select-v') 20export class LitSelectV extends BaseElement { 21 showItems: Array<string> = []; 22 itemValue: Array<string> = []; 23 customItem: Array<string> = []; 24 private focused: any; 25 private inputElement: any; 26 private iconElement: any; 27 private options: HTMLDivElement | undefined; 28 private valueStr: string = ''; 29 30 static get observedAttributes() { 31 return [ 32 'value', 33 'default-value', 34 'placeholder', 35 'disabled', 36 'show-search', 37 'border', 38 'mode', 39 ]; 40 } 41 42 get value() { 43 return this.inputElement!.value || this.defaultValue; 44 } 45 46 get rounded() { 47 return this.hasAttribute("rounded"); 48 } 49 50 set rounded(rounded: boolean) { 51 if (rounded) { 52 this.setAttribute("rounded", ''); 53 } else { 54 this.removeAttribute("rounded"); 55 } 56 } 57 58 get placement(): string { 59 return this.getAttribute("placement") || ""; 60 } 61 62 set placement(placement: string) { 63 if (placement) { 64 this.setAttribute("placement", placement); 65 } else { 66 this.removeAttribute("placement"); 67 } 68 } 69 70 get border() { 71 return this.getAttribute('border') || 'true'; 72 } 73 74 set border(value) { 75 if (value) { 76 this.setAttribute('border', 'true'); 77 } else { 78 this.setAttribute('border', 'false'); 79 } 80 } 81 82 get defaultPlaceholder() { 83 return this.getAttribute('placeholder') || ''; 84 } 85 86 get defaultValue() { 87 return this.getAttribute('default-value') || ''; 88 } 89 90 set defaultValue(value) { 91 this.setAttribute('default-value', value); 92 } 93 94 get placeholder() { 95 return this.getAttribute('placeholder') || this.defaultPlaceholder; 96 } 97 98 set placeholder(value) { 99 this.setAttribute('placeholder', value); 100 } 101 102 set all(isAll: boolean) { 103 if (isAll) { 104 this.setAttribute('is-all', ''); 105 } else { 106 this.removeAttribute('is-all'); 107 } 108 } 109 110 get all() { 111 return this.hasAttribute('is-all'); 112 } 113 114 dataSource(value: Array<string>, valueStr: string) { 115 this.options!.innerHTML = ''; 116 if (value.length > 0) { 117 this.options!.style.display = "block" 118 this.valueStr = valueStr; 119 this.itemValue = value; 120 if (valueStr != "") { 121 let option = document.createElement("lit-select-option"); 122 if (this.all) { 123 option.setAttribute("selected", ""); 124 this.showItems = value 125 } 126 option.setAttribute('value', valueStr); 127 option.textContent = valueStr; 128 this.options!.appendChild(option); 129 this.initDataItem(value); 130 this.initCustomOptions() 131 } else { 132 this.initDataItem(value); 133 this.initOptions() 134 } 135 } else { 136 this.options!.style.display = "none" 137 } 138 if (this.title == 'Event List') { 139 let inputElement = this.shadowRoot?.querySelector('input') as HTMLInputElement; 140 inputElement.readOnly = false 141 } 142 } 143 144 initDataItem(value: Array<string>) { 145 value.forEach( 146 item => { 147 let option = document.createElement("lit-select-option"); 148 if (this.showItems.indexOf(item) > -1 || this.all) { 149 option.setAttribute("selected", "") 150 } 151 option.setAttribute('value', item); 152 option.textContent = item; 153 this.options!.appendChild(option); 154 } 155 ) 156 } 157 158 initElements(): void { 159 this.tabIndex = 0; 160 this.focused = false; 161 this.inputElement = this.shadowRoot!.querySelector('input') as HTMLInputElement; 162 this.options = this.shadowRoot!.querySelector('.body') as HTMLDivElement; 163 this.iconElement = this.shadowRoot!.querySelector('.icon'); 164 this.onclick = (ev: any) => { 165 if (this.focused === false) { 166 this.focused = true; 167 } else { 168 this.focused = false; 169 } 170 } 171 172 this.onmouseout = this.onblur = ev => { 173 this.focused = false; 174 } 175 this.inputElement.onfocus = (ev: any) => { 176 if (this.hasAttribute('disabled')) return; 177 } 178 this.inputElement.onblur = (ev: any) => { 179 if (this.hasAttribute('disabled')) return; 180 } 181 } 182 183 initHtml() { 184 return ` 185 <style> 186 :host{ 187 display: inline-flex; 188 position: relative; 189 overflow: visible; 190 cursor: pointer; 191 border-radius: 2px; 192 outline: none; 193 -webkit-user-select:none ; 194 -moz-user-select:none; 195 user-select:none; 196 } 197 :host(:not([border])), 198 :host([border='true']){ 199 border: 1px solid var(--bark-prompt,#dcdcdc); 200 } 201 input{ 202 border: 0; 203 outline: none; 204 background-color: transparent; 205 cursor: pointer; 206 -webkit-user-select:none ; 207 -moz-user-select:none; 208 user-select:none; 209 display: inline-flex; 210 color: var(--dark-color2,rgba(0,0,0,0.9)); 211 } 212 :host([highlight]) input { 213 color: rgba(255,255,255,0.9); 214 } 215 input{ 216 width: 100%; 217 } 218 :host([mode]) input{ 219 padding: 6px 0px; 220 } 221 :host([mode]) .root{ 222 padding: 1px 8px; 223 } 224 .root{ 225 position: relative; 226 padding: 3px 6px; 227 display: flex; 228 align-items: center; 229 justify-content: space-between; 230 border-radius: 2px; 231 outline: none; 232 font-size: 1rem; 233 z-index: 2; 234 -webkit-user-select:none ; 235 -moz-user-select:none; 236 user-select:none; 237 width: 100%; 238 } 239 .body{ 240 max-height: 256px; 241 position: absolute; 242 bottom: 100%; 243 z-index: 99; 244 padding-top: 5px; 245 margin-top: 2px; 246 background-color: var(--dark-background4,#fff); 247 width: 100%; 248 transform: scaleY(.6); 249 visibility: hidden; 250 opacity: 0; 251 transform-origin: bottom center; 252 display: block; 253 flex-direction: column; 254 box-shadow: 0 5px 15px 0px #00000033; 255 border-radius: 2px; 256 overflow: auto; 257 } 258 .body-bottom{ 259 bottom: auto; 260 top: 100%; 261 transform-origin: top center; 262 } 263 :host([placement="bottom"]) .body{ 264 bottom:unset; 265 top: 100%; 266 transition: none; 267 transform: none; 268 } 269 270 :host([rounded]) .body { 271 border-radius: 16px; 272 } 273 :host([rounded]) .root { 274 border-radius: 16px; 275 height: 25px; 276 } 277 .icon{ 278 pointer-events: none; 279 } 280 .noSelect{ 281 -moz-user-select:none; 282 -ms-user-select:none; 283 user-select:none; 284 -khtml-user-select:none; 285 -webkit-touch-callout:none; 286 -webkit-user-select:none; 287 } 288 289 :host(:not([border]):not([disabled]):focus), 290 :host([border='true']:not([disabled]):focus), 291 :host(:not([border]):not([disabled]):hover), 292 :host([border='true']:not([disabled]):hover){ 293 border:1px solid var(--bark-prompt,#ccc) 294 } 295 :host(:not([disabled]):focus) .body, 296 :host(:not([disabled]):focus-within) .body{ 297 transform: scaleY(1); 298 opacity: 1; 299 z-index: 99; 300 visibility: visible; 301 } 302 :host(:not([disabled]):focus) input{ 303 color: var(--dark-color,#bebebe); 304 } 305 input::-webkit-input-placeholder { 306 color: var(--dark-color,#aab2bd); 307 } 308 :host(:not([border])[disabled]) *, 309 :host([border='true'][disabled]) *{ 310 background-color: var(--dark-background1,#f5f5f5); 311 color: #b7b7b7; 312 cursor: not-allowed; 313 } 314 :host([border='false'][disabled]) *{ 315 color: #b7b7b7; 316 cursor: not-allowed; 317 } 318 .loading{ 319 display: none; 320 } 321 .icon{ 322 display: flex; 323 } 324 325 </style> 326 <div class="root noSelect" tabindex="0" hidefocus="true"> 327 <input placeholder="${this.placeholder}" tabindex="0" readonly="readonly"> 328 <lit-icon class="icon" name='down' color="#c3c3c3"></lit-icon> 329 </div> 330 <div class="body"> 331 <slot></slot> 332 <slot name="footer"></slot> 333 </div> 334 ` 335 } 336 337 connectedCallback() { 338 } 339 340 initCustomOptions() { 341 let querySelector = this.shadowRoot?.querySelector(`lit-select-option[value="${this.valueStr}"]`) as LitSelectOption; 342 this.shadowRoot?.querySelectorAll('lit-select-option').forEach(a => { 343 a.setAttribute('check', ''); 344 a.addEventListener('onSelected', (e: any) => { 345 if (a.hasAttribute("selected")) { 346 let number = this.showItems.indexOf(a.textContent!); 347 if (number > -1) { 348 this.showItems!.splice(number, 1); 349 this.inputElement!.value = this.showItems; 350 } 351 this.all = false 352 querySelector.removeAttribute("selected"); 353 a.removeAttribute("selected"); 354 return; 355 } else { 356 let index = this.itemValue.indexOf(a.textContent!); 357 let value = this.showItems.indexOf(a.textContent!); 358 if (index > -1 && value == -1) { 359 this.showItems.push(a.textContent!); 360 this.inputElement!.value = this.showItems; 361 } 362 if (this.showItems.length >= this.itemValue.length) { 363 querySelector.setAttribute('selected', '') 364 this.all = true; 365 } else { 366 querySelector.removeAttribute('selected') 367 this.all = false; 368 } 369 a.setAttribute('selected', '') 370 } 371 }) 372 }) 373 this.selectAll(querySelector); 374 } 375 376 377 initOptions() { 378 this.options!.addEventListener('click', ev => { 379 let items = this.inputElement!.value.split(","); 380 this.customItem = [] 381 items.forEach((item: string) => { 382 if (item.trim() != "") { 383 let indexItem = this.itemValue.indexOf(item.trim()); 384 if (indexItem == -1) { 385 this.customItem.push(item.trim()) 386 } 387 } 388 }); 389 if (this.customItem.length > 0) { 390 this.inputElement.value = this.customItem.concat(this.showItems); 391 } else { 392 this.inputElement.value = this.showItems 393 } 394 }) 395 this.shadowRoot?.querySelectorAll('lit-select-option').forEach(a => { 396 a.setAttribute('check', ''); 397 a.addEventListener('onSelected', (e: any) => { 398 if (a.hasAttribute("selected")) { 399 let number = this.showItems.indexOf(a.textContent!); 400 if (number > -1) { 401 this.showItems.splice(number, 1) 402 } 403 a.removeAttribute("selected"); 404 return; 405 } else { 406 let index = this.itemValue.indexOf(a.textContent!); 407 if (index > -1) { 408 this.showItems.push(a.textContent!); 409 } 410 a.setAttribute('selected', '') 411 } 412 }) 413 }) 414 } 415 416 selectAll(querySelector: LitSelectOption) { 417 querySelector?.addEventListener("click", ev => { 418 if (querySelector.hasAttribute("selected")) { 419 this.shadowRoot?.querySelectorAll('lit-select-option').forEach(a => { 420 a.setAttribute('selected', ''); 421 this.all = true 422 }) 423 this.itemValue.forEach(i => { 424 this.showItems.push(i) 425 }) 426 this.inputElement.value = this.itemValue; 427 } else { 428 this.shadowRoot?.querySelectorAll('lit-select-option').forEach(i => { 429 i.removeAttribute('selected'); 430 this.all = false 431 }) 432 this.showItems = []; 433 this.inputElement.value = ""; 434 } 435 }) 436 } 437 438 attributeChangedCallback(name: any, oldValue: any, newValue: any) { 439 } 440 441} 442