All files / app/services/domcomputation domcomputation.service.ts

100% Statements 23/23
100% Branches 15/15
100% Functions 3/3
100% Lines 23/23

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            1x                         2x 2x 2x 2x   2x 2x 2x                             11x 11x 11x 11x   11x 11x 11x                                             419x 140x     279x     279x     279x       279x     279x     279x      
import { ElementRef, Injectable } from '@angular/core';
 
/** DOM Computation service. */
@Injectable({
  providedIn: 'root',
})
export class DOMComputationService {
  /**
   * Gets the actual width of an element
   *
   * @param {any} element The element
   * @returns The actual width
   */
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  getActualWidth(element: any) {
    // https://stackoverflow.com/a/32637350
    // https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
    // https://stackoverflow.com/a/63622682
    // https://stackoverflow.com/a/29881817
    const rec = element.getBoundingClientRect();
    let width = rec.width;
    const cs = getComputedStyle(element);
    const paddingX = parseFloat(cs.paddingLeft) + parseFloat(cs.paddingRight);
    const borderX =
      parseFloat(cs.borderLeftWidth) + parseFloat(cs.borderRightWidth);
    width -= paddingX + borderX;
    return width;
  }
 
  /**
   * Gets the actual height of an element
   *
   * @param {any} element The element
   * @returns The actual height
   */
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  getActualHeight(element: any) {
    // https://stackoverflow.com/a/32637350
    // https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
    // https://stackoverflow.com/a/63622682
    // https://stackoverflow.com/a/29881817
    const rec = element.getBoundingClientRect();
    let height = rec.height;
    const cs = getComputedStyle(element);
    const paddingY = parseFloat(cs.paddingTop) + parseFloat(cs.paddingBottom);
    const borderY =
      parseFloat(cs.borderTopWidth) + parseFloat(cs.borderBottomWidth);
    height -= paddingY + borderY;
    return height;
  }
 
  /**
   * Checks whether or not an element is into view, with an optional buffer for
   * the viewport.
   *
   * @param element The element.
   * @param bufferFactorHeight Buffer factor for the height. For instance, a
   *   buffer factor of 0 means no buffer, a buffer factor of 1 means that the
   *   viewport height is extended (both up and down) by another viewport
   *   height.
   * @param bufferFactorWidth Buffer factor for the width. For instance, a
   *   buffer factor of 0 means no buffer, a buffer factor of 1 means that the
   *   viewport width is extended (both left and right) by another viewport
   *   width.
   * @returns
   */
  isIntoView(
    element: ElementRef<HTMLElement>,
    bufferFactorHeight = 0,
    bufferFactorWidth = 0
  ) {
    if (!element?.nativeElement) {
      return false;
    }
 
    const rect = element.nativeElement.getBoundingClientRect();
 
    const topShown =
      rect.top >= -bufferFactorHeight * window.innerHeight &&
      rect.top <= (bufferFactorHeight + 1) * window.innerHeight;
    const bottomShown =
      rect.bottom >= -bufferFactorHeight * window.innerHeight &&
      rect.bottom <= (bufferFactorHeight + 1) * window.innerHeight;
 
    const leftShown =
      rect.left >= -bufferFactorWidth * window.innerWidth &&
      rect.left <= (bufferFactorWidth + 1) * window.innerWidth;
    const rightShown =
      rect.right >= -bufferFactorWidth * window.innerWidth &&
      rect.right <= (bufferFactorWidth + 1) * window.innerWidth;
 
    return (topShown || bottomShown) && (leftShown || rightShown);
  }
}