private _listenForTableEvents()

in src/cdk-experimental/popover-edit/table-directives.ts [86:153]


  private _listenForTableEvents(): void {
    const element = this.elementRef.nativeElement;
    const toClosest = (selector: string) =>
      map((event: UIEvent) => closest(event.target, selector));

    this.ngZone.runOutsideAngular(() => {
      // Track mouse movement over the table to hide/show hover content.
      fromEvent<MouseEvent>(element, 'mouseover')
        .pipe(toClosest(ROW_SELECTOR), takeUntil(this.destroyed))
        .subscribe(this.editEventDispatcher.hovering);
      fromEvent<MouseEvent>(element, 'mouseleave')
        .pipe(mapTo(null), takeUntil(this.destroyed))
        .subscribe(this.editEventDispatcher.hovering);
      fromEvent<MouseEvent>(element, 'mousemove')
        .pipe(
          throttleTime(MOUSE_MOVE_THROTTLE_TIME_MS),
          toClosest(ROW_SELECTOR),
          takeUntil(this.destroyed),
        )
        .subscribe(this.editEventDispatcher.mouseMove);

      // Track focus within the table to hide/show/make focusable hover content.
      fromEventPattern<FocusEvent>(
        handler => element.addEventListener('focus', handler, true),
        handler => element.removeEventListener('focus', handler, true),
      )
        .pipe(toClosest(ROW_SELECTOR), share(), takeUntil(this.destroyed))
        .subscribe(this.editEventDispatcher.focused);

      merge(
        fromEventPattern<FocusEvent>(
          handler => element.addEventListener('blur', handler, true),
          handler => element.removeEventListener('blur', handler, true),
        ),
        fromEvent<KeyboardEvent>(element, 'keydown').pipe(filter(event => event.key === 'Escape')),
      )
        .pipe(mapTo(null), share(), takeUntil(this.destroyed))
        .subscribe(this.editEventDispatcher.focused);

      // Keep track of rows within the table. This is used to know which rows with hover content
      // are first or last in the table. They are kept focusable in case focus enters from above
      // or below the table.
      this.ngZone.onStable
        .pipe(
          // Optimization: ignore dom changes while focus is within the table as we already
          // ensure that rows above and below the focused/active row are tabbable.
          withLatestFrom(this.editEventDispatcher.editingOrFocused),
          filter(([_, activeRow]) => activeRow == null),
          map(() => element.querySelectorAll(ROW_SELECTOR)),
          share(),
          takeUntil(this.destroyed),
        )
        .subscribe(this.editEventDispatcher.allRows);

      fromEvent<KeyboardEvent>(element, 'keydown')
        .pipe(
          filter(event => event.key === 'Enter'),
          toClosest(CELL_SELECTOR),
          takeUntil(this.destroyed),
        )
        .subscribe(this.editEventDispatcher.editing);

      // Keydown must be used here or else key autorepeat does not work properly on some platforms.
      fromEvent<KeyboardEvent>(element, 'keydown')
        .pipe(takeUntil(this.destroyed))
        .subscribe(this.focusDispatcher.keyObserver);
    });
  }