Skip to content

Commit 07aec13

Browse files
mbaumimsmattlewis92
authored andcommitted
feat(tooltip): add a configurable tooltip delay (#891)
Closes #790
1 parent 3552d0c commit 07aec13

8 files changed

+95
-5
lines changed

projects/angular-calendar/src/modules/common/calendar-tooltip.directive.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import {
1717
import { DOCUMENT } from '@angular/common';
1818
import { PlacementArray, positionElements } from 'positioning';
1919
import { CalendarEvent } from 'calendar-utils';
20+
import { Observable, of, Subject, timer } from 'rxjs';
21+
import { takeUntil } from 'rxjs/operators';
2022

2123
@Component({
2224
selector: 'mwl-calendar-tooltip-window',
@@ -67,8 +69,11 @@ export class CalendarTooltipDirective implements OnDestroy {
6769

6870
@Input('tooltipAppendToBody') appendToBody: boolean; // tslint:disable-line no-input-rename
6971

72+
@Input('tooltipDelay') delay: number | null = null; // tslint:disable-line no-input-rename
73+
7074
private tooltipFactory: ComponentFactory<CalendarTooltipWindowComponent>;
7175
private tooltipRef: ComponentRef<CalendarTooltipWindowComponent>;
76+
private cancelTooltipDelay$ = new Subject();
7277

7378
constructor(
7479
private elementRef: ElementRef,
@@ -89,7 +94,11 @@ export class CalendarTooltipDirective implements OnDestroy {
8994

9095
@HostListener('mouseenter')
9196
onMouseOver(): void {
92-
this.show();
97+
const delay$: Observable<any> =
98+
this.delay === null ? of('now') : timer(this.delay);
99+
delay$.pipe(takeUntil(this.cancelTooltipDelay$)).subscribe(() => {
100+
this.show();
101+
});
93102
}
94103

95104
@HostListener('mouseleave')
@@ -124,6 +133,7 @@ export class CalendarTooltipDirective implements OnDestroy {
124133
);
125134
this.tooltipRef = null;
126135
}
136+
this.cancelTooltipDelay$.next();
127137
}
128138

129139
private positionTooltip(previousPosition?: string): void {

projects/angular-calendar/src/modules/day/calendar-day-view-event.component.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { PlacementArray } from 'positioning';
1818
let-eventClicked="eventClicked"
1919
let-tooltipTemplate="tooltipTemplate"
2020
let-tooltipAppendToBody="tooltipAppendToBody"
21+
let-tooltipDelay="tooltipDelay"
2122
>
2223
<div
2324
class="cal-event"
@@ -30,6 +31,7 @@ import { PlacementArray } from 'positioning';
3031
[tooltipEvent]="dayEvent.event"
3132
[tooltipTemplate]="tooltipTemplate"
3233
[tooltipAppendToBody]="tooltipAppendToBody"
34+
[tooltipDelay]="tooltipDelay"
3335
(mwlClick)="eventClicked.emit()"
3436
>
3537
<mwl-calendar-event-actions
@@ -53,7 +55,8 @@ import { PlacementArray } from 'positioning';
5355
tooltipPlacement: tooltipPlacement,
5456
eventClicked: eventClicked,
5557
tooltipTemplate: tooltipTemplate,
56-
tooltipAppendToBody: tooltipAppendToBody
58+
tooltipAppendToBody: tooltipAppendToBody,
59+
tooltipDelay: tooltipDelay
5760
}"
5861
>
5962
</ng-template>
@@ -74,5 +77,7 @@ export class CalendarDayViewEventComponent {
7477

7578
@Input() tooltipTemplate: TemplateRef<any>;
7679

80+
@Input() tooltipDelay: number | null;
81+
7782
@Output() eventClicked: EventEmitter<any> = new EventEmitter();
7883
}

projects/angular-calendar/src/modules/day/calendar-day-view.component.ts

+8
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ export interface DayViewEventResize {
9090
[tooltipPlacement]="tooltipPlacement"
9191
[tooltipTemplate]="tooltipTemplate"
9292
[tooltipAppendToBody]="tooltipAppendToBody"
93+
[tooltipDelay]="tooltipDelay"
9394
[customTemplate]="eventTemplate"
9495
[eventTitleTemplate]="eventTitleTemplate"
9596
[eventActionsTemplate]="eventActionsTemplate"
@@ -166,6 +167,7 @@ export interface DayViewEventResize {
166167
[tooltipPlacement]="tooltipPlacement"
167168
[tooltipTemplate]="tooltipTemplate"
168169
[tooltipAppendToBody]="tooltipAppendToBody"
170+
[tooltipDelay]="tooltipDelay"
169171
[customTemplate]="eventTemplate"
170172
[eventTitleTemplate]="eventTitleTemplate"
171173
[eventActionsTemplate]="eventActionsTemplate"
@@ -283,6 +285,12 @@ export class CalendarDayViewComponent implements OnChanges, OnInit, OnDestroy {
283285
*/
284286
@Input() tooltipAppendToBody: boolean = true;
285287

288+
/**
289+
* The delay in milliseconds before the tooltip should be displayed. If not provided the tooltip
290+
* will be displayed immediately.
291+
*/
292+
@Input() tooltipDelay: number | null = null;
293+
286294
/**
287295
* A custom template to use to replace the hour segment
288296
*/

projects/angular-calendar/src/modules/month/calendar-month-cell.component.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { PlacementArray } from 'positioning';
2323
let-eventClicked="eventClicked"
2424
let-tooltipTemplate="tooltipTemplate"
2525
let-tooltipAppendToBody="tooltipAppendToBody"
26+
let-tooltipDelay="tooltipDelay"
2627
>
2728
<div class="cal-cell-top">
2829
<span class="cal-day-badge" *ngIf="day.badgeTotal > 0">{{
@@ -47,6 +48,7 @@ import { PlacementArray } from 'positioning';
4748
[tooltipEvent]="event"
4849
[tooltipTemplate]="tooltipTemplate"
4950
[tooltipAppendToBody]="tooltipAppendToBody"
51+
[tooltipDelay]="tooltipDelay"
5052
mwlDraggable
5153
[class.cal-draggable]="event.draggable"
5254
dragActiveClass="cal-drag-active"
@@ -67,7 +69,8 @@ import { PlacementArray } from 'positioning';
6769
unhighlightDay: unhighlightDay,
6870
eventClicked: eventClicked,
6971
tooltipTemplate: tooltipTemplate,
70-
tooltipAppendToBody: tooltipAppendToBody
72+
tooltipAppendToBody: tooltipAppendToBody,
73+
tooltipDelay: tooltipDelay
7174
}"
7275
>
7376
</ng-template>
@@ -101,6 +104,8 @@ export class CalendarMonthCellComponent {
101104

102105
@Input() tooltipTemplate: TemplateRef<any>;
103106

107+
@Input() tooltipDelay: number | null;
108+
104109
@Output() highlightDay: EventEmitter<any> = new EventEmitter();
105110

106111
@Output() unhighlightDay: EventEmitter<any> = new EventEmitter();

projects/angular-calendar/src/modules/month/calendar-month-view.component.ts

+7
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ export interface CalendarMonthViewEventTimesChangedEvent<
7979
[tooltipPlacement]="tooltipPlacement"
8080
[tooltipAppendToBody]="tooltipAppendToBody"
8181
[tooltipTemplate]="tooltipTemplate"
82+
[tooltipDelay]="tooltipDelay"
8283
[customTemplate]="cellTemplate"
8384
(mwlClick)="dayClicked.emit({ day: day })"
8485
(highlightDay)="toggleDayHighlight($event.event, true)"
@@ -172,6 +173,12 @@ export class CalendarMonthViewComponent
172173
*/
173174
@Input() tooltipAppendToBody: boolean = true;
174175

176+
/**
177+
* The delay in milliseconds before the tooltip should be displayed. If not provided the tooltip
178+
* will be displayed immediately.
179+
*/
180+
@Input() tooltipDelay: number | null = null;
181+
175182
/**
176183
* The start number of the week
177184
*/

projects/angular-calendar/src/modules/week/calendar-week-view-event.component.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { PlacementArray } from 'positioning';
1919
let-tooltipTemplate="tooltipTemplate"
2020
let-tooltipAppendToBody="tooltipAppendToBody"
2121
let-tooltipDisabled="tooltipDisabled"
22+
let-tooltipDelay="tooltipDelay"
2223
>
2324
<div
2425
class="cal-event"
@@ -34,6 +35,7 @@ import { PlacementArray } from 'positioning';
3435
[tooltipEvent]="weekEvent.event"
3536
[tooltipTemplate]="tooltipTemplate"
3637
[tooltipAppendToBody]="tooltipAppendToBody"
38+
[tooltipDelay]="tooltipDelay"
3739
(mwlClick)="eventClicked.emit()"
3840
>
3941
<mwl-calendar-event-actions
@@ -58,7 +60,8 @@ import { PlacementArray } from 'positioning';
5860
eventClicked: eventClicked,
5961
tooltipTemplate: tooltipTemplate,
6062
tooltipAppendToBody: tooltipAppendToBody,
61-
tooltipDisabled: tooltipDisabled
63+
tooltipDisabled: tooltipDisabled,
64+
tooltipDelay: tooltipDelay
6265
}"
6366
>
6467
</ng-template>
@@ -73,6 +76,8 @@ export class CalendarWeekViewEventComponent {
7376

7477
@Input() tooltipDisabled: boolean;
7578

79+
@Input() tooltipDelay: number | null;
80+
7681
@Input() customTemplate: TemplateRef<any>;
7782

7883
@Input() eventTitleTemplate: TemplateRef<any>;

projects/angular-calendar/src/modules/week/calendar-week-view.component.ts

+8
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ export interface CalendarWeekViewBeforeRenderEvent extends WeekView {
170170
[tooltipPlacement]="tooltipPlacement"
171171
[tooltipTemplate]="tooltipTemplate"
172172
[tooltipAppendToBody]="tooltipAppendToBody"
173+
[tooltipDelay]="tooltipDelay"
173174
[customTemplate]="eventTemplate"
174175
[eventTitleTemplate]="eventTitleTemplate"
175176
[eventActionsTemplate]="eventActionsTemplate"
@@ -293,6 +294,7 @@ export interface CalendarWeekViewBeforeRenderEvent extends WeekView {
293294
[tooltipTemplate]="tooltipTemplate"
294295
[tooltipAppendToBody]="tooltipAppendToBody"
295296
[tooltipDisabled]="dragActive || timeEventResizes.size > 0"
297+
[tooltipDelay]="tooltipDelay"
296298
[customTemplate]="eventTemplate"
297299
[eventTitleTemplate]="eventTitleTemplate"
298300
[eventActionsTemplate]="eventActionsTemplate"
@@ -390,6 +392,12 @@ export class CalendarWeekViewComponent implements OnChanges, OnInit, OnDestroy {
390392
*/
391393
@Input() tooltipAppendToBody: boolean = true;
392394

395+
/**
396+
* The delay in milliseconds before the tooltip should be displayed. If not provided the tooltip
397+
* will be displayed immediately.
398+
*/
399+
@Input() tooltipDelay: number | null = null;
400+
393401
/**
394402
* The start number of the week
395403
*/

projects/angular-calendar/test/calendar-month-view.component.spec.ts

+43-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import {
33
ComponentFixture,
44
TestBed,
55
fakeAsync,
6-
flush
6+
flush,
7+
tick
78
} from '@angular/core/testing';
89
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
910
import moment from 'moment';
@@ -541,6 +542,47 @@ describe('calendarMonthView component', () => {
541542
expect(!!document.body.querySelector('.cal-tooltip')).to.equal(false);
542543
}));
543544

545+
it('should show a tooltip on mouseover of the event after a delay', fakeAsync(() => {
546+
const fixture: ComponentFixture<
547+
CalendarMonthViewComponent
548+
> = TestBed.createComponent(CalendarMonthViewComponent);
549+
eventTitle.monthTooltip = (e: CalendarEvent) => {
550+
return `title: ${e.title}`;
551+
};
552+
fixture.componentInstance.viewDate = new Date('2016-06-27');
553+
fixture.componentInstance.events = [
554+
{
555+
start: new Date('2016-05-30'),
556+
end: new Date('2016-06-02'),
557+
title: 'foo <b>bar</b>'
558+
}
559+
];
560+
fixture.componentInstance.tooltipDelay = 2000;
561+
fixture.componentInstance.ngOnChanges({ viewDate: {}, events: {} });
562+
fixture.detectChanges();
563+
const event: HTMLElement = fixture.nativeElement.querySelector(
564+
'.cal-days .cal-cell-row .cal-cell:nth-child(4) .cal-events .cal-event'
565+
);
566+
triggerDomEvent('mouseenter', event);
567+
fixture.detectChanges();
568+
tick(fixture.componentInstance.tooltipDelay - 1);
569+
expect(!!document.body.querySelector('.cal-tooltip')).to.equal(false);
570+
tick(1);
571+
expect(!!document.body.querySelector('.cal-tooltip')).to.equal(true);
572+
const tooltip: HTMLElement = document.body.querySelector(
573+
'.cal-tooltip'
574+
) as HTMLElement;
575+
expect(tooltip.querySelector('.cal-tooltip-inner').innerHTML).to.equal(
576+
'title: foo <b>bar</b>'
577+
);
578+
expect(tooltip.classList.contains('cal-tooltip-top')).to.equal(true);
579+
expect(!!tooltip.style.top).to.equal(true);
580+
expect(!!tooltip.style.left).to.equal(true);
581+
triggerDomEvent('mouseleave', event);
582+
fixture.detectChanges();
583+
expect(!!document.body.querySelector('.cal-tooltip')).to.equal(false);
584+
}));
585+
544586
it('should disable the tooltip', fakeAsync(() => {
545587
const fixture: ComponentFixture<
546588
CalendarMonthViewComponent

0 commit comments

Comments
 (0)