Skip to content

Commit 9e27017

Browse files
committed
Merge branch 'feature/align-tooltip' of https://github.com/IgniteUI/igniteui-angular into feature/align-tooltip
2 parents aad5727 + 07eefb7 commit 9e27017

File tree

4 files changed

+112
-152
lines changed

4 files changed

+112
-152
lines changed

projects/igniteui-angular/src/lib/directives/tooltip/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,8 @@ Since the **IgxTooltip** directive extends the **IgxToggle** directive and there
104104
### Methods
105105
| Name | Type | Arguments | Description |
106106
| :--- |:--- | :--- | :--- |
107-
| showTooltip | void | N/A | Shows the tooltip after the amount of ms specified by the `showDelay` property. |
108-
| hideTooltip | void | N/A | Hides the tooltip after the amount of ms specified by the `hideDelay` property. |
107+
| showTooltip | void | N/A | Shows the tooltip. |
108+
| hideTooltip | void | N/A | Hides the tooltip. |
109109

110110
### Events
111111
|Name|Description|Cancelable|Event arguments|

projects/igniteui-angular/src/lib/directives/tooltip/tooltip-target.directive.ts

Lines changed: 65 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
5656
* ```
5757
*/
5858
@Input()
59-
public showDelay = 500;
59+
public showDelay = 200;
6060

6161
/**
6262
* Gets/sets the amount of milliseconds that should pass before hiding the tooltip.
@@ -73,7 +73,7 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
7373
* ```
7474
*/
7575
@Input()
76-
public hideDelay = 500;
76+
public hideDelay = 300;
7777

7878
/**
7979
* Controls whether the arrow element of the tooltip is rendered.
@@ -275,7 +275,8 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
275275
@Output()
276276
public tooltipHide = new EventEmitter<ITooltipHideEventArgs>();
277277

278-
private destroy$ = new Subject<void>();
278+
private _destroy$ = new Subject<void>();
279+
private _autoHideDelay = 180;
279280

280281
constructor(private _element: ElementRef,
281282
@Optional() private _navigationService: IgxNavigationService, private _viewContainerRef: ViewContainerRef) {
@@ -288,7 +289,7 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
288289
@HostListener('click')
289290
public override onClick() {
290291
if (!this.target.collapsed) {
291-
this.target.forceClose(this.mergedOverlaySettings);
292+
this._hideOnInteraction();
292293
}
293294
}
294295

@@ -301,24 +302,8 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
301302
return;
302303
}
303304

304-
this.checkOutletAndOutsideClick();
305-
const shouldReturn = this.preMouseEnterCheck();
306-
if (shouldReturn) {
307-
return;
308-
}
309-
310-
const showingArgs = { target: this, tooltip: this.target, cancel: false };
311-
this.tooltipShow.emit(showingArgs);
312-
313-
if (showingArgs.cancel) {
314-
return;
315-
}
316-
317-
this.target.toBeShown = true;
318-
this.target.timeoutId = setTimeout(() => {
319-
this.target.open(this.mergedOverlaySettings); // Call open() of IgxTooltipDirective
320-
this.target.toBeShown = false;
321-
}, this.showDelay);
305+
this._checkOutletAndOutsideClick();
306+
this._showOnInteraction();
322307
}
323308

324309
/**
@@ -334,19 +319,8 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
334319
return;
335320
}
336321

337-
this.checkOutletAndOutsideClick();
338-
const shouldReturn = this.preMouseLeaveCheck();
339-
if (shouldReturn || this.target.collapsed) {
340-
return;
341-
}
342-
343-
this.target.toBeHidden = true;
344-
this.target.timeoutId = setTimeout(() => {
345-
this.target.close(); // Call close() of IgxTooltipDirective
346-
this.target.toBeHidden = false;
347-
}, this.hideDelay);
348-
349-
322+
this._checkOutletAndOutsideClick();
323+
this._hideOnInteraction();
350324
}
351325

352326
/**
@@ -358,7 +332,7 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
358332
return;
359333
}
360334

361-
this.showTooltip();
335+
this._showOnInteraction();
362336
}
363337

364338
/**
@@ -373,7 +347,7 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
373347
if (this.nativeElement !== event.target &&
374348
!this.nativeElement.contains(event.target)
375349
) {
376-
this.hideTooltip();
350+
this._hideOnInteraction();
377351
}
378352
}
379353

@@ -394,118 +368,110 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
394368
this._overlayDefaults.closeOnOutsideClick = false;
395369
this._overlayDefaults.closeOnEscape = true;
396370

397-
this.target.closing.pipe(takeUntil(this.destroy$)).subscribe((event) => {
371+
this.target.closing.pipe(takeUntil(this._destroy$)).subscribe((event) => {
398372
const hidingArgs = { target: this, tooltip: this.target, cancel: false };
399373
this.tooltipHide.emit(hidingArgs);
400374

401375
if (hidingArgs.cancel) {
402376
event.cancel = true;
403377
}
404378
});
379+
380+
this.target.onShow = this._showOnInteraction.bind(this);
381+
this.target.onHide = this._hideOnInteraction.bind(this);
405382
}
406383

407384
/**
408385
* @hidden
409386
*/
410387
public ngOnDestroy() {
411-
this.destroy$.next();
412-
this.destroy$.complete();
388+
this._destroy$.next();
389+
this._destroy$.complete();
413390
}
414391

