Skip to content
This repository was archived by the owner on May 29, 2019. It is now read-only.

Commit 6daf871

Browse files
RobJacobswesleycho
authored andcommitted
fix(tooltip): popup close delay not respected
Under PR #4455 the timeout for the popup close delay was impacted by the evalAsync for setting the isOpen value. Moved the popup close delay timeout to the hideTooltipBind method so the hide method will now get called after the close popup delay. This will also ensure if the show method is called and the close timeout is cancelled, the isOpen property will not get toggled. Closes #4597 Fixes #4567
1 parent be5802a commit 6daf871

File tree

5 files changed

+60
-40
lines changed

5 files changed

+60
-40
lines changed

Diff for: src/popover/docs/readme.md

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ will display:
2222
- `popover-animation`: Should it fade in and out? Defaults to "true".
2323
- `popover-popup-delay`: For how long should the user have to have the mouse
2424
over the element before the popover shows (in milliseconds)? Defaults to 0.
25+
- `popover-close-popup-delay`: For how long should the popover remain open
26+
after the close trigger event? Defaults to 0.
2527
- `popover-trigger`: What should trigger the show of the popover? See the
2628
`tooltip` directive for supported values.
2729
- `popover-append-to-body`: Should the tooltip be appended to `$body` instead of

Diff for: src/tooltip/docs/demo.html

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
pharetra convallis posuere morbi leo urna,
2020
<a href="#" tooltip-animation="false" uib-tooltip="I don't fade. :-(">fading</a>
2121
at elementum eu, facilisis sed odio morbi quis commodo odio. In cursus
22-
<a href="#" tooltip-popup-delay='1000' uib-tooltip='appears with delay'>delayed</a> turpis massa tincidunt dui ut.
22+
<a href="#" tooltip-popup-delay='1000' uib-tooltip='appears with delay'>show delay</a>
23+
turpis massa tincidunt dui ut. In cursus
24+
<a href="#" tooltip-popup-close-delay='1000' uib-tooltip='hides with delay'>hide delay</a>
2325
<a href="#" uib-tooltip-template="'myTooltipTemplate.html'">Custom template</a>
2426
nunc sed velit dignissim sodales ut eu sem integer vitae. Turpis egestas
2527
</p>

Diff for: src/tooltip/docs/readme.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ will display:
2020
- `tooltip-animation`: Should it fade in and out? Defaults to "true".
2121
- `tooltip-popup-delay`: For how long should the user have to have the mouse
2222
over the element before the tooltip shows (in milliseconds)? Defaults to 0.
23-
- `tooltip-close-popup-delay`: For how long should the tooltip remained open?
23+
- `tooltip-close-popup-delay`: For how long should the tooltip remain open
24+
after the close trigger event? Defaults to 0.
2425
- `tooltip-trigger`: What should trigger a show of the tooltip? Supports a space separated list of event names.
2526
Note: this attribute is no longer observable. See `tooltip-enable`.
2627
- `tooltip-enable`: Is it enabled? It will enable or disable the configured

Diff for: src/tooltip/test/tooltip.spec.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -386,11 +386,11 @@ describe('tooltip', function() {
386386
expect(tooltipScope.isOpen).toBe(false);
387387
});
388388

