All files / lib/accordion accordion.component.ts

97.29% Statements 108/111
88.23% Branches 15/17
83.33% Functions 5/6
97.29% Lines 108/111

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 109 110 111 1121x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 15x 15x 15x 15x 15x 15x   15x 15x 1x 1x 1x     1x 1x 2x 2x 2x 2x 2x 2x 2x 1x 1x 1x 1x 1x 4x 4x 4x 4x 4x 1x 1x 3x 1x 1x 2x 2x 4x 4x 4x 4x 1x 1x 1x 2x 2x 2x 2x 2x 2x 2x 2x 1x 1x 2x 1x 2x 2x 2x 2x 1x 1x 1x 1x 1x 45x 45x 1x  
/*******************************************************************************
 * Copyright bei
 * Entwicklungs- und Pflegeverbund für das gemeinsame Fachverfahren gefa
 *
 *******************************************************************************/
import {
  AfterContentInit,
  Component,
  ContentChildren,
  OnDestroy,
  QueryList,
} from '@angular/core';
import { Subscription } from 'rxjs';
 
import { FocusableElementOwner } from '../utils/util.types';
 
import { AccordionPanelComponent } from './accordion-panel.component';
 
/**
 * An `gc-accordion` allows the user have one or more components contained in collapsible containers.
 */
@Component({
  selector: 'gc-accordion',
  templateUrl: './accordion.component.html',
  styleUrls: ['./accordion.component.css'],
})
export class AccordionComponent
  implements AfterContentInit, OnDestroy, FocusableElementOwner
{
  /**
   * @ignore
   */
  @ContentChildren(AccordionPanelComponent)
  private panels?: QueryList<AccordionPanelComponent>;
 
  /** @ignore */
  private panelsChangeSubscription?: Subscription;
 
  /** @ignore */
  public ngAfterContentInit(): void {
    if (!this.panels) {
      return;
    }
    const handler = this.attachParent.bind(this);
    this.panels.forEach(handler);
    this.panelsChangeSubscription = this.panels.changes.subscribe(() => {
      this.panels?.forEach(handler);
    });
  }
 
  /** @ignore */
  public ngOnDestroy(): void {
    this.panelsChangeSubscription?.unsubscribe();
  }
 
  public focusChild(): boolean {
    if (this.panels?.first) {
      this.panels.first.focusChild();
      return true;
    } else {
      return false;
    }
  }
 
  /**
   * @ignore
   */
  public _moveFocus(
    curPanel: AccordionPanelComponent,
    action: 'first' | 'last' | 'next' | 'previous',
  ): boolean {
    if (this.panels && this.panels.length > 0) {
      if (action === 'first') {
        this.panels.get(0)?.focusChild();
        return true;
      } else if (action === 'last') {
        this.panels.get(this.panels.length - 1)?.focusChild();
        return true;
      } else {
        return this.moveFocusOnNeighbour(this.panels, curPanel, action);
      }
    }
    return false;
  }
 
  /** @ignore */
  private moveFocusOnNeighbour(
    panels: QueryList<AccordionPanelComponent>,
    curPanel: AccordionPanelComponent,
    action: 'next' | 'previous',
  ): boolean {
    const idx = panels.toArray().findIndex(item => item === curPanel);
    if (idx != -1) {
      if (action === 'previous' && idx - 1 >= 0) {
        panels.get(idx - 1)?.focusChild();
        return true;
      } else if (action === 'next' && idx + 1 < panels.length) {
        panels.get(idx + 1)?.focusChild();
        return true;
      }
    }
    return false;
  }
 
  /**
   * @ignore
   */
  private attachParent(panel: AccordionPanelComponent) {
    panel._parent = this;
  }
}