415392
/**
416-
* Shows the tooltip by respecting the 'showDelay' property.
393+
* Shows the tooltip if not already shown.
417394
*
418395
* ```typescript
419396
* this.tooltipTarget.showTooltip();
420397
* ```
421398
*/
422399
public showTooltip() {
423-
clearTimeout(this.target.timeoutId);
424-
425-
if (!this.target.collapsed) {
426-
// if close animation has started finish it, or close the tooltip with no animation
427-
this.target.forceClose(this.mergedOverlaySettings);
428-
this.target.toBeHidden = false;
429-
}
430-
431-
const showingArgs = { target: this, tooltip: this.target, cancel: false };
432-
this.tooltipShow.emit(showingArgs);
433-
434-
if (showingArgs.cancel) {
435-
return;
436-
}
437-
438-
this.target.toBeShown = true;
439-
this.target.timeoutId = setTimeout(() => {
440-
this.target.open(this.mergedOverlaySettings); // Call open() of IgxTooltipDirective
441-
this.target.toBeShown = false;
442-
}, this.showDelay);
400+
this._showTooltip(false, true);
443401
}
444402

445403
/**
446-
* Hides the tooltip by respecting the 'hideDelay' property.
404+
* Hides the tooltip if not already hidden.
447405
*
448406
* ```typescript
449407
* this.tooltipTarget.hideTooltip();
450408
* ```
451409
*/
452410
public hideTooltip() {
453-
if (this.target.collapsed && this.target.toBeShown) {
454-
clearTimeout(this.target.timeoutId);
455-
}
456-
457-
if (this.target.collapsed || this.target.toBeHidden) {
458-
return;
459-
}
411+
this._hideTooltip(false);
412+
}
460413

461-
this.target.toBeHidden = true;
462-
this.target.timeoutId = setTimeout(() => {
463-
this.target.close(); // Call close() of IgxTooltipDirective
464-
this.target.toBeHidden = false;
465-
}, this.hideDelay);
414+
private get _mergedOverlaySettings() {
415+
return Object.assign({}, this._overlayDefaults, this.overlaySettings);
466416
}
467417

