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