| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- import { Directive, forwardRef, Input, AfterViewInit, ElementRef, ViewContainerRef, OnDestroy, NgZone } from '@angular/core';
- import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
- import { C3Tooltip } from './c3-tooltip.component';
- import { Overlay, OverlayRef, OverlayConfig, PositionStrategy, FlexibleConnectedPositionStrategy, ConnectedPosition } from '@angular/cdk/overlay';
- import { Platform } from '@angular/cdk/platform';
- import { TemplatePortal } from '@angular/cdk/portal';
-
- export const MAT_AUTOCOMPLETE_VALUE_ACCESSOR: any = {
- provide: NG_VALUE_ACCESSOR,
- useExisting: forwardRef(() => C3TooltipTrigger),
- multi: true
- };
-
- @Directive({
- selector: '[c3Tooltip]',
- exportAs: 'c3TooltipTrigger',
- providers: [MAT_AUTOCOMPLETE_VALUE_ACCESSOR]
- })
- export class C3TooltipTrigger implements AfterViewInit, OnDestroy {
- private _overlayRef: OverlayRef | null;
- private _portal: TemplatePortal;
- private _positionStrategy: FlexibleConnectedPositionStrategy;
- private _overlayAttached: boolean = false;
-
- @Input('c3Tooltip') tooltip: C3Tooltip;
-
- @Input('c3TooltipDisabled') disabled: Boolean = false;
-
- /** The default delay in ms before showing the tooltip after show is called */
- @Input('c3TooltipShowDelay') showDelay = 0;
-
- /** The default delay in ms before hiding the tooltip after hide is called */
- @Input('c3TooltipHideDelay') hideDelay = 0;
-
- private _manualListeners = new Map<string, EventListenerOrEventListenerObject>();
-
- constructor(
- private _element: ElementRef<HTMLElement>,
- private _overlay: Overlay,
- platform: Platform,
- private _ngZone: NgZone,
- private _viewContainerRef: ViewContainerRef) {
- if (!platform.IOS && !platform.ANDROID) {
- this._manualListeners
- .set('mouseenter', () => this.show())
- .set('mouseleave', () => this.hide());
- }
- }
-
- ngAfterViewInit() {
- this._manualListeners.forEach((listener, event) => this._element.nativeElement.addEventListener(event, listener));
- }
-
- ngOnDestroy() {
- this._manualListeners.forEach((listener, event) => {
- this._element.nativeElement.removeEventListener(event, listener);
- });
- this._manualListeners.clear();
- }
-
- show(delay: number = this.showDelay) {
- console.log('show')
- let overlayRef = this._overlayRef;
-
- if (!overlayRef) {
- this._portal = new TemplatePortal(this.tooltip.template, this._viewContainerRef);
- overlayRef = this._overlay.create(this._getOverlayConfig());
- this._overlayRef = overlayRef;
- }
-
- if (overlayRef && !overlayRef.hasAttached()) {
- overlayRef.attach(this._portal);
- this._overlayAttached = true;
- }
- }
-
- get panelOpen(): boolean {
- return this._overlayAttached;
- }
-
- hide() {
- if (!this._overlayAttached) {
- return;
- }
-
- if (this._overlayRef && this._overlayRef.hasAttached()) {
- this._overlayRef.detach();
- }
- }
-
- private _getOverlayConfig(): OverlayConfig {
- return new OverlayConfig({
- positionStrategy: this._getOverlayPosition(),
- width: this._element.nativeElement.getBoundingClientRect().width
- });
- }
-
- private _getOverlayPosition(): PositionStrategy {
- const strategy = this._overlay.position()
- .flexibleConnectedTo(this.tooltip.template.elementRef)
- .withFlexibleDimensions(true)
- .withPush(false)
- .withViewportMargin(8);
-
- this._setStrategyPositions(strategy);
- this._positionStrategy = strategy;
- return strategy;
- }
- private _setStrategyPositions(positionStrategy: FlexibleConnectedPositionStrategy) {
- const belowPosition: ConnectedPosition = {
- originX: 'start',
- originY: 'bottom',
- overlayX: 'start',
- overlayY: 'top'
- };
- const abovePosition: ConnectedPosition = {
- originX: 'start',
- originY: 'top',
- overlayX: 'start',
- overlayY: 'bottom',
-
- // The overlay edge connected to the trigger should have squared corners, while
- // the opposite end has rounded corners. We apply a CSS class to swap the
- // border-radius based on the overlay position.
- };
-
- let positions: ConnectedPosition[];
-
- positions = [belowPosition, abovePosition];
-
- positionStrategy.withPositions(positions);
- }
- }
|