diff --git a/src/tooltip/test/tooltip.spec.js b/src/tooltip/test/tooltip.spec.js index 30e495ee80..bbc8efbf81 100644 --- a/src/tooltip/test/tooltip.spec.js +++ b/src/tooltip/test/tooltip.spec.js @@ -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( + 'Selector Text' + ))(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; diff --git a/src/tooltip/tooltip.js b/src/tooltip/tooltip.js index ad99f2dec4..2a589d5bb6 100644 --- a/src/tooltip/tooltip.js +++ b/src/tooltip/tooltip.js @@ -192,6 +192,7 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s return; } + cancelHide(); prepareTooltip(); if (ttScope.popupDelay) { @@ -206,8 +207,12 @@ 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(); } @@ -215,21 +220,8 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s // 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);