From 07aec134ff684a2d4540978fa12f5319de726dda Mon Sep 17 00:00:00 2001 From: Mike Baum Date: Wed, 20 Feb 2019 20:56:10 +1100 Subject: [PATCH] feat(tooltip): add a configurable tooltip delay (#891) Closes #790 --- .../common/calendar-tooltip.directive.ts | 12 ++++- .../day/calendar-day-view-event.component.ts | 7 ++- .../day/calendar-day-view.component.ts | 8 ++++ .../month/calendar-month-cell.component.ts | 7 ++- .../month/calendar-month-view.component.ts | 7 +++ .../calendar-week-view-event.component.ts | 7 ++- .../week/calendar-week-view.component.ts | 8 ++++ .../calendar-month-view.component.spec.ts | 44 ++++++++++++++++++- 8 files changed, 95 insertions(+), 5 deletions(-) diff --git a/projects/angular-calendar/src/modules/common/calendar-tooltip.directive.ts b/projects/angular-calendar/src/modules/common/calendar-tooltip.directive.ts index f0cde64bd..df66a7cc3 100644 --- a/projects/angular-calendar/src/modules/common/calendar-tooltip.directive.ts +++ b/projects/angular-calendar/src/modules/common/calendar-tooltip.directive.ts @@ -17,6 +17,8 @@ import { import { DOCUMENT } from '@angular/common'; import { PlacementArray, positionElements } from 'positioning'; import { CalendarEvent } from 'calendar-utils'; +import { Observable, of, Subject, timer } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; @Component({ selector: 'mwl-calendar-tooltip-window', @@ -67,8 +69,11 @@ export class CalendarTooltipDirective implements OnDestroy { @Input('tooltipAppendToBody') appendToBody: boolean; // tslint:disable-line no-input-rename + @Input('tooltipDelay') delay: number | null = null; // tslint:disable-line no-input-rename + private tooltipFactory: ComponentFactory; private tooltipRef: ComponentRef; + private cancelTooltipDelay$ = new Subject(); constructor( private elementRef: ElementRef, @@ -89,7 +94,11 @@ export class CalendarTooltipDirective implements OnDestroy { @HostListener('mouseenter') onMouseOver(): void { - this.show(); + const delay$: Observable = + this.delay === null ? of('now') : timer(this.delay); + delay$.pipe(takeUntil(this.cancelTooltipDelay$)).subscribe(() => { + this.show(); + }); } @HostListener('mouseleave') @@ -124,6 +133,7 @@ export class CalendarTooltipDirective implements OnDestroy { ); this.tooltipRef = null; } + this.cancelTooltipDelay$.next(); } private positionTooltip(previousPosition?: string): void { diff --git a/projects/angular-calendar/src/modules/day/calendar-day-view-event.component.ts b/projects/angular-calendar/src/modules/day/calendar-day-view-event.component.ts index 0a88123d0..998cc0c93 100644 --- a/projects/angular-calendar/src/modules/day/calendar-day-view-event.component.ts +++ b/projects/angular-calendar/src/modules/day/calendar-day-view-event.component.ts @@ -18,6 +18,7 @@ import { PlacementArray } from 'positioning'; let-eventClicked="eventClicked" let-tooltipTemplate="tooltipTemplate" let-tooltipAppendToBody="tooltipAppendToBody" + let-tooltipDelay="tooltipDelay" >
@@ -74,5 +77,7 @@ export class CalendarDayViewEventComponent { @Input() tooltipTemplate: TemplateRef; + @Input() tooltipDelay: number | null; + @Output() eventClicked: EventEmitter = new EventEmitter(); } diff --git a/projects/angular-calendar/src/modules/day/calendar-day-view.component.ts b/projects/angular-calendar/src/modules/day/calendar-day-view.component.ts index e3161632e..ce20ee72b 100644 --- a/projects/angular-calendar/src/modules/day/calendar-day-view.component.ts +++ b/projects/angular-calendar/src/modules/day/calendar-day-view.component.ts @@ -90,6 +90,7 @@ export interface DayViewEventResize { [tooltipPlacement]="tooltipPlacement" [tooltipTemplate]="tooltipTemplate" [tooltipAppendToBody]="tooltipAppendToBody" + [tooltipDelay]="tooltipDelay" [customTemplate]="eventTemplate" [eventTitleTemplate]="eventTitleTemplate" [eventActionsTemplate]="eventActionsTemplate" @@ -166,6 +167,7 @@ export interface DayViewEventResize { [tooltipPlacement]="tooltipPlacement" [tooltipTemplate]="tooltipTemplate" [tooltipAppendToBody]="tooltipAppendToBody" + [tooltipDelay]="tooltipDelay" [customTemplate]="eventTemplate" [eventTitleTemplate]="eventTitleTemplate" [eventActionsTemplate]="eventActionsTemplate" @@ -283,6 +285,12 @@ export class CalendarDayViewComponent implements OnChanges, OnInit, OnDestroy { */ @Input() tooltipAppendToBody: boolean = true; + /** + * The delay in milliseconds before the tooltip should be displayed. If not provided the tooltip + * will be displayed immediately. + */ + @Input() tooltipDelay: number | null = null; + /** * A custom template to use to replace the hour segment */ diff --git a/projects/angular-calendar/src/modules/month/calendar-month-cell.component.ts b/projects/angular-calendar/src/modules/month/calendar-month-cell.component.ts index ea70f972c..d6c48f8c8 100644 --- a/projects/angular-calendar/src/modules/month/calendar-month-cell.component.ts +++ b/projects/angular-calendar/src/modules/month/calendar-month-cell.component.ts @@ -23,6 +23,7 @@ import { PlacementArray } from 'positioning'; let-eventClicked="eventClicked" let-tooltipTemplate="tooltipTemplate" let-tooltipAppendToBody="tooltipAppendToBody" + let-tooltipDelay="tooltipDelay" >
{{ @@ -47,6 +48,7 @@ import { PlacementArray } from 'positioning'; [tooltipEvent]="event" [tooltipTemplate]="tooltipTemplate" [tooltipAppendToBody]="tooltipAppendToBody" + [tooltipDelay]="tooltipDelay" mwlDraggable [class.cal-draggable]="event.draggable" dragActiveClass="cal-drag-active" @@ -67,7 +69,8 @@ import { PlacementArray } from 'positioning'; unhighlightDay: unhighlightDay, eventClicked: eventClicked, tooltipTemplate: tooltipTemplate, - tooltipAppendToBody: tooltipAppendToBody + tooltipAppendToBody: tooltipAppendToBody, + tooltipDelay: tooltipDelay }" > @@ -101,6 +104,8 @@ export class CalendarMonthCellComponent { @Input() tooltipTemplate: TemplateRef; + @Input() tooltipDelay: number | null; + @Output() highlightDay: EventEmitter = new EventEmitter(); @Output() unhighlightDay: EventEmitter = new EventEmitter(); diff --git a/projects/angular-calendar/src/modules/month/calendar-month-view.component.ts b/projects/angular-calendar/src/modules/month/calendar-month-view.component.ts index 8861b86a7..41453cc4e 100644 --- a/projects/angular-calendar/src/modules/month/calendar-month-view.component.ts +++ b/projects/angular-calendar/src/modules/month/calendar-month-view.component.ts @@ -79,6 +79,7 @@ export interface CalendarMonthViewEventTimesChangedEvent< [tooltipPlacement]="tooltipPlacement" [tooltipAppendToBody]="tooltipAppendToBody" [tooltipTemplate]="tooltipTemplate" + [tooltipDelay]="tooltipDelay" [customTemplate]="cellTemplate" (mwlClick)="dayClicked.emit({ day: day })" (highlightDay)="toggleDayHighlight($event.event, true)" @@ -172,6 +173,12 @@ export class CalendarMonthViewComponent */ @Input() tooltipAppendToBody: boolean = true; + /** + * The delay in milliseconds before the tooltip should be displayed. If not provided the tooltip + * will be displayed immediately. + */ + @Input() tooltipDelay: number | null = null; + /** * The start number of the week */ diff --git a/projects/angular-calendar/src/modules/week/calendar-week-view-event.component.ts b/projects/angular-calendar/src/modules/week/calendar-week-view-event.component.ts index d8b863c6d..832cc1aed 100644 --- a/projects/angular-calendar/src/modules/week/calendar-week-view-event.component.ts +++ b/projects/angular-calendar/src/modules/week/calendar-week-view-event.component.ts @@ -19,6 +19,7 @@ import { PlacementArray } from 'positioning'; let-tooltipTemplate="tooltipTemplate" let-tooltipAppendToBody="tooltipAppendToBody" let-tooltipDisabled="tooltipDisabled" + let-tooltipDelay="tooltipDelay" >
@@ -73,6 +76,8 @@ export class CalendarWeekViewEventComponent { @Input() tooltipDisabled: boolean; + @Input() tooltipDelay: number | null; + @Input() customTemplate: TemplateRef; @Input() eventTitleTemplate: TemplateRef; diff --git a/projects/angular-calendar/src/modules/week/calendar-week-view.component.ts b/projects/angular-calendar/src/modules/week/calendar-week-view.component.ts index e8dae17e1..05eed81c5 100644 --- a/projects/angular-calendar/src/modules/week/calendar-week-view.component.ts +++ b/projects/angular-calendar/src/modules/week/calendar-week-view.component.ts @@ -170,6 +170,7 @@ export interface CalendarWeekViewBeforeRenderEvent extends WeekView { [tooltipPlacement]="tooltipPlacement" [tooltipTemplate]="tooltipTemplate" [tooltipAppendToBody]="tooltipAppendToBody" + [tooltipDelay]="tooltipDelay" [customTemplate]="eventTemplate" [eventTitleTemplate]="eventTitleTemplate" [eventActionsTemplate]="eventActionsTemplate" @@ -293,6 +294,7 @@ export interface CalendarWeekViewBeforeRenderEvent extends WeekView { [tooltipTemplate]="tooltipTemplate" [tooltipAppendToBody]="tooltipAppendToBody" [tooltipDisabled]="dragActive || timeEventResizes.size > 0" + [tooltipDelay]="tooltipDelay" [customTemplate]="eventTemplate" [eventTitleTemplate]="eventTitleTemplate" [eventActionsTemplate]="eventActionsTemplate" @@ -390,6 +392,12 @@ export class CalendarWeekViewComponent implements OnChanges, OnInit, OnDestroy { */ @Input() tooltipAppendToBody: boolean = true; + /** + * The delay in milliseconds before the tooltip should be displayed. If not provided the tooltip + * will be displayed immediately. + */ + @Input() tooltipDelay: number | null = null; + /** * The start number of the week */ diff --git a/projects/angular-calendar/test/calendar-month-view.component.spec.ts b/projects/angular-calendar/test/calendar-month-view.component.spec.ts index 08b9c8e55..9404a24a7 100644 --- a/projects/angular-calendar/test/calendar-month-view.component.spec.ts +++ b/projects/angular-calendar/test/calendar-month-view.component.spec.ts @@ -3,7 +3,8 @@ import { ComponentFixture, TestBed, fakeAsync, - flush + flush, + tick } from '@angular/core/testing'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import moment from 'moment'; @@ -541,6 +542,47 @@ describe('calendarMonthView component', () => { expect(!!document.body.querySelector('.cal-tooltip')).to.equal(false); })); + it('should show a tooltip on mouseover of the event after a delay', fakeAsync(() => { + const fixture: ComponentFixture< + CalendarMonthViewComponent + > = TestBed.createComponent(CalendarMonthViewComponent); + eventTitle.monthTooltip = (e: CalendarEvent) => { + return `title: ${e.title}`; + }; + fixture.componentInstance.viewDate = new Date('2016-06-27'); + fixture.componentInstance.events = [ + { + start: new Date('2016-05-30'), + end: new Date('2016-06-02'), + title: 'foo bar' + } + ]; + fixture.componentInstance.tooltipDelay = 2000; + fixture.componentInstance.ngOnChanges({ viewDate: {}, events: {} }); + fixture.detectChanges(); + const event: HTMLElement = fixture.nativeElement.querySelector( + '.cal-days .cal-cell-row .cal-cell:nth-child(4) .cal-events .cal-event' + ); + triggerDomEvent('mouseenter', event); + fixture.detectChanges(); + tick(fixture.componentInstance.tooltipDelay - 1); + expect(!!document.body.querySelector('.cal-tooltip')).to.equal(false); + tick(1); + expect(!!document.body.querySelector('.cal-tooltip')).to.equal(true); + const tooltip: HTMLElement = document.body.querySelector( + '.cal-tooltip' + ) as HTMLElement; + expect(tooltip.querySelector('.cal-tooltip-inner').innerHTML).to.equal( + 'title: foo bar' + ); + expect(tooltip.classList.contains('cal-tooltip-top')).to.equal(true); + expect(!!tooltip.style.top).to.equal(true); + expect(!!tooltip.style.left).to.equal(true); + triggerDomEvent('mouseleave', event); + fixture.detectChanges(); + expect(!!document.body.querySelector('.cal-tooltip')).to.equal(false); + })); + it('should disable the tooltip', fakeAsync(() => { const fixture: ComponentFixture< CalendarMonthViewComponent