389-
it('should use default popup close delay if specified delay is not a number and close after delay', function() {
389+
it('should use default popup close delay if specified delay is not a number and close immediately', function() {
390390
scope.delay = 'text1000';
391391
scope.$digest();
392392
trigger(elm, 'mouseenter');
393-
expect(tooltipScope.popupCloseDelay).toBe(500);
393+
expect(tooltipScope.popupCloseDelay).toBe(0);
394394
expect(tooltipScope.isOpen).toBe(true);
395395
trigger(elm, 'mouseleave');
396396
$timeout.flush();

Diff for: src/tooltip/tooltip.js

+51-36
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
1515
placement: 'top',
1616
animation: true,
1717
popupDelay: 0,
18-
popupCloseDelay: 500,
18+
popupCloseDelay: 0,
1919
useContentExp: false
2020
};
2121

@@ -135,7 +135,8 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
135135
var tooltip;
136136
var tooltipLinkedScope;
137137
var transitionTimeout;
138-
var popupTimeout;
138+
var showTimeout;
139+
var hideTimeout;
139140
var positionTimeout;
140141
var appendToBody = angular.isDefined(options.appendToBody) ? options.appendToBody : false;
141142
var triggers = getTriggers(undefined);
@@ -196,27 +197,35 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
196197
if (ttScope.popupDelay) {
197198
// Do nothing if the tooltip was already scheduled to pop-up.
198199
// This happens if show is triggered multiple times before any hide is triggered.
199-
if (!popupTimeout) {
200-
popupTimeout = $timeout(show, ttScope.popupDelay, false);
200+
if (!showTimeout) {
201+
showTimeout = $timeout(show, ttScope.popupDelay, false);
201202
}
202203
} else {
203204
show();
204205
}
205206
}
206207

207208
function hideTooltipBind() {
208-
hide();
209+
if (ttScope.popupCloseDelay) {
210+
hideTimeout = $timeout(hide, ttScope.popupCloseDelay, false);
211+
} else {
212+
hide();
213+
}
209214
}
210215

211216
// Show the tooltip popup element.
212217
function show() {
213-
if (popupTimeout) {
214-
$timeout.cancel(popupTimeout);
215-
popupTimeout = null;
218+
if (showTimeout) {
219+
$timeout.cancel(showTimeout);
220+
showTimeout = null;
216221
}
217222

218223
// If there is a pending remove transition, we must cancel it, lest the
219224
// tooltip be mysteriously removed.
225+
if (hideTimeout) {
226+
$timeout.cancel(hideTimeout);
227+
hideTimeout = null;
228+
}
220229
if (transitionTimeout) {
221230
$timeout.cancel(transitionTimeout);
222231
transitionTimeout = null;
@@ -232,10 +241,7 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
232241
// And show the tooltip.
233242
ttScope.$evalAsync(function() {
234243
ttScope.isOpen = true;
235-
if (isOpenParse && angular.isFunction(isOpenParse.assign)) {
236-
isOpenParse.assign(ttScope.origScope, ttScope.isOpen);
237-
}
238-
244+
assignIsOpen(true);
239245
positionTooltip();
240246
});
241247
}
@@ -246,31 +252,33 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
246252
return;
247253
}
248254

255+
//if tooltip is going to be shown after delay, we must cancel this
256+
if (showTimeout) {
257+
$timeout.cancel(showTimeout);
258+
showTimeout = null;
259+
}
260+
261+
if (positionTimeout) {
262+
$timeout.cancel(positionTimeout);
263+
positionTimeout = null;
264+
}
265+
249266
// First things first: we don't show it anymore.
250267
ttScope.$evalAsync(function() {
251268
ttScope.isOpen = false;
252-
if (isOpenParse && angular.isFunction(isOpenParse.assign)) {
253-
isOpenParse.assign(ttScope.origScope, ttScope.isOpen);
269+
assignIsOpen(false);
270+
// And now we remove it from the DOM. However, if we have animation, we
271+
// need to wait for it to expire beforehand.
272+
// FIXME: this is a placeholder for a port of the transitions library.
273+
// The fade transition in TWBS is 150ms.
274+
if (ttScope.animation) {
275+
if (!transitionTimeout) {
276+
transitionTimeout = $timeout(removeTooltip, 150, false);
277+
}
278+
} else {
279+
removeTooltip();
254280
}
255281
});
256-
257-
//if tooltip is going to be shown after delay, we must cancel this
258-
$timeout.cancel(popupTimeout);
259-
popupTimeout = null;
260-
261-
$timeout.cancel(positionTimeout);
262-
positionTimeout = null;
263-
264-
// And now we remove it from the DOM. However, if we have animation, we
265-
// need to wait for it to expire beforehand.
266-
// FIXME: this is a placeholder for a port of the transitions library.
267-
if (ttScope.animation) {
268-
if (!transitionTimeout) {
269-
transitionTimeout = $timeout(removeTooltip, ttScope.popupCloseDelay);
270-
}
271-
} else {
272-
removeTooltip();
273-
}
274282
}
275283

276284
function createTooltip() {
@@ -327,6 +335,12 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
327335
ttScope.popupCloseDelay = !isNaN(closeDelay) ? closeDelay : options.popupCloseDelay;
328336
}
329337

338+
function assignIsOpen(isOpen) {
339+
if (isOpenParse && angular.isFunction(isOpenParse.assign)) {
340+
isOpenParse.assign(scope, isOpen);
341+
}
342+
}
343+
330344
ttScope.contentExp = function() {
331345
return ttScope.content;
332346
};
@@ -335,9 +349,9 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
335349
* Observe the relevant attributes.
336350
*/
337351
attrs.$observe('disabled', function(val) {
338-
if (popupTimeout && val) {
339-
$timeout.cancel(popupTimeout);
340-
popupTimeout = null;
352+
if (showTimeout && val) {
353+
$timeout.cancel(showTimeout);
354+
showTimeout = null;
341355
}
342356

343357
if (val && ttScope.isOpen) {
@@ -482,7 +496,8 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
482496
// Make sure tooltip is destroyed and removed.
483497
scope.$on('$destroy', function onDestroyTooltip() {
484498
$timeout.cancel(transitionTimeout);
485-
$timeout.cancel(popupTimeout);
499+
$timeout.cancel(showTimeout);
500+
$timeout.cancel(hideTimeout);
486501
$timeout.cancel(positionTimeout);
487502
unregisterTriggers();
488503
removeTooltip();

0 commit comments

Comments
 (0)