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 { LitTableColumn } from './lit-table-column'; 17import { LitProgressBar } from './../progress-bar/LitProgressBar'; 18import { BaseElement, element } from '../BaseElement'; 19import '../utils/Template'; 20import { TableRowObject } from './TableRowObject'; 21import { 22 addCopyEventListener, 23 addSelectAllBox, 24 createDownUpSvg, 25 exportData, 26 fixed, 27 formatExportData, 28 formatName, 29 iconPadding, 30 iconWidth, 31 litPageTableHtml, 32} from './LitTableHtml'; 33import { LitIcon } from '../icon/LitIcon'; 34 35@element('lit-page-table') 36export class LitPageTable extends BaseElement { 37 meauseRowElement: HTMLDivElement | undefined; 38 currentRecycleList: HTMLDivElement[] = []; 39 currentTreeDivList: HTMLDivElement[] = []; 40 public rememberScrollTop = false; 41 public getItemTextColor?: (data: unknown) => string; 42 public itemTextHandleMap: Map<string, (value: unknown) => string> = new Map<string, (value: unknown) => string>(); 43 public exportLoading: boolean = false; 44 public exportTextHandleMap: Map<string, (value: unknown) => string> = new Map<string, (value: unknown) => string>(); 45 public ds: Array<unknown> = []; 46 public recycleDs: Array<unknown> = []; 47 public tableColumns: NodeListOf<LitTableColumn> | undefined; 48 public tableElement: HTMLDivElement | null | undefined; 49 public columns: Array<Element> | null | undefined; 50 public exportProgress: LitProgressBar | null | undefined; 51 private gridTemplateColumns: Array<string> = []; 52 private st: HTMLSlotElement | null | undefined; 53 private theadElement: HTMLDivElement | null | undefined; 54 private tbodyElement: HTMLDivElement | undefined | null; 55 private treeElement: HTMLDivElement | undefined | null; 56 private previousDiv: HTMLDivElement | undefined | null; 57 private nextDiv: HTMLDivElement | undefined | null; 58 private currentPageDiv: HTMLDivElement | undefined | null; 59 private targetPageInput: HTMLInputElement | undefined | null; 60 private jumpDiv: HTMLDivElement | undefined | null; 61 private colCount: number = 0; 62 private isScrollXOutSide: boolean = false; 63 private currentPage: number = 0; 64 startSkip: number = 0; 65 66 static get observedAttributes(): string[] { 67 return [ 68 'scroll-y', 69 'selectable', 70 'no-head', 71 'grid-line', 72 'defaultOrderColumn', 73 'hideDownload', 74 'loading', 75 'pagination', 76 ]; 77 } 78 79 set loading(value: boolean) { 80 this.exportProgress!.loading = value; 81 } 82 83 get hideDownload(): boolean { 84 return this.hasAttribute('hideDownload'); 85 } 86 87 set hideDownload(value) { 88 if (value) { 89 this.setAttribute('hideDownload', ''); 90 } else { 91 this.removeAttribute('hideDownload'); 92 } 93 } 94 95 get selectable(): boolean { 96 return this.hasAttribute('selectable'); 97 } 98 99 set selectable(value) { 100 if (value) { 101 this.setAttribute('selectable', ''); 102 } else { 103 this.removeAttribute('selectable'); 104 } 105 } 106 107 get scrollY(): string { 108 return this.getAttribute('scroll-y') || 'auto'; 109 } 110 111 set scrollY(value) { 112 this.setAttribute('scroll-y', value); 113 } 114 get recycleDataSource(): unknown[] { 115 return this.ds || []; 116 } 117 118 set recycleDataSource(value) { 119 this.isScrollXOutSide = this.tableElement!.scrollWidth > this.tableElement!.clientWidth; 120 this.ds = value; 121 this.toTop(); 122 this.currentPage = 0; 123 this.pagination = value.length > 0 && Array.isArray(value[0]); 124 if (this.pagination) { 125 this.currentPageDiv!.textContent = `第 ${this.currentPage + 1} 页,共 ${this.ds.length} 页`; 126 this.targetPageInput!.value = ''; 127 } 128 if (this.hasAttribute('tree')) { 129 this.recycleDs = this.meauseTreeRowElement(value); 130 } else { 131 // @ts-ignore 132 this.recycleDs = this.meauseAllRowHeight(this.pagination ? value[0] : value); 133 } 134 } 135 136 set pagination(value: boolean) { 137 if (value) { 138 this.setAttribute('pagination', ''); 139 } else { 140 this.removeAttribute('pagination'); 141 } 142 } 143 144 get pagination(): boolean { 145 return this.hasAttribute('pagination'); 146 } 147 148 initElements(): void { 149 this.tableElement = this.shadowRoot?.querySelector('.table'); 150 this.st = this.shadowRoot?.querySelector('#slot'); 151 this.theadElement = this.shadowRoot?.querySelector('.thead'); 152 this.exportProgress = this.shadowRoot?.querySelector('#export_progress_bar'); 153 this.treeElement = this.shadowRoot?.querySelector('.tree'); 154 this.tbodyElement = this.shadowRoot?.querySelector('.body'); 155 this.tableColumns = this.querySelectorAll<LitTableColumn>('lit-table-column'); 156 this.previousDiv = this.shadowRoot?.querySelector<HTMLDivElement>('#previousPage'); 157 this.nextDiv = this.shadowRoot?.querySelector<HTMLDivElement>('#nextPage'); 158 this.currentPageDiv = this.shadowRoot?.querySelector<HTMLDivElement>('#currentPage'); 159 this.targetPageInput = this.shadowRoot?.querySelector<HTMLInputElement>('#targetPage'); 160 this.jumpDiv = this.shadowRoot?.querySelector<HTMLDivElement>('#jumpPage'); 161 this.initPageEventListener(); 162 this.targetPageInput!.addEventListener('input', ()=>{ 163 let maxPage = this.ds.length!; 164 this.targetPageInput!.max = String(maxPage); 165 let currentValue = parseInt(this.targetPageInput!.value, 10); 166 let max = parseInt(this.targetPageInput!.max, 10); 167 if (currentValue > max) { 168 this.targetPageInput!.value = String(max); 169 } 170 }); 171 } 172 173 initPageEventListener(): void { 174 this.previousDiv!.onclick = (): void => { 175 if (this.currentPage > 0) { 176 this.currentPage = Math.max(this.currentPage - 1, 0); 177 this.showCurrentPageData(); 178 } 179 }; 180 this.nextDiv!.onclick = (): void => { 181 if (this.currentPage < this.ds.length - 1) { 182 this.currentPage = Math.min(this.currentPage + 1, this.ds.length - 1); 183 this.showCurrentPageData(); 184 } 185 }; 186 this.jumpDiv!.onclick = (): void => { 187 let value = this.targetPageInput!.value; 188 let reg = /^[0-9]*$/; 189 if (value.length > 0 && reg.test(value)) { 190 let target = parseInt(value); 191 if (target < 1) { 192 target = 1; 193 } 194 if (target > this.ds.length) { 195 target = this.ds.length; 196 } 197 this.targetPageInput!.value = `${target}`; 198 if (this.currentPage !== target - 1) { 199 this.currentPage = target - 1; 200 this.showCurrentPageData(); 201 } 202 } else { 203 this.targetPageInput!.value = ''; 204 } 205 }; 206 } 207 208 toTop(): void { 209 if (this.rememberScrollTop) { 210 this.tableElement!.scrollTop = 0; 211 this.tableElement!.scrollLeft = 0; 212 } else { 213 this.tableElement!.scrollTop = 0; 214 } 215 } 216 217 showCurrentPageData(): void { 218 this.toTop(); 219 this.currentPageDiv!.textContent = `第 ${(this.currentPage || 0) + 1} 页,共 ${this.ds.length} 页`; 220 if (this.hasAttribute('tree')) { 221 // @ts-ignore 222 this.recycleDs = this.meauseTreeRowElement(this.ds[this.currentPage]); 223 } else { 224 // @ts-ignore 225 this.recycleDs = this.meauseAllRowHeight(this.ds[this.currentPage]); 226 } 227 } 228 229 initHtml(): string { 230 return litPageTableHtml; 231 } 232 233 dataExportInit(): void { 234 let exportDiv = this.shadowRoot!.querySelector<HTMLDivElement>('.export'); 235 exportDiv && 236 (exportDiv.onclick = (): void => { 237 this.exportData(); 238 }); 239 } 240 241 exportData(): void { 242 exportData(this); 243 } 244 245 formatExportData(dataSource: unknown[]): unknown[] { 246 return formatExportData(dataSource, this); 247 } 248 249 //当 custom element首次被插入文档DOM时,被调用。 250 connectedCallback(): void { 251 this.dataExportInit(); 252 addCopyEventListener(this); 253 this.colCount = this.tableColumns!.length; 254 this.st?.addEventListener('slotchange', () => { 255 this.theadElement!.innerHTML = ''; 256 setTimeout(() => { 257 this.columns = this.st!.assignedElements(); 258 let rowElement = document.createElement('div'); 259 rowElement.classList.add('th'); 260 this.gridTemplateColumns = []; 261 let pageArea: Array<unknown> = []; 262 addSelectAllBox(rowElement, this); 263 this.resolvingArea(this.columns, 0, 0, pageArea, rowElement); 264 pageArea.forEach((rows, j, array) => { 265 for (let i = 0; i < this.colCount; i++) { 266 // @ts-ignore 267 if (!rows[i]) { 268 // @ts-ignore 269 rows[i] = array[j - 1][i]; 270 } 271 } 272 }); 273 if (this.selectable) { 274 // @ts-ignore 275 let s = pageArea.map((a) => '"_checkbox_ ' + a.map((aa: unknown) => aa.t).join(' ') + '"').join(' '); 276 rowElement.style.gridTemplateColumns = '60px ' + this.gridTemplateColumns.join(' '); 277 rowElement.style.gridTemplateRows = `repeat(${pageArea.length},1fr)`; 278 rowElement.style.gridTemplateAreas = s; 279 } else { 280 // @ts-ignore 281 let s = pageArea.map((a) => '"' + a.map((aa: unknown) => aa.t).join(' ') + '"').join(' '); 282 rowElement.style.gridTemplateColumns = this.gridTemplateColumns.join(' '); 283 rowElement.style.gridTemplateRows = `repeat(${pageArea.length},1fr)`; 284 rowElement.style.gridTemplateAreas = s; 285 } 286 this.theadElement!.innerHTML = ''; 287 this.theadElement!.append(rowElement); 288 this.treeElement!.style.top = this.theadElement?.clientHeight + 'px'; 289 }); 290 }); 291 this.shadowRoot!.addEventListener('load', function (event) {}); 292 this.tableElement!.addEventListener('mouseout', (ev) => this.mouseOut()); 293 } 294 295 resolvingArea(columns: unknown, x: unknown, y: unknown, area: Array<unknown>, rowElement: HTMLDivElement): void { 296 // @ts-ignore 297 columns.forEach((a: unknown, i: unknown) => { 298 // @ts-ignore 299 if (!area[y]) { 300 // @ts-ignore 301 area[y] = []; 302 } // @ts-ignore 303 let key = a.getAttribute('key') || a.getAttribute('title'); // @ts-ignore 304 if (a.tagName === 'LIT-TABLE-GROUP') { 305 // @ts-ignore 306 let childList = [...a.children].filter((a) => a.tagName !== 'TEMPLATE'); // @ts-ignore 307 let len = a.querySelectorAll('lit-table-column').length; 308 if (childList.length > 0) { 309 // @ts-ignore 310 this.resolvingArea(childList, x, y + 1, area, rowElement); 311 } 312 for (let j = 0; j < len; j++) { 313 // @ts-ignore 314 area[y][x] = { x, y, t: key }; // @ts-ignore 315 x++; 316 } 317 let head = document.createElement('div'); 318 head.classList.add('td'); // @ts-ignore 319 head.style.justifyContent = a.getAttribute('align'); 320 head.style.borderBottom = '1px solid #f0f0f0'; 321 head.style.gridArea = key; // @ts-ignore 322 head.innerText = a.title; // @ts-ignore 323 if (a.hasAttribute('fixed')) { 324 // @ts-ignore 325 fixed(head, a.getAttribute('fixed'), '#42b983'); 326 } 327 rowElement.append(head); // @ts-ignore 328 } else if (a.tagName === 'LIT-TABLE-COLUMN') { 329 // @ts-ignore 330 area[y][x] = { x, y, t: key }; // @ts-ignore 331 x++; 332 let h: unknown = document.createElement('div'); // @ts-ignore 333 h.classList.add('td'); // @ts-ignore 334 if (i > 0) { 335 let resizeDiv: HTMLDivElement = document.createElement('div'); 336 resizeDiv.classList.add('resize'); // @ts-ignore 337 h.appendChild(resizeDiv); // @ts-ignore 338 this.resizeEventHandler(rowElement, resizeDiv, i); 339 } // @ts-ignore 340 this.resolvingAreaColumnOrder(a, i, key, h); // @ts-ignore 341 h.style.justifyContent = a.getAttribute('align'); // @ts-ignore 342 this.gridTemplateColumns.push(a.getAttribute('width') || '1fr'); // @ts-ignore 343 h.style.gridArea = key; 344 let titleLabel = document.createElement('label'); // @ts-ignore 345 titleLabel.textContent = a.title; // @ts-ignore 346 h.appendChild(titleLabel); // @ts-ignore 347 if (a.hasAttribute('fixed')) { 348 // @ts-ignore 349 fixed(h, a.getAttribute('fixed'), '#42b983'); 350 } // @ts-ignore 351 rowElement.append(h); 352 } 353 }); 354 } 355 356 resolvingAreaColumnOrder(column: unknown, index: number, key: string, head: unknown): void { 357 // @ts-ignore 358 if (column.hasAttribute('order')) { 359 // @ts-ignore 360 (head as unknown).sortType = 0; // @ts-ignore 361 head.classList.add('td-order'); // @ts-ignore 362 head.style.position = 'relative'; 363 let { upSvg, downSvg } = createDownUpSvg(index, head); // @ts-ignore 364 head.onclick = (): void => { 365 if (this.isResize || this.resizeColumnIndex !== -1) { 366 return; 367 } 368 this?.shadowRoot?.querySelectorAll('.td-order svg').forEach((it: unknown) => { 369 // @ts-ignore 370 it.setAttribute('fill', 'let(--dark-color1,#212121)'); // @ts-ignore 371 it.sortType = 0; // @ts-ignore 372 it.style.display = 'none'; 373 }); // @ts-ignore 374 if (head.sortType === undefined || head.sortType === null) { 375 // @ts-ignore 376 head.sortType = 0; // @ts-ignore 377 } else if (head.sortType === 2) { 378 // @ts-ignore 379 head.sortType = 0; 380 } else { 381 // @ts-ignore 382 head.sortType += 1; 383 } 384 upSvg.setAttribute('fill', 'let(--dark-color1,#212121)'); 385 downSvg.setAttribute('fill', 'let(--dark-color1,#212121)'); // @ts-ignore 386 upSvg.style.display = head.sortType === 1 ? 'block' : 'none'; // @ts-ignore 387 downSvg.style.display = head.sortType === 2 ? 'block' : 'none'; // @ts-ignore 388 switch (head.sortType) { 389 case 1: 390 this.theadElement!.setAttribute('sort', ''); 391 break; 392 case 2: 393 break; 394 default: 395 this.theadElement!.removeAttribute('sort'); 396 break; 397 } 398 this.dispatchEvent( 399 new CustomEvent('column-click', { 400 detail: { 401 // @ts-ignore 402 sort: head.sortType, 403 key: key, 404 }, 405 composed: true, 406 }) 407 ); 408 }; 409 } 410 } 411 412 private isResize: boolean = false; 413 private resizeColumnIndex: number = -1; 414 private resizeDownX: number = 0; 415 private columnMinWidth: number = 50; 416 private beforeResizeWidth: number = 0; 417 418 resizeMouseMoveEventHandler(header: HTMLDivElement): void { 419 header.addEventListener('mousemove', (event) => { 420 if (this.isResize) { 421 header.style.cursor = 'col-resize'; 422 let width = event.clientX - this.resizeDownX; 423 let prePageWidth = Math.max(this.beforeResizeWidth + width, this.columnMinWidth); 424 for (let i = 0; i < header.childNodes.length; i++) { 425 let node = header.childNodes.item(i) as HTMLDivElement; 426 this.gridTemplateColumns[i] = `${node.clientWidth}px`; 427 } 428 this.gridTemplateColumns[this.resizeColumnIndex - 1] = `${prePageWidth}px`; 429 let lastNode = header.childNodes.item(header.childNodes.length - 1) as HTMLDivElement; 430 let totalWidth = 0; 431 this.gridTemplateColumns.forEach((it) => { 432 totalWidth += parseInt(it); 433 }); 434 totalWidth = Math.max(totalWidth, this.shadowRoot!.querySelector<HTMLDivElement>('.table')!.scrollWidth); 435 this.gridTemplateColumns[this.gridTemplateColumns.length - 1] = `${totalWidth - lastNode.offsetLeft - 1}px`; 436 header.style.gridTemplateColumns = this.gridTemplateColumns.join(' '); 437 let preNode = header.childNodes.item(this.resizeColumnIndex - 1) as HTMLDivElement; 438 preNode.style.width = `${prePageWidth}px`; 439 this.shadowRoot!.querySelectorAll<HTMLDivElement>('.tr').forEach((tr) => { 440 tr.style.gridTemplateColumns = this.gridTemplateColumns.join(' '); 441 }); 442 event.preventDefault(); 443 event.stopPropagation(); 444 } else { 445 header.style.cursor = 'pointer'; 446 } 447 }); 448 } 449 450 resizeEventHandler(header: HTMLDivElement, element: HTMLDivElement, index: number): void { 451 this.resizeMouseMoveEventHandler(header); 452 header.addEventListener('mouseup', (event) => { 453 this.resizeDownX = 0; 454 this.isResize = false; 455 header.style.cursor = 'pointer'; 456 setTimeout(() => { 457 this.resizeColumnIndex = -1; 458 }, 100); 459 event.stopPropagation(); 460 event.preventDefault(); 461 }); 462 header.addEventListener('mouseleave', (event) => { 463 event.stopPropagation(); 464 event.preventDefault(); 465 this.isResize = false; 466 this.resizeDownX = 0; 467 this.resizeColumnIndex = -1; 468 header.style.cursor = 'pointer'; 469 }); 470 element.addEventListener('mousedown', (event) => { 471 if (event.button === 0) { 472 this.resizeColumnIndex = index; 473 this.isResize = true; 474 this.resizeDownX = event.clientX; 475 let pre = header.childNodes.item(this.resizeColumnIndex - 1) as HTMLDivElement; 476 this.beforeResizeWidth = pre.clientWidth; 477 event.stopPropagation(); 478 } 479 }); 480 element.addEventListener('click', (event) => { 481 event.stopPropagation(); 482 }); 483 } 484 485 // Is called when the custom element is removed from the document DOM. 486 disconnectedCallback(): void {} 487 488 // It is called when the custom element is moved to a new document. 489 adoptedCallback(): void {} 490 491 // It is called when a custom element adds, deletes, or modifies its own properties. 492 attributeChangedCallback(name: string, oldValue: string, newValue: string): void {} 493 494 meauseElementHeight(rowData: unknown): number { 495 return 27; 496 } 497 498 meauseTreeElementHeight(rowData: unknown, depth: number): number { 499 return 27; 500 } 501 502 meauseAllRowHeight(list: unknown[]): TableRowObject[] { 503 this.tbodyElement!.innerHTML = ''; 504 this.meauseRowElement = undefined; 505 this.startSkip = 0; 506 let head = this.shadowRoot!.querySelector('.th'); 507 this.tbodyElement && (this.tbodyElement.style.width = head?.clientWidth + 'px'); 508 this.currentRecycleList = []; 509 let headHeight = 0; 510 let totalHeight = headHeight; 511 let visibleObjects: TableRowObject[] = []; 512 let itemHandler = (rowData: unknown, index: number): void => { 513 let height = this.meauseElementHeight(rowData); 514 let tableRowObject = new TableRowObject(); 515 tableRowObject.height = height; 516 tableRowObject.top = totalHeight; 517 tableRowObject.data = rowData; 518 tableRowObject.rowIndex = index; 519 if ( 520 Math.max(totalHeight, this.tableElement!.scrollTop + headHeight) <= 521 Math.min(totalHeight + height, this.tableElement!.scrollTop + this.tableElement!.clientHeight + headHeight) 522 ) { 523 let newTableElement = this.createNewTableElement(tableRowObject); 524 newTableElement.style.transform = `translateY(${totalHeight}px)`; 525 this.tbodyElement?.append(newTableElement); 526 this.currentRecycleList.push(newTableElement); 527 } 528 totalHeight += height; 529 visibleObjects.push(tableRowObject); 530 }; 531 let realIndex = 0; 532 list.forEach((item, index) => { 533 if (Array.isArray(item)) { 534 item.forEach((rowData, childIndex) => { 535 itemHandler(rowData, realIndex); 536 realIndex++; 537 }); 538 } else { 539 itemHandler(item, index); 540 } 541 }); 542 this.tbodyElement && (this.tbodyElement.style.height = totalHeight + (this.isScrollXOutSide ? 0 : 0) + 'px'); 543 this.addOnScrollListener(visibleObjects); 544 return visibleObjects; 545 } 546 547 addOnScrollListener(visibleObjList: TableRowObject[]): void { 548 this.tableElement && 549 (this.tableElement.onscroll = (event): void => { 550 let tblScrollTop = this.tableElement!.scrollTop; 551 let skip = 0; 552 for (let i = 0; i < visibleObjList.length; i++) { 553 if ( 554 visibleObjList[i].top <= tblScrollTop && 555 visibleObjList[i].top + visibleObjList[i].height >= tblScrollTop 556 ) { 557 skip = i; 558 break; 559 } 560 } 561 let reduce = this.currentRecycleList.map((item) => item.clientHeight).reduce((a, b) => a + b, 0); 562 if (reduce === 0) { 563 return; 564 } 565 while ( 566 reduce <= this.tableElement!.clientHeight && 567 this.currentRecycleList.length + skip < visibleObjList.length 568 ) { 569 let newTableElement = this.createNewTableElement(visibleObjList[skip]); 570 this.tbodyElement?.append(newTableElement); 571 this.currentRecycleList.push(newTableElement); 572 reduce += newTableElement.clientHeight; 573 } 574 this.startSkip = skip; 575 for (let i = 0; i < this.currentRecycleList.length; i++) { 576 this.freshCurrentLine(this.currentRecycleList[i], visibleObjList[i + skip]); 577 } 578 }); 579 } 580 581 measureReset(): void { 582 this.meauseRowElement = undefined; 583 this.tbodyElement!.innerHTML = ''; 584 this.treeElement!.innerHTML = ''; 585 this.currentRecycleList = []; 586 this.currentTreeDivList = []; 587 } 588 589 meauseTreeRowElement(list: unknown[]): TableRowObject[] { 590 this.measureReset(); 591 let headHeight = this.theadElement?.clientHeight || 0; 592 let totalHeight = 0; 593 let visibleObjects: TableRowObject[] = []; 594 let resetAllHeight = (list: unknown[], depth: number, parentNode?: TableRowObject): void => { 595 list.forEach((item) => { 596 let tableRowObject = new TableRowObject(); 597 tableRowObject.depth = depth; 598 tableRowObject.data = item; 599 tableRowObject.top = totalHeight; 600 tableRowObject.height = this.meauseTreeElementHeight(tableRowObject, depth); 601 if (parentNode !== undefined) { 602 parentNode.children.push(tableRowObject); 603 } 604 let maxHeight = Math.max(totalHeight, this.tableElement!.scrollTop); 605 let minHeight = Math.min( 606 totalHeight + tableRowObject.height, 607 this.tableElement!.scrollTop + this.tableElement!.clientHeight - headHeight 608 ); 609 if (maxHeight <= minHeight) { 610 let newTableElement = this.createNewTreeTableElement(tableRowObject); // @ts-ignore 611 newTableElement.style.transform = `translateY(${totalHeight}px)`; // @ts-ignore 612 this.tbodyElement?.append(newTableElement); 613 if (this.treeElement?.lastChild) { 614 (this.treeElement?.lastChild as HTMLElement).style.height = tableRowObject.height + 'px'; 615 } // @ts-ignore 616 this.currentRecycleList.push(newTableElement); 617 } 618 totalHeight += tableRowObject.height; 619 visibleObjects.push(tableRowObject); // @ts-ignore 620 if (item.hasNext) { 621 // @ts-ignore 622 if (item.parents !== undefined && item.parents.length > 0 && item.status) { 623 // @ts-ignore 624 resetAllHeight(item.parents, depth + 1, tableRowObject); // @ts-ignore 625 } else if (item.children !== undefined && item.children.length > 0 && item.status) { 626 // @ts-ignore 627 resetAllHeight(item.children, depth + 1, tableRowObject); 628 } 629 } else { 630 // @ts-ignore 631 if (item.children !== undefined && item.children.length > 0) { 632 // @ts-ignore 633 resetAllHeight(item.children, depth + 1, tableRowObject); 634 } 635 } 636 }); 637 }; 638 resetAllHeight(list, 0); 639 this.tbodyElement && (this.tbodyElement.style.height = totalHeight + 'px'); 640 this.treeElement!.style.height = this.tableElement!.clientHeight - this.theadElement!.clientHeight + 'px'; 641 this.addTreeRowScrollListener(); 642 return visibleObjects; 643 } 644 645 addTreeRowScrollListener(): void { 646 this.tableElement && 647 (this.tableElement.onscroll = (event): void => { 648 let visibleObjs = this.recycleDs.filter((item) => { 649 // @ts-ignore 650 return !item.rowHidden; 651 }); 652 let top = this.tableElement!.scrollTop; 653 this.treeElement!.style.transform = `translateY(${top}px)`; 654 let skip = 0; 655 for (let index = 0; index < visibleObjs.length; index++) { 656 // @ts-ignore 657 if (visibleObjs[index].top <= top && visibleObjs[index].top + visibleObjs[index].height >= top) { 658 skip = index; 659 break; 660 } 661 } 662 let reduce = this.currentRecycleList.map((item) => item.clientHeight).reduce((a, b) => a + b, 0); 663 if (reduce === 0) { 664 return; 665 } 666 while (reduce <= this.tableElement!.clientHeight) { 667 // @ts-ignore 668 let newTableElement = this.createNewTreeTableElement(visibleObjs[skip]); // @ts-ignore 669 this.tbodyElement?.append(newTableElement); 670 if (this.treeElement?.lastChild) { 671 // @ts-ignore 672 (this.treeElement?.lastChild as HTMLElement).style.height = visibleObjs[skip].height + 'px'; 673 } // @ts-ignore 674 this.currentRecycleList.push(newTableElement); // @ts-ignore 675 reduce += newTableElement.clientHeight; 676 } 677 for (let i = 0; i < this.currentRecycleList.length; i++) { 678 this.freshCurrentLine( 679 this.currentRecycleList[i], // @ts-ignore 680 visibleObjs[i + skip], 681 this.treeElement?.children[i] as HTMLElement 682 ); 683 } 684 }); 685 } 686 687 createNewTreeTableElement(rowData: TableRowObject): unknown { 688 let newTableElement = document.createElement('div'); 689 newTableElement.classList.add('tr'); 690 let treeTop = 0; 691 if (this.treeElement!.children?.length > 0) { 692 let transX = Number((this.treeElement?.lastChild as HTMLElement).style.transform.replace(/[^0-9]/gi, '')); 693 treeTop += transX + rowData.height; 694 } 695 this?.columns?.forEach((column: unknown, index) => { 696 // @ts-ignore 697 let dataIndex = column.getAttribute('data-index') || '1'; 698 let td: unknown; 699 if (index === 0) { 700 td = this.firstElementTdHandler(newTableElement, dataIndex, rowData, column); 701 } else { 702 td = this.otherElementHandler(dataIndex, rowData, column); // @ts-ignore 703 newTableElement.append(td); 704 } 705 }); 706 let lastChild = this.treeElement?.lastChild as HTMLElement; 707 if (lastChild) { 708 lastChild.style.transform = `translateY(${treeTop}px)`; 709 } // @ts-ignore 710 (newTableElement as unknown).data = rowData.data; 711 newTableElement.style.gridTemplateColumns = this.gridTemplateColumns.join(' '); 712 newTableElement.style.position = 'absolute'; 713 newTableElement.style.top = '0px'; 714 newTableElement.style.left = '0px'; 715 newTableElement.style.cursor = 'pointer'; //@ts-ignore 716 this.setHighLight(rowData.data.isSearch, newTableElement); 717 this.addRowElementEvent(newTableElement, rowData); 718 return newTableElement; 719 } 720 721 addRowElementEvent(newTableElement: HTMLDivElement, rowData: unknown): void { 722 newTableElement.onmouseenter = (): void => { 723 // @ts-ignore 724 if ((newTableElement as unknown).data.isSelected) { 725 return; 726 } 727 let indexOf = this.currentRecycleList.indexOf(newTableElement); 728 this.currentTreeDivList.forEach((row) => { 729 row.classList.remove('mouse-in'); 730 }); 731 if (indexOf >= 0 && indexOf < this.treeElement!.children.length) { 732 this.setMouseIn(true, [this.treeElement?.children[indexOf] as HTMLElement]); 733 } 734 }; 735 newTableElement.onmouseleave = (): void => { 736 // @ts-ignore 737 if ((newTableElement as unknown).data.isSelected) { 738 return; 739 } 740 let indexOf = this.currentRecycleList.indexOf(newTableElement); 741 if (indexOf >= 0 && indexOf < this.treeElement!.children.length) { 742 this.setMouseIn(false, [this.treeElement?.children[indexOf] as HTMLElement]); 743 } 744 }; 745 newTableElement.onclick = (e): void => { 746 let indexOf = this.currentRecycleList.indexOf(newTableElement); 747 this.dispatchRowClickEvent(rowData, [this.treeElement?.children[indexOf] as HTMLElement, newTableElement]); 748 }; 749 } 750 751 firstElementTdHandler( 752 newTableElement: HTMLDivElement, 753 dataIndex: string, 754 rowData: unknown, 755 column: unknown 756 ): HTMLDivElement { 757 let td: unknown; // @ts-ignore 758 let text = formatName(dataIndex, rowData.data[dataIndex], this); // @ts-ignore 759 if (column.template) { 760 // @ts-ignore 761 td = column.template.render(rowData.data).content.cloneNode(true); // @ts-ignore 762 td.template = column.template; // @ts-ignore 763 td.title = text; 764 } else { 765 td = document.createElement('div'); // @ts-ignore 766 td.innerHTML = text; // @ts-ignore 767 td.dataIndex = dataIndex; // @ts-ignore 768 td.title = text; 769 } // @ts-ignore 770 if (rowData.data.children && rowData.data.children.length > 0 && !rowData.data.hasNext) { 771 let btn = this.createExpandBtn(rowData); // @ts-ignore 772 td.insertBefore(btn, td.firstChild); 773 } // @ts-ignore 774 if (rowData.data.hasNext) { 775 // @ts-ignore 776 td.title = rowData.data.objectName; 777 let btn = this.createBtn(rowData); // @ts-ignore 778 td.insertBefore(btn, td.firstChild); 779 } // @ts-ignore 780 td.style.paddingLeft = rowData.depth * iconWidth + 'px'; // @ts-ignore 781 if (!rowData.data.children || rowData.data.children.length === 0) { 782 // @ts-ignore 783 td.style.paddingLeft = iconWidth * rowData.depth + iconWidth + iconPadding * 2 + 'px'; 784 } // @ts-ignore 785 (td as unknown).data = rowData.data; // @ts-ignore 786 td.classList.add('tree-first-body'); // @ts-ignore 787 td.style.position = 'absolute'; // @ts-ignore 788 td.style.top = '0px'; // @ts-ignore 789 td.style.left = '0px'; // @ts-ignore 790 this.addFirstElementEvent(td, newTableElement, rowData); // @ts-ignore 791 this.setHighLight(rowData.data.isSearch, td); // @ts-ignore 792 this.treeElement!.style.width = column.getAttribute('width'); // @ts-ignore 793 this.treeElement?.append(td); // @ts-ignore 794 this.currentTreeDivList.push(td); // @ts-ignore 795 return td; 796 } 797 798 addFirstElementEvent(td: HTMLDivElement, tr: HTMLDivElement, rowData: unknown): void { 799 td.onmouseenter = (): void => { 800 let indexOf = this.currentTreeDivList.indexOf(td); 801 this.currentRecycleList.forEach((row) => { 802 row.classList.remove('mouse-in'); 803 }); 804 if (indexOf >= 0 && indexOf < this.currentRecycleList.length && td.innerHTML !== '') { 805 this.setMouseIn(true, [td]); 806 } 807 }; 808 td.onmouseleave = (): void => { 809 let indexOf = this.currentTreeDivList.indexOf(td); 810 if (indexOf >= 0 && indexOf < this.currentRecycleList.length) { 811 this.setMouseIn(false, [td]); 812 } 813 }; 814 td.onclick = (): void => { 815 let indexOf = this.currentTreeDivList.indexOf(td); 816 this.dispatchRowClickEvent(rowData, [td, tr]); 817 }; 818 } 819 820 otherElementHandler(dataIndex: string, rowData: unknown, column: unknown): HTMLDivElement { 821 // @ts-ignore 822 let text = formatName(dataIndex, rowData.data[dataIndex], this); 823 let td: unknown = document.createElement('div'); 824 td = document.createElement('div'); // @ts-ignore 825 td.classList.add('td'); // @ts-ignore 826 td.style.overflow = 'hidden'; // @ts-ignore 827 td.style.textOverflow = 'ellipsis'; // @ts-ignore 828 td.style.whiteSpace = 'nowrap'; // @ts-ignore 829 td.title = text; // @ts-ignore 830 td.dataIndex = dataIndex; // @ts-ignore 831 td.style.justifyContent = column.getAttribute('align') || 'flex-start'; // @ts-ignore 832 if (column.template) { 833 // @ts-ignore 834 td.appendChild(column.template.render(rowData.data).content.cloneNode(true)); // @ts-ignore 835 td.template = column.template; 836 } else { 837 // @ts-ignore 838 td.innerHTML = text; 839 } // @ts-ignore 840 return td; 841 } 842 843 createBtn(row: unknown): unknown { 844 let btn: unknown = document.createElement('lit-icon'); // @ts-ignore 845 btn.classList.add('tree-icon'); // @ts-ignore 846 if (row.data.expanded) { 847 // @ts-ignore 848 btn.name = 'plus-square'; 849 } else { 850 // @ts-ignore 851 btn.name = 'minus-square'; 852 } // @ts-ignore 853 btn.addEventListener('click', (e: unknown) => { 854 // @ts-ignore 855 row.data.status = false; 856 const resetNodeHidden = (hidden: boolean, rowData: unknown): void => { 857 if (hidden) { 858 // @ts-ignore 859 rowData.children.forEach((child: unknown) => { 860 // @ts-ignore 861 child.rowHidden = false; 862 }); 863 } else { 864 // @ts-ignore 865 rowData.children.forEach((child: unknown) => { 866 // @ts-ignore 867 child.rowHidden = true; 868 resetNodeHidden(hidden, child); 869 }); 870 } 871 }; 872 // @ts-ignore 873 if (row.data.expanded) { 874 // @ts-ignore 875 row.data.status = true; 876 this.dispatchRowClickEventIcon(row, [btn]); // @ts-ignore 877 row.data.expanded = false; 878 resetNodeHidden(true, row); 879 } else { 880 // @ts-ignore 881 row.data.expanded = true; // @ts-ignore 882 row.data.status = false; 883 resetNodeHidden(false, row); 884 } 885 this.reMeauseHeight(); // @ts-ignore 886 e.stopPropagation(); 887 }); 888 return btn; 889 } 890 891 createExpandBtn(row: unknown): LitIcon { 892 let btn: unknown = document.createElement('lit-icon'); // @ts-ignore 893 btn.classList.add('tree-icon'); 894 // @ts-ignore 895 if (row.expanded) { 896 // @ts-ignore 897 btn.name = 'minus-square'; 898 } else { 899 // @ts-ignore 900 btn.name = 'plus-square'; 901 } // @ts-ignore 902 btn.onclick = (e: Event): void => { 903 const resetNodeHidden = (hidden: boolean, rowData: unknown): void => { 904 // @ts-ignore 905 if (rowData.children.length > 0) { 906 if (hidden) { 907 // @ts-ignore 908 rowData.children.forEach((child: unknown) => { 909 // @ts-ignore 910 child.rowHidden = true; 911 resetNodeHidden(hidden, child); 912 }); 913 } else { 914 // @ts-ignore 915 rowData.children.forEach((child: unknown) => { 916 // @ts-ignore 917 child.rowHidden = !rowData.expanded; // @ts-ignore 918 if (rowData.expanded) { 919 resetNodeHidden(hidden, child); 920 } 921 }); 922 } 923 } 924 }; 925 // @ts-ignore 926 if (row.expanded) { 927 // @ts-ignore 928 row.expanded = false; 929 resetNodeHidden(true, row); 930 } else { 931 // @ts-ignore 932 row.expanded = true; 933 resetNodeHidden(false, row); 934 } 935 this.reMeauseHeight(); 936 e.stopPropagation(); 937 }; // @ts-ignore 938 return btn; 939 } 940 941 getVisibleObjs(): { visibleObjs: unknown[]; skip: number; reduce: number } { 942 let totalH = 0; 943 this.recycleDs.forEach((it) => { 944 // @ts-ignore 945 if (!it.rowHidden) { 946 // @ts-ignore 947 it.top = totalH; // @ts-ignore 948 totalH += it.height; 949 } 950 }); 951 this.tbodyElement && (this.tbodyElement.style.height = totalH + (this.isScrollXOutSide ? 0 : 0) + 'px'); 952 this.treeElement!.style.height = this.tableElement!.clientHeight - this.theadElement!.clientHeight + 'px'; 953 let visibleObjs = this.recycleDs.filter((item) => { 954 // @ts-ignore 955 return !item.rowHidden; 956 }); 957 let top = this.tableElement!.scrollTop; 958 let skip = 0; 959 for (let i = 0; i < visibleObjs.length; i++) { 960 // @ts-ignore 961 if (visibleObjs[i].top <= top && visibleObjs[i].top + visibleObjs[i].height >= top) { 962 skip = i; 963 break; 964 } 965 } 966 let reduce = this.currentRecycleList.map((item) => item.clientHeight).reduce((a, b) => a + b, 0); 967 return { visibleObjs, skip, reduce }; 968 } 969 970 reMeauseHeight(): void { 971 if (this.currentRecycleList.length === 0) { 972 return; 973 } 974 let { visibleObjs, skip, reduce } = this.getVisibleObjs(); 975 if (reduce === 0) { 976 return; 977 } 978 while (reduce <= this.tableElement!.clientHeight + 1) { 979 let rowElement; 980 if (this.hasAttribute('tree')) { 981 // @ts-ignore 982 rowElement = this.createNewTreeTableElement(visibleObjs[skip]); 983 } else { 984 rowElement = this.createNewTableElement(visibleObjs[skip]); 985 } // @ts-ignore 986 this.tbodyElement?.append(rowElement); 987 if (this.hasAttribute('tree')) { 988 if (this.treeElement?.lastChild) { 989 // @ts-ignore 990 (this.treeElement?.lastChild as HTMLElement).style.height = visibleObjs[skip].height + 'px'; 991 } 992 } // @ts-ignore 993 this.currentRecycleList.push(rowElement); // @ts-ignore 994 reduce += rowElement.clientHeight; 995 } 996 for (let i = 0; i < this.currentRecycleList.length; i++) { 997 if (this.hasAttribute('tree')) { 998 this.freshCurrentLine( 999 this.currentRecycleList[i], // @ts-ignore 1000 visibleObjs[i + skip], 1001 this.treeElement?.children[i] as HTMLElement 1002 ); 1003 } else { 1004 // @ts-ignore 1005 this.freshCurrentLine(this.currentRecycleList[i], visibleObjs[i + skip]); 1006 } 1007 } 1008 } 1009 1010 createNewTableElement(rowData: unknown): HTMLDivElement { 1011 let rowElement = document.createElement('div'); 1012 rowElement.classList.add('tr'); 1013 this?.columns?.forEach((column: unknown) => { 1014 // @ts-ignore 1015 let dataIndex = column.getAttribute('data-index') || '1'; 1016 let td: unknown; 1017 td = document.createElement('div'); // @ts-ignore 1018 td.classList.add('td'); // @ts-ignore 1019 td.style.overflow = 'hidden'; // @ts-ignore 1020 td.style.textOverflow = 'ellipsis'; // @ts-ignore 1021 td.style.whiteSpace = 'nowrap'; // @ts-ignore 1022 td.dataIndex = dataIndex; // @ts-ignore 1023 td.style.justifyContent = column.getAttribute('align') || 'flex-start'; // @ts-ignore 1024 let text = formatName(dataIndex, rowData.data[dataIndex], this); // @ts-ignore 1025 td.title = text; // @ts-ignore 1026 if (column.template) { 1027 // @ts-ignore 1028 td.appendChild(column.template.render(rowData.data).content.cloneNode(true)); // @ts-ignore 1029 td.template = column.template; 1030 } else { 1031 // @ts-ignore 1032 td.innerHTML = text; 1033 } // @ts-ignore 1034 rowElement.append(td); 1035 }); 1036 rowElement.onclick = (): void => { 1037 this.dispatchRowClickEvent(rowData, [rowElement]); 1038 }; 1039 rowElement.onmouseover = (): void => { 1040 this.dispatchRowHoverEvent(rowData, [rowElement]); 1041 }; // @ts-ignore 1042 if (rowData.data.isSelected !== undefined) { 1043 // @ts-ignore 1044 this.setSelectedRow(rowData.data.isSelected, [rowElement]); 1045 } // @ts-ignore 1046 (rowElement as unknown).data = rowData.data; 1047 rowElement.style.cursor = 'pointer'; 1048 rowElement.style.gridTemplateColumns = this.gridTemplateColumns.join(' '); 1049 rowElement.style.position = 'absolute'; 1050 rowElement.style.top = '0px'; 1051 rowElement.style.left = '0px'; // @ts-ignore 1052 rowElement.style.height = `${rowData.height}px`; 1053 if (this.getItemTextColor) { 1054 // @ts-ignore 1055 rowElement.style.color = this.getItemTextColor(rowData.data); 1056 } 1057 return rowElement; 1058 } 1059 1060 freshCurrentLine(element: HTMLElement, rowObject: TableRowObject, firstElement?: HTMLElement): void { 1061 if (!rowObject) { 1062 if (firstElement) { 1063 firstElement.style.display = 'none'; 1064 } 1065 element.style.display = 'none'; 1066 return; 1067 } 1068 let childIndex = -1; //@ts-ignore 1069 this.setHighLight(rowObject.data.isSearch, element); 1070 element.childNodes.forEach((child) => { 1071 if (child.nodeType !== 1) { 1072 return; 1073 } 1074 childIndex++; 1075 let idx = firstElement !== undefined ? childIndex + 1 : childIndex; 1076 this.freshLineFirstElementHandler(firstElement, rowObject, childIndex); 1077 //@ts-ignore 1078 let dataIndex = this.columns![idx].getAttribute('data-index') || '1'; //@ts-ignore 1079 let text = formatName(dataIndex, rowObject.data[dataIndex], this); // @ts-ignore 1080 if ((this.columns![idx] as unknown).template) { 1081 (child as HTMLElement).innerHTML = ''; 1082 (child as HTMLElement).appendChild( 1083 // @ts-ignore 1084 (this.columns![idx] as unknown).template.render(rowObject.data).content.cloneNode(true) 1085 ); 1086 // @ts-ignore 1087 (child as HTMLElement).title = text; 1088 } else { 1089 //@ts-ignore 1090 (child as HTMLElement).innerHTML = text; //@ts-ignore 1091 (child as HTMLElement).title = text; 1092 } 1093 }); 1094 this.freshLineStyleAndEvents(element, rowObject, firstElement); 1095 } 1096 1097 freshLineFirstElementHandler(rowFirstElement: unknown, rowObject: TableRowObject, childIndex: number): void { 1098 if (rowFirstElement !== undefined && childIndex === 0) { 1099 //@ts-ignore 1100 this.setHighLight(rowObject.data.isSearch, rowFirstElement); // @ts-ignore 1101 (rowFirstElement as unknown).data = rowObject.data; // @ts-ignore 1102 if ((this.columns![0] as unknown).template) { 1103 // @ts-ignore 1104 rowFirstElement.innerHTML = (this.columns![0] as unknown).template 1105 .render(rowObject.data) 1106 .content.cloneNode(true).innerHTML; 1107 } else { 1108 let dataIndex = this.columns![0].getAttribute('data-index') || '1'; //@ts-ignore 1109 let text = formatName(dataIndex, rowObject.data[dataIndex], this); // @ts-ignore 1110 rowFirstElement.innerHTML = text; // @ts-ignore 1111 rowFirstElement.title = text; 1112 } //@ts-ignore 1113 if (rowObject.children && rowObject.children.length > 0 && !rowObject.data.hasNext) { 1114 let btn = this.createExpandBtn(rowObject); // @ts-ignore 1115 rowFirstElement.insertBefore(btn, rowFirstElement.firstChild); 1116 } // @ts-ignore 1117 rowFirstElement.style.paddingLeft = iconWidth * rowObject.depth + 'px'; 1118 if (!rowObject.children || rowObject.children.length === 0) { 1119 // @ts-ignore 1120 rowFirstElement.style.paddingLeft = iconWidth * rowObject.depth + iconWidth + iconPadding * 2 + 'px'; 1121 } //@ts-ignore 1122 if (rowObject.data.hasNext) { 1123 let btn = this.createBtn(rowObject); // @ts-ignore 1124 rowFirstElement.title = rowObject.data.objectName; // @ts-ignore 1125 rowFirstElement.insertBefore(btn, rowFirstElement.firstChild); // @ts-ignore 1126 rowFirstElement.style.paddingLeft = iconWidth * rowObject.depth + 'px'; 1127 } // @ts-ignore 1128 rowFirstElement.onclick = (): void => { 1129 this.dispatchRowClickEvent(rowObject, [rowFirstElement, element]); 1130 }; // @ts-ignore 1131 rowFirstElement.style.transform = `translateY(${rowObject.top - this.tableElement!.scrollTop}px)`; //@ts-ignore 1132 if (rowObject.data.isSelected !== undefined) { 1133 //@ts-ignore 1134 this.setSelectedRow(rowObject.data.isSelected, [rowFirstElement]); 1135 } else { 1136 this.setSelectedRow(false, [rowFirstElement]); 1137 } 1138 } 1139 } 1140 1141 freshLineStyleAndEvents(element: HTMLElement, rowData: TableRowObject, firstElement?: HTMLElement): void { 1142 if (element.style.display === 'none') { 1143 element.style.display = 'grid'; 1144 } 1145 element.style.transform = `translateY(${rowData.top}px)`; 1146 if (firstElement && firstElement.style.display === 'none') { 1147 firstElement.style.display = 'flex'; 1148 } 1149 element.onclick = (e): void => { 1150 if (firstElement !== undefined) { 1151 this.dispatchRowClickEvent(rowData, [firstElement, element]); 1152 } else { 1153 this.dispatchRowClickEvent(rowData, [element]); 1154 } 1155 }; 1156 element.onmouseenter = (): void => { 1157 this.dispatchRowHoverEvent(rowData, [element]); 1158 }; 1159 // @ts-ignore 1160 (element as unknown).data = rowData.data; //@ts-ignore 1161 if (rowData.data.isSelected !== undefined) { 1162 //@ts-ignore 1163 this.setSelectedRow(rowData.data.isSelected, [element]); 1164 } else { 1165 this.setSelectedRow(false, [element]); 1166 } //@ts-ignore 1167 if (rowData.data.isHover !== undefined) { 1168 //@ts-ignore 1169 this.setMouseIn(rowData.data.isHover, [element]); 1170 } else { 1171 this.setMouseIn(false, [element]); 1172 } 1173 if (this.getItemTextColor) { 1174 // @ts-ignore 1175 element.style.color = this.getItemTextColor((element as unknown).data); 1176 } 1177 } 1178 1179 setSelectedRow(isSelected: boolean, rows: unknown[]): void { 1180 if (isSelected) { 1181 rows.forEach((row) => { 1182 // @ts-ignore 1183 if (row.classList.contains('mouse-in')) { 1184 // @ts-ignore 1185 row.classList.remove('mouse-in'); 1186 } // @ts-ignore 1187 row.classList.add('mouse-select'); 1188 }); 1189 } else { 1190 rows.forEach((row) => { 1191 // @ts-ignore 1192 row.classList.remove('mouse-select'); 1193 }); 1194 } 1195 } 1196 1197 setMouseIn(isMouseIn: boolean, rows: unknown[]): void { 1198 if (isMouseIn) { 1199 rows.forEach((row) => { 1200 // @ts-ignore 1201 row.classList.add('mouse-in'); 1202 }); 1203 } else { 1204 rows.forEach((row) => { 1205 // @ts-ignore 1206 row.classList.remove('mouse-in'); 1207 }); 1208 } 1209 } 1210 1211 scrollToData(data: unknown): void { 1212 if (this.recycleDs.length > 0) { 1213 let filter = this.recycleDs.filter((item) => { 1214 // @ts-ignore 1215 return item.data === data; 1216 }); 1217 if (filter.length > 0) { 1218 // @ts-ignore 1219 this.tableElement!.scrollTop = filter[0].top; 1220 } 1221 this.setCurrentSelection(data); 1222 } 1223 } 1224 1225 expandList(datasource: unknown[]): void { 1226 let source = this.recycleDs.filter((item) => { 1227 // @ts-ignore 1228 return datasource.indexOf(item.data) !== -1; 1229 }); 1230 if (source.length > 0) { 1231 source.forEach((item) => { 1232 // @ts-ignore 1233 item.expanded = true; // @ts-ignore 1234 item.rowHidden = false; 1235 }); 1236 } 1237 this.reMeauseHeight(); 1238 } 1239 1240 clearAllSelection(rowObjectData: unknown = undefined): void { 1241 this.recycleDs.forEach((item) => { 1242 // @ts-ignore 1243 if (rowObjectData || (item.data !== rowObjectData && item.data.isSelected)) { 1244 // @ts-ignore 1245 item.data.isSelected = false; 1246 } 1247 }); 1248 this.setSelectedRow(false, this.currentTreeDivList); 1249 this.setSelectedRow(false, this.currentRecycleList); 1250 } 1251 1252 clearAllHover(rowObjectData: unknown): void { 1253 this.recycleDs.forEach((item) => { 1254 // @ts-ignore 1255 if (item.data !== rowObjectData && item.data.isHover) { 1256 // @ts-ignore 1257 item.data.isHover = false; 1258 } 1259 }); 1260 this.setMouseIn(false, this.currentTreeDivList); 1261 this.setMouseIn(false, this.currentRecycleList); 1262 } 1263 1264 mouseOut(): void { 1265 // @ts-ignore 1266 this.recycleDs.forEach((item) => (item.data.isHover = false)); 1267 this.setMouseIn(false, this.currentTreeDivList); 1268 this.setMouseIn(false, this.currentRecycleList); 1269 this.dispatchEvent( 1270 new CustomEvent('row-hover', { 1271 detail: { 1272 data: undefined, 1273 }, 1274 composed: true, 1275 }) 1276 ); 1277 } 1278 1279 setCurrentSelection(data: unknown): void { 1280 // @ts-ignore 1281 if (data.isSelected !== undefined) { 1282 this.currentTreeDivList.forEach((item) => { 1283 // @ts-ignore 1284 if ((item as unknown).data === data) { 1285 // @ts-ignore 1286 this.setSelectedRow(data.isSelected, [item]); 1287 } 1288 }); 1289 this.currentRecycleList.forEach((item) => { 1290 // @ts-ignore 1291 if ((item as unknown).data === data) { 1292 // @ts-ignore 1293 this.setSelectedRow(data.isSelected, [item]); 1294 } 1295 }); 1296 } 1297 } 1298 1299 setCurrentHover(data: unknown): void { 1300 this.setMouseIn(false, this.currentTreeDivList); 1301 this.setMouseIn(false, this.currentRecycleList); // @ts-ignore 1302 if (data.isHover !== undefined) { 1303 this.currentTreeDivList.forEach((item) => { 1304 // @ts-ignore 1305 if ((item as unknown).data === data) { 1306 // @ts-ignore 1307 this.setMouseIn(data.isHover, [item]); 1308 } 1309 }); 1310 this.currentRecycleList.forEach((item) => { 1311 // @ts-ignore 1312 if ((item as unknown).data === data) { 1313 // @ts-ignore 1314 this.setMouseIn(data.isHover, [item]); 1315 } 1316 }); 1317 } 1318 } 1319 1320 dispatchRowClickEventIcon(rowObject: unknown, elements: unknown[]): void { 1321 this.dispatchEvent( 1322 new CustomEvent('icon-click', { 1323 detail: { 1324 // @ts-ignore 1325 ...rowObject.data, // @ts-ignore 1326 data: rowObject.data, 1327 callBack: (isSelected: boolean): void => { 1328 //是否爲单选 1329 if (isSelected) { 1330 // @ts-ignore 1331 this.clearAllSelection(rowObject.data); 1332 } // @ts-ignore 1333 this.setSelectedRow(rowObject.data.isSelected, elements); 1334 }, 1335 }, 1336 composed: true, 1337 }) 1338 ); 1339 } 1340 1341 dispatchRowClickEvent(rowObject: unknown, elements: unknown[]): void { 1342 this.dispatchEvent( 1343 new CustomEvent('row-click', { 1344 detail: { 1345 // @ts-ignore 1346 ...rowObject.data, // @ts-ignore 1347 data: rowObject.data, 1348 callBack: (isSelected: boolean): void => { 1349 //是否爲单选 1350 if (isSelected) { 1351 // @ts-ignore 1352 this.clearAllSelection(rowObject.data); 1353 } 1354 // @ts-ignore 1355 rowObject.data.isSelected = true; 1356 // @ts-ignore 1357 this.setSelectedRow(rowObject.data.isSelected, elements); 1358 }, 1359 }, 1360 composed: true, 1361 }) 1362 ); 1363 } 1364 1365 dispatchRowHoverEvent(rowObject: unknown, elements: unknown[]): void { 1366 this.dispatchEvent( 1367 new CustomEvent('row-hover', { 1368 detail: { 1369 // @ts-ignore 1370 data: rowObject.data, 1371 callBack: (): void => { 1372 // @ts-ignore 1373 this.clearAllHover(rowObject.data); // @ts-ignore 1374 this.setMouseIn(rowObject.data.isHover, elements); 1375 }, 1376 }, 1377 composed: true, 1378 }) 1379 ); 1380 } 1381 setHighLight(isSearch: boolean, element: unknown): void { 1382 if (isSearch) { 1383 // @ts-ignore 1384 element.setAttribute('high-light', ''); 1385 } else { 1386 // @ts-ignore 1387 element.removeAttribute('high-light'); 1388 } 1389 } 1390} 1391 1392if (!customElements.get('lit-page-table')) { 1393 customElements.define('lit-page-table', LitPageTable); 1394} 1395