Skip to content
Snippets Groups Projects
Select Git revision
  • 99da23a18922dc47475ee8d8af2b6fee9c92a1c9
  • main default protected
  • release
  • OZG-7856_schadcode_scanner
  • ci-pipeline
  • OZG-7526-signatur-nicht-uebernommen
  • OZG-6223-zip-download-bug
  • OZG-7367-tooltip-extension
  • OZG-7023-OZG-6956-E2E-externe-Stellen
  • OZG-6238-npm-durch-pnpm-ersetzen
  • release-admin
  • release-info
  • OZG-6700-admin-feature-toggle
  • E2E-Updates
  • OZG-7047-tooltips
  • OZG-6957-e2e-fachstellen-oe-daten
  • OZG-7006-ZuarbeitAnfragen
  • temp_OZG-7027
  • unit-tests-hotfix
  • OZG-6731-POC-keycloakResourceService-with-multiple-stateResources
  • e2e-add-zufi-version
  • 2.26.0
  • 2.25.0
  • 2.24.2
  • 2.24.1
  • 2.24.0
  • 2.23.0
  • 2.22.0
  • 2.21.0
  • 2.20.0
  • 2.21.0-SNAPSHOT
  • 2.19.0
  • 2.18.0
  • 2.17.1
  • 1.3.0
  • release-admin-1.3.0
  • release-info-1.3.0
  • 2.17.0
  • 2.16.0
  • 2.15.0
  • release-admin-1.1.0
41 results

text-field.component.html

Blame
  • tooltip.directive.ts 3.02 KiB
    import { isEscapeKey } from '@alfa-client/tech-shared';
    import { InteractivityChecker } from '@angular/cdk/a11y';
    import {
      ComponentRef,
      Directive,
      ElementRef,
      HostListener,
      inject,
      Input,
      OnDestroy,
      Renderer2,
      ViewContainerRef,
    } from '@angular/core';
    import { uniqueId } from 'lodash-es';
    import { TooltipComponent } from './tooltip.component';
    
    @Directive({
      selector: '[tooltip]',
      standalone: true,
    })
    export class TooltipDirective implements OnDestroy {
      @Input() tooltip: string = '';
    
      componentRef: ComponentRef<TooltipComponent> = null;
      focusableElement: HTMLElement = null;
      tooltipId: string;
    
      public viewContainerRef: ViewContainerRef = inject(ViewContainerRef);
      public elementRef: ElementRef<HTMLElement> = inject(ElementRef);
      public renderer: Renderer2 = inject(Renderer2);
      public interactivityChecker: InteractivityChecker = inject(InteractivityChecker);
    
      ngOnDestroy(): void {
        this.destroy();
      }
    
      @HostListener('mouseenter')
      @HostListener('focusin')
      createTooltip(): void {
        if (this.componentRef === null) {
          const nativeElement: HTMLElement = this.elementRef.nativeElement;
          const attachedToFocused: boolean = nativeElement.contains(document.activeElement);
          this.componentRef = this.viewContainerRef.createComponent(TooltipComponent);
          nativeElement.appendChild(this.componentRef.location.nativeElement);
          this.setDescribedBy();
          this.setTooltipProperties(attachedToFocused);
        }
      }
    
      @HostListener('mouseleave')
      @HostListener('window:scroll')
      @HostListener('focusout')
      destroyTooltip(): void {
        this.destroy();
      }
    
      @HostListener('keydown', ['$event'])
      onKeydown(e: KeyboardEvent): void {
        if (isEscapeKey(e)) {
          this.destroy();
        }
      }
    
      setTooltipProperties(attachedToFocused = false): void {
        if (this.componentRef !== null) {
          const { left, right, bottom } = this.elementRef.nativeElement.getBoundingClientRect();
          this.componentRef.instance.left = (right + left) / 2;
          this.componentRef.instance.top = attachedToFocused ? bottom + 4 : bottom;
          this.componentRef.instance.text = this.tooltip;
          this.componentRef.instance.id = this.tooltipId;
        }
      }
    
      setDescribedBy(): void {
        const nativeElement: HTMLElement = this.elementRef.nativeElement;
        this.tooltipId = uniqueId('tooltip');
        this.focusableElement =
          this.interactivityChecker.isFocusable(nativeElement) ? nativeElement : this.getFocusableElement(nativeElement);
        this.renderer.setAttribute(this.focusableElement, 'aria-describedby', this.tooltipId);
      }
    
      removeDescribedBy(): void {
        this.renderer.removeAttribute(this.focusableElement, 'aria-describedby');
      }
    
      getFocusableElement(element: HTMLElement): HTMLElement {
        return element.querySelector('a[href], button, input, textarea, select, details, [tabindex]:not([tabindex="-1"])');
      }
    
      destroy(): void {
        if (this.componentRef !== null) {
          this.componentRef.destroy();
          this.componentRef = null;
          this.removeDescribedBy();
          this.focusableElement = null;
        }
      }
    }