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

Commit

Permalink
fix(tooltip): delay timeouts
Browse files Browse the repository at this point in the history
The show and hide delay timeouts where not getting
cancelled correctly resulting in tooltips staying
open when both popup and popup-close delays were
in use.

Closes #4621
Fixes #4618
RobJacobs authored and wesleycho committed Oct 14, 2015
1 parent 6c82b2b commit 02425b8
Showing 2 changed files with 57 additions and 30 deletions.
23 changes: 23 additions & 0 deletions src/tooltip/test/tooltip.spec.js
Original file line number Diff line number Diff line change
@@ -419,6 +419,29 @@ describe('tooltip', function() {
});
});

describe('with specified popup and popup close delay', function() {
var $timeout;
beforeEach(inject(function($compile, _$timeout_) {
$timeout = _$timeout_;
scope.delay = '1000';
elm = $compile(angular.element(
'<span uib-tooltip="tooltip text" tooltip-popup-close-delay="{{delay}}" tooltip-popup-close-delay="{{delay}}" ng-disabled="disabled">Selector Text</span>'
))(scope);
elmScope = elm.scope();
tooltipScope = elmScope.$$childTail;
scope.$digest();
}));

it('should not open if mouseleave before timeout', function() {
trigger(elm, 'mouseenter');
$timeout.flush(500);
trigger(elm, 'mouseleave');
$timeout.flush();

expect(tooltipScope.isOpen).toBe(false);
});
});

describe('with an is-open attribute', function() {
beforeEach(inject(function ($compile) {
scope.isOpen = false;
64 changes: 34 additions & 30 deletions src/tooltip/tooltip.js
Original file line number Diff line number Diff line change
@@ -192,6 +192,7 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
return;
}

cancelHide();
prepareTooltip();

if (ttScope.popupDelay) {
@@ -206,30 +207,21 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
}

function hideTooltipBind() {
cancelShow();

if (ttScope.popupCloseDelay) {
hideTimeout = $timeout(hide, ttScope.popupCloseDelay, false);
if (!hideTimeout) {
hideTimeout = $timeout(hide, ttScope.popupCloseDelay, false);
}
} else {
hide();
}
}

// Show the tooltip popup element.
function show() {
if (showTimeout) {
$timeout.cancel(showTimeout);
showTimeout = null;
}

// If there is a pending remove transition, we must cancel it, lest the
// tooltip be mysteriously removed.
if (hideTimeout) {
$timeout.cancel(hideTimeout);
hideTimeout = null;
}
if (transitionTimeout) {
$timeout.cancel(transitionTimeout);
transitionTimeout = null;
}
cancelShow();
cancelHide();

// Don't show empty tooltips.
if (!ttScope.content) {
@@ -246,13 +238,7 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
});
}

// Hide the tooltip popup element.
function hide() {
if (!ttScope) {
return;
}

//if tooltip is going to be shown after delay, we must cancel this
function cancelShow() {
if (showTimeout) {
$timeout.cancel(showTimeout);
showTimeout = null;
@@ -262,6 +248,16 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
$timeout.cancel(positionTimeout);
positionTimeout = null;
}
}

// Hide the tooltip popup element.
function hide() {
cancelShow();
cancelHide();

if (!ttScope) {
return;
}

// First things first: we don't show it anymore.
ttScope.$evalAsync(function() {
@@ -281,6 +277,17 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
});
}

function cancelHide() {
if (hideTimeout) {
$timeout.cancel(hideTimeout);
hideTimeout = null;
}
if (transitionTimeout) {
$timeout.cancel(transitionTimeout);
transitionTimeout = null;
}
}

function createTooltip() {
// There can only be one tooltip element per directive shown at once.
if (tooltip) {
@@ -349,9 +356,8 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
* Observe the relevant attributes.
*/
attrs.$observe('disabled', function(val) {
if (showTimeout && val) {
$timeout.cancel(showTimeout);
showTimeout = null;
if (val) {
cancelShow();
}

if (val && ttScope.isOpen) {
@@ -495,10 +501,8 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s

// Make sure tooltip is destroyed and removed.
scope.$on('$destroy', function onDestroyTooltip() {
$timeout.cancel(transitionTimeout);
$timeout.cancel(showTimeout);
$timeout.cancel(hideTimeout);
$timeout.cancel(positionTimeout);
cancelShow();
cancelHide();
unregisterTriggers();
removeTooltip();
openedTooltips.remove(ttScope);

0 comments on commit 02425b8

Please sign in to comment.