All files / tree-view si-tree-view-item-height.service.ts

90.32% Statements 28/31
77.77% Branches 7/9
100% Functions 3/3
89.28% Lines 25/28

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108                                        1x                               103x   103x                           99x 99x     99x 99x 96x 96x     99x 95x 95x     99x                             361x 361x     361x 1814x 4x 4x     361x 4x     361x       100x 100x 100x          
/**
 * Copyright (c) Siemens 2016 - 2025
 * SPDX-License-Identifier: MIT
 */
import { EventEmitter, inject, Injectable } from '@angular/core';
 
import { TreeItem } from './si-tree-view.model';
import { SiTreeViewService } from './si-tree-view.service';
 
/**
 * This service provides helper functionality for the tree view to read the height of the tree/list items and
 * the group list items out of the DOM.
 *
 * Important: The coupling to the TreeViewComponent is very high as the service contains knowledge on the HTML structure!!!
 * Thus the service is provided only by the TreeViewComponent.
 *
 * Constraint: The height of the items (DOM elements) must be all the same; The height of the grouped items (DOM elements)
 * must be all the same;
 */
@Injectable()
export class SiTreeViewItemHeightService {
  /**
   * The height of a tree list item.
   * Can be undefined if the tree list has not been layout rendered yet.
   */
  itemHeight?: number;
 
  /**
   * The height of a grouped list item.
   * Can be undefined if the tree list has not been layout rendered yet or if it does not contain group items.
   */
  groupItemHeight?: number;
 
  /**
   * Emitter for itemHeight changes.
   */
  readonly itemHeightChange = new EventEmitter<number>();
 
  private siTreeViewService = inject(SiTreeViewService);
 
  /**
   * Updates the height of a list item, if an appropriate item is in the DOM.
   *
   * @returns The new height of the list item; or undefined if no list item is in the DOM yet.
   */
  updateItemHeight(
    elementList: Element,
    flattenedTrees: TreeItem[],
    itemsBase: number,
    virtualizedItems: number
  ): number | undefined {
    let newHeight: number | undefined;
    let itemsTop: number = itemsBase + virtualizedItems;
    Iif (itemsTop > flattenedTrees.length) {
      itemsTop = flattenedTrees.length;
    }
    for (let i: number = itemsBase; i < itemsTop; i++) {
      if (this.siTreeViewService.isGroupedItem(flattenedTrees[i]) === false) {
        newHeight = this.getItemHeightOfListElement(elementList, i - itemsBase);
        break;
      }
    }
    if (newHeight !== undefined && this.itemHeight !== newHeight) {
      this.itemHeight = newHeight;
      this.itemHeightChange.emit(newHeight);
    }
 
    return newHeight;
  }
 
  /**
   * Updates the height of a group item, if an appropriate item is in the DOM.
   *
   * @returns The new height of the group item; or undefined if no group item is in the DOM yet.
   */
  updateGroupedItemHeight(
    elementList: Element,
    flattenedTrees: TreeItem[],
    itemsBase: number,
    virtualizedItems: number
  ): number | undefined {
    let newHeight: number | undefined;
    let itemsTop: number = itemsBase + virtualizedItems;
    Iif (itemsTop > flattenedTrees.length) {
      itemsTop = flattenedTrees.length;
    }
    for (let i: number = itemsBase; i < itemsTop; i++) {
      if (this.siTreeViewService.isGroupedItem(flattenedTrees[i])) {
        newHeight = this.getItemHeightOfListElement(elementList, i - itemsBase);
        break;
      }
    }
    if (newHeight !== undefined) {
      this.groupItemHeight = newHeight;
    }
 
    return newHeight;
  }
 
  private getItemHeightOfListElement(elementList: Element, index: number): number | undefined {
    const items = elementList.querySelectorAll('si-tree-view-item');
    if (index < items.length) {
      return items.item(index).getBoundingClientRect().height;
    }
    return undefined;
  }
}