feat(tooltip): add input for delaying show and hide (#2101)

* feat(tooltip): add input for delaying show and hide

* change input for delays to number

* remove fakeasyc from tests that dont need show tick

* fix comment

* rename new inputs to camelCase
This commit is contained in:
Andrew Seguin
2016-12-09 15:18:23 -08:00
committed by mmalerba
parent ca2046b967
commit e85d1080ef
4 changed files with 92 additions and 26 deletions
+14 -2
View File
@@ -6,7 +6,9 @@
md-raised-button
color="primary"
[md-tooltip]="message"
[tooltip-position]="position">
[tooltip-position]="position"
[tooltipShowDelay]="showDelay"
[tooltipHideDelay]="hideDelay">
Mouse over to see the tooltip
</button>
</p>
@@ -27,11 +29,21 @@
<md-input-container><input md-input type="text" [(ngModel)]="message"></md-input-container>
</p>
<p>
<strong>Show Delay (ms): </strong>
<md-input type="number" [(ngModel)]="showDelay"></md-input>
</p>
<p>
<strong>Hide Delay (ms): </strong>
<md-input type="number" [(ngModel)]="hideDelay"></md-input>
</p>
<strong>Mouse over to</strong>
<button md-raised-button color="primary" (mouseenter)="tooltip.show()">
Show tooltip
</button>
<button md-raised-button color="primary" (mouseenter)="tooltip.hide(0)">
<button md-raised-button color="primary" (mouseenter)="tooltip.hide()">
Hide tooltip
</button>
<button md-raised-button color="primary" (mouseenter)="tooltip.toggle()">
+2
View File
@@ -11,4 +11,6 @@ import {TooltipPosition} from '@angular/material';
export class TooltipDemo {
position: TooltipPosition = 'below';
message: string = 'Here is the tooltip';
showDelay = 0;
hideDelay = 0;
}
+40 -6
View File
@@ -54,6 +54,7 @@ describe('MdTooltip', () => {
expect(tooltipDirective._tooltipInstance).toBeUndefined();
tooltipDirective.show();
tick(0); // Tick for the show delay (default is 0)
expect(tooltipDirective._isTooltipVisible()).toBe(true);
fixture.detectChanges();
@@ -74,7 +75,37 @@ describe('MdTooltip', () => {
expect(tooltipDirective._tooltipInstance).toBeNull();
}));
it('should not show tooltip if message is not present or empty', fakeAsync(() => {
it('should show with delay', fakeAsync(() => {
expect(tooltipDirective._tooltipInstance).toBeUndefined();
const tooltipDelay = 1000;
tooltipDirective.show(tooltipDelay);
expect(tooltipDirective._isTooltipVisible()).toBe(false);
fixture.detectChanges();
expect(overlayContainerElement.textContent).toContain('');
tick(tooltipDelay);
expect(tooltipDirective._isTooltipVisible()).toBe(true);
expect(overlayContainerElement.textContent).toContain(initialTooltipMessage);
}));
it('should not show if hide is called before delay finishes', fakeAsync(() => {
expect(tooltipDirective._tooltipInstance).toBeUndefined();
const tooltipDelay = 1000;
tooltipDirective.show(tooltipDelay);
expect(tooltipDirective._isTooltipVisible()).toBe(false);
fixture.detectChanges();
expect(overlayContainerElement.textContent).toContain('');
tooltipDirective.hide();
tick(tooltipDelay);
expect(tooltipDirective._isTooltipVisible()).toBe(false);
}));
it('should not show tooltip if message is not present or empty', () => {
expect(tooltipDirective._tooltipInstance).toBeUndefined();
tooltipDirective.message = undefined;
@@ -96,10 +127,11 @@ describe('MdTooltip', () => {
fixture.detectChanges();
tooltipDirective.show();
expect(tooltipDirective._tooltipInstance).toBeUndefined();
}));
});
it('should not follow through with hide if show is called after', fakeAsync(() => {
tooltipDirective.show();
tick(0); // Tick for the show delay (default is 0)
expect(tooltipDirective._isTooltipVisible()).toBe(true);
// After hide called, a timeout delay is created that will to hide the tooltip.
@@ -133,10 +165,11 @@ describe('MdTooltip', () => {
expect(tooltipDirective._overlayRef).toBeNull();
});
it('should be able to modify the tooltip message', () => {
it('should be able to modify the tooltip message', fakeAsync(() => {
expect(tooltipDirective._tooltipInstance).toBeUndefined();
tooltipDirective.show();
tick(0); // Tick for the show delay (default is 0)
expect(tooltipDirective._tooltipInstance._visibility).toBe('visible');
fixture.detectChanges();
@@ -147,16 +180,17 @@ describe('MdTooltip', () => {
fixture.detectChanges();
expect(overlayContainerElement.textContent).toContain(newMessage);
});
}));
it('should be removed after parent destroyed', () => {
it('should be removed after parent destroyed', fakeAsync(() => {
tooltipDirective.show();
tick(0); // Tick for the show delay (default is 0)
expect(tooltipDirective._isTooltipVisible()).toBe(true);
fixture.destroy();
expect(overlayContainerElement.childNodes.length).toBe(0);
expect(overlayContainerElement.textContent).toBe('');
});
}));
it('should not try to dispose the tooltip when destroyed and done hiding', fakeAsync(() => {
tooltipDirective.show();
+36 -18
View File
@@ -74,6 +74,12 @@ export class MdTooltip {
}
}
/** The default delay in ms before showing the tooltip after show is called */
@Input('tooltipShowDelay') showDelay = 0;
/** The default delay in ms before hiding the tooltip after hide is called */
@Input('tooltipHideDelay') hideDelay = 0;
/** The message to be displayed in the tooltip */
private _message: string;
@Input('md-tooltip') get message() {
@@ -97,22 +103,20 @@ export class MdTooltip {
}
}
/** Shows the tooltip */
show(): void {
if (!this._message || !this._message.trim()) {
return;
}
/** Shows the tooltip after the delay in ms, defaults to tooltip-delay-show or 0ms if no input */
show(delay: number = this.showDelay): void {
if (!this._message || !this._message.trim()) { return; }
if (!this._tooltipInstance) {
this._createTooltip();
}
this._setTooltipMessage(this._message);
this._tooltipInstance.show(this._position);
this._tooltipInstance.show(this._position, delay);
}
/** Hides the tooltip after the provided delay in ms, defaulting to 0ms. */
hide(delay = 0): void {
/** Hides the tooltip after the delay in ms, defaults to tooltip-delay-hide or 0ms if no input */
hide(delay: number = this.hideDelay): void {
if (this._tooltipInstance) {
this._tooltipInstance.hide(delay);
}
@@ -222,7 +226,7 @@ export class MdTooltip {
}
}
export type TooltipVisibility = 'visible' | 'hidden';
export type TooltipVisibility = 'initial' | 'visible' | 'hidden';
@Component({
moduleId: module.id,
@@ -232,6 +236,7 @@ export type TooltipVisibility = 'visible' | 'hidden';
animations: [
trigger('state', [
state('void', style({transform: 'scale(0)'})),
state('initial', style({transform: 'scale(0)'})),
state('visible', style({transform: 'scale(1)'})),
state('hidden', style({transform: 'scale(0)'})),
transition('* => visible', animate('150ms cubic-bezier(0.0, 0.0, 0.2, 1)')),
@@ -246,11 +251,14 @@ export class TooltipComponent {
/** Message to display in the tooltip */
message: string;
/** The timeout ID of any current timer set to show the tooltip */
_showTimeoutId: number;
/** The timeout ID of any current timer set to hide the tooltip */
_hideTimeoutId: number;
/** Property watched by the animation framework to show or hide the tooltip */
_visibility: TooltipVisibility;
_visibility: TooltipVisibility = 'initial';
/** Whether interactions on the page should close the tooltip */
_closeOnInteraction: boolean = false;
@@ -264,23 +272,33 @@ export class TooltipComponent {
constructor(@Optional() private _dir: Dir) {}
/** Shows the tooltip with an animation originating from the provided origin */
show(position: TooltipPosition): void {
this._closeOnInteraction = false;
this._visibility = 'visible';
this._setTransformOrigin(position);
show(position: TooltipPosition, delay: number): void {
// Cancel the delayed hide if it is scheduled
if (this._hideTimeoutId) {
clearTimeout(this._hideTimeoutId);
}
// If this was set to true immediately, then the body click would trigger interaction and
// close the tooltip right after it was displayed.
setTimeout(() => { this._closeOnInteraction = true; }, 0);
// Body interactions should cancel the tooltip if there is a delay in showing.
this._closeOnInteraction = true;
this._setTransformOrigin(position);
this._showTimeoutId = setTimeout(() => {
this._visibility = 'visible';
// If this was set to true immediately, then a body click that triggers show() would
// trigger interaction and close the tooltip right after it was displayed.
this._closeOnInteraction = false;
setTimeout(() => { this._closeOnInteraction = true; }, 0);
}, delay);
}
/** Begins the animation to hide the tooltip after the provided delay in ms */
hide(delay: number): void {
// Cancel the delayed show if it is scheduled
if (this._showTimeoutId) {
clearTimeout(this._showTimeoutId);
}
this._hideTimeoutId = setTimeout(() => {
this._visibility = 'hidden';
this._closeOnInteraction = false;