468-
private checkOutletAndOutsideClick() {
418+
private _checkOutletAndOutsideClick(): void {
469419
if (this.outlet) {
470420
this._overlayDefaults.outlet = this.outlet;
471421
}
472422
}
473423

474-
private get mergedOverlaySettings() {
475-
return Object.assign({}, this._overlayDefaults, this.overlaySettings);
424+
private _hideTooltip(withDelay: boolean): void {
425+
if (this.target.collapsed) {
426+
return;
427+
}
428+
429+
this.target.timeoutId = setTimeout(() => {
430+
// Call close() of IgxTooltipDirective
431+
this.target.close();
432+
}, withDelay ? this.hideDelay : 0);
476433
}
477434

478-
// Return true if the execution in onMouseEnter should be terminated after this method
479-
private preMouseEnterCheck() {
480-
// If tooltip is about to be opened
481-
if (this.target.toBeShown) {
482-
clearTimeout(this.target.timeoutId);
483-
this.target.toBeShown = false;
435+
private _showTooltip(withDelay: boolean, withEvents: boolean): void {
436+
if (!this.target.collapsed) {
437+
return;
484438
}
485439

486-
// If Tooltip is opened or about to be hidden
487-
if (!this.target.collapsed || this.target.toBeHidden) {
488-
clearTimeout(this.target.timeoutId);
440+
if (withEvents) {
441+
const showingArgs = { target: this, tooltip: this.target, cancel: false };
442+
this.tooltipShow.emit(showingArgs);
489443

490-
// if close animation has started finish it, or close the tooltip with no animation
491-
this.target.forceClose(this.mergedOverlaySettings);
492-
this.target.toBeHidden = false;
444+
if (showingArgs.cancel) return;
493445
}
494446

495-
return false;
447+
this.target.timeoutId = setTimeout(() => {
448+
// Call open() of IgxTooltipDirective
449+
this.target.open(this._mergedOverlaySettings);
450+
}, withDelay ? this.showDelay : 0);
496451
}
497452

498-
// Return true if the execution in onMouseLeave should be terminated after this method
499-
private preMouseLeaveCheck(): boolean {
500-
clearTimeout(this.target.timeoutId);
501453

502-
// If tooltip is about to be opened
503-
if (this.target.toBeShown) {
504-
this.target.toBeShown = false;
505-
this.target.toBeHidden = false;
506-
return true;
454+
private _showOnInteraction(): void {
455+
this._stopTimeoutAndAnimation();
456+
this._showTooltip(true, true);
457+
}
458+
459+
private _hideOnInteraction(): void {
460+
if (!this.target.sticky) {
461+
this._setAutoHide();
507462
}
463+
}
464+
465+
private _setAutoHide(): void {
466+
this._stopTimeoutAndAnimation();
467+
468+
this.target.timeoutId = setTimeout(() => {
469+
this._hideTooltip(true);
470+
}, this._autoHideDelay);
471+
}
508472

509-
return false;
473+
private _stopTimeoutAndAnimation(): void {
474+
clearTimeout(this.target.timeoutId);
475+
this.target.stopAnimations();
510476
}
511477
}

projects/igniteui-angular/src/lib/directives/tooltip/tooltip.directive.spec.ts

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ describe('IgxTooltip', () => {
4646
}));
4747

4848
it('IgxTooltipTargetDirective default values', () => {
49-
expect(tooltipTarget.showDelay).toBe(500);
50-
expect(tooltipTarget.hideDelay).toBe(500);
49+
expect(tooltipTarget.showDelay).toBe(200);
50+
expect(tooltipTarget.hideDelay).toBe(300);
5151
expect(tooltipTarget.tooltipDisabled).toBe(false);
5252
expect(tooltipTarget.overlaySettings).toBeUndefined();
5353
});
@@ -156,20 +156,17 @@ describe('IgxTooltip', () => {
156156
verifyTooltipVisibility(tooltipNativeElement, tooltipTarget, false);
157157
}));
158158

159-
it('showing tooltip through API respects showDelay', fakeAsync(() => {
159+
it('showing tooltip through API does NOT respect showDelay', fakeAsync(() => {
160160
tooltipTarget.showDelay = 400;
161161
fix.detectChanges();
162162

163163
tooltipTarget.showTooltip();
164164

165165
tick(300);
166-
verifyTooltipVisibility(tooltipNativeElement, tooltipTarget, false);
167-
168-
tick(100);
169166
verifyTooltipVisibility(tooltipNativeElement, tooltipTarget, true);
170167
}));
171168

172-
it('hiding tooltip through API respects hideDelay', fakeAsync(() => {
169+
it('hiding tooltip through API does NOT respect hideDelay', fakeAsync(() => {
173170
tooltipTarget.hideDelay = 450;
174171
fix.detectChanges();
175172

@@ -179,9 +176,6 @@ describe('IgxTooltip', () => {
179176
tooltipTarget.hideTooltip();
180177

181178
tick(400);
182-
verifyTooltipVisibility(tooltipNativeElement, tooltipTarget, true);
183-
184-
tick(50);
185179
verifyTooltipVisibility(tooltipNativeElement, tooltipTarget, false);
186180
}));
187181

@@ -193,25 +187,21 @@ describe('IgxTooltip', () => {
193187

194188
hoverElement(button);
195189

196-
tick(250);
190+
tick(100);
197191
verifyTooltipVisibility(tooltipNativeElement, tooltipTarget, false);
198192

199-
tick(250);
193+
tick(100);
200194
verifyTooltipVisibility(tooltipNativeElement, tooltipTarget, true);
201195
}));
202196

203197
it('IgxTooltip closes and reopens if opening it through API multiple times', fakeAsync(() => {
204-
tooltipTarget.showTooltip();
205-
tick(500);
206-
207-
verifyTooltipVisibility(tooltipNativeElement, tooltipTarget, true);
198+
spyOn(tooltipTarget.target, 'forceClose').and.callThrough();
208199

209200
tooltipTarget.showTooltip();
210-
tick(250);
211-
verifyTooltipVisibility(tooltipNativeElement, tooltipTarget, false);
201+
tick();
212202

213-
tick(250);
214-
verifyTooltipVisibility(tooltipNativeElement, tooltipTarget, true);
203+
tooltipTarget.showTooltip();
204+
expect(tooltipTarget.target.forceClose).toHaveBeenCalledTimes(1);
215205
}));
216206

217207
it('IgxTooltip respects the passed overlaySettings', fakeAsync(() => {

0 commit comments

Comments
 (0)