diff --git a/src/popover/docs/readme.md b/src/popover/docs/readme.md index 8b98f4a914..993eea0514 100644 --- a/src/popover/docs/readme.md +++ b/src/popover/docs/readme.md @@ -22,6 +22,8 @@ will display: - `popover-animation`: Should it fade in and out? Defaults to "true". - `popover-popup-delay`: For how long should the user have to have the mouse over the element before the popover shows (in milliseconds)? Defaults to 0. +- `popover-close-popup-delay`: For how long should the popover remain open + after the close trigger event? Defaults to 0. - `popover-trigger`: What should trigger the show of the popover? See the `tooltip` directive for supported values. - `popover-append-to-body`: Should the tooltip be appended to `$body` instead of diff --git a/src/tooltip/docs/demo.html b/src/tooltip/docs/demo.html index bb3260ae00..795f3657b0 100644 --- a/src/tooltip/docs/demo.html +++ b/src/tooltip/docs/demo.html @@ -19,7 +19,9 @@ pharetra convallis posuere morbi leo urna, fading at elementum eu, facilisis sed odio morbi quis commodo odio. In cursus - delayed turpis massa tincidunt dui ut. + show delay + turpis massa tincidunt dui ut. In cursus + hide delay Custom template nunc sed velit dignissim sodales ut eu sem integer vitae. Turpis egestas

diff --git a/src/tooltip/docs/readme.md b/src/tooltip/docs/readme.md index ca6c92c618..16d4cdb6c9 100644 --- a/src/tooltip/docs/readme.md +++ b/src/tooltip/docs/readme.md @@ -20,7 +20,8 @@ will display: - `tooltip-animation`: Should it fade in and out? Defaults to "true". - `tooltip-popup-delay`: For how long should the user have to have the mouse over the element before the tooltip shows (in milliseconds)? Defaults to 0. -- `tooltip-close-popup-delay`: For how long should the tooltip remained open? +- `tooltip-close-popup-delay`: For how long should the tooltip remain open + after the close trigger event? Defaults to 0. - `tooltip-trigger`: What should trigger a show of the tooltip? Supports a space separated list of event names. Note: this attribute is no longer observable. See `tooltip-enable`. - `tooltip-enable`: Is it enabled? It will enable or disable the configured diff --git a/src/tooltip/test/tooltip.spec.js b/src/tooltip/test/tooltip.spec.js index 74b249a639..30e495ee80 100644 --- a/src/tooltip/test/tooltip.spec.js +++ b/src/tooltip/test/tooltip.spec.js @@ -386,11 +386,11 @@ describe('tooltip', function() { expect(tooltipScope.isOpen).toBe(false); }); - it('should use default popup close delay if specified delay is not a number and close after delay', function() { + it('should use default popup close delay if specified delay is not a number and close immediately', function() { scope.delay = 'text1000'; scope.$digest(); trigger(elm, 'mouseenter'); - expect(tooltipScope.popupCloseDelay).toBe(500); + expect(tooltipScope.popupCloseDelay).toBe(0); expect(tooltipScope.isOpen).toBe(true); trigger(elm, 'mouseleave'); $timeout.flush(); diff --git a/src/tooltip/tooltip.js b/src/tooltip/tooltip.js index dd11cf8c8f..f2d1dd7297 100644 --- a/src/tooltip/tooltip.js +++ b/src/tooltip/tooltip.js @@ -15,7 +15,7 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s placement: 'top', animation: true, popupDelay: 0, - popupCloseDelay: 500, + popupCloseDelay: 0, useContentExp: false }; @@ -135,7 +135,8 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s var tooltip; var tooltipLinkedScope; var transitionTimeout; - var popupTimeout; + var showTimeout; + var hideTimeout; var positionTimeout; var appendToBody = angular.isDefined(options.appendToBody) ? options.appendToBody : false; var triggers = getTriggers(undefined); @@ -196,8 +197,8 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s if (ttScope.popupDelay) { // Do nothing if the tooltip was already scheduled to pop-up. // This happens if show is triggered multiple times before any hide is triggered. - if (!popupTimeout) { - popupTimeout = $timeout(show, ttScope.popupDelay, false); + if (!showTimeout) { + showTimeout = $timeout(show, ttScope.popupDelay, false); } } else { show(); @@ -205,18 +206,26 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s } function hideTooltipBind() { - hide(); + if (ttScope.popupCloseDelay) { + hideTimeout = $timeout(hide, ttScope.popupCloseDelay, false); + } else { + hide(); + } } // Show the tooltip popup element. function show() { - if (popupTimeout) { - $timeout.cancel(popupTimeout); - popupTimeout = null; + 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; @@ -232,10 +241,7 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s // And show the tooltip. ttScope.$evalAsync(function() { ttScope.isOpen = true; - if (isOpenParse && angular.isFunction(isOpenParse.assign)) { - isOpenParse.assign(ttScope.origScope, ttScope.isOpen); - } - + assignIsOpen(true); positionTooltip(); }); } @@ -246,31 +252,33 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s return; } + //if tooltip is going to be shown after delay, we must cancel this + if (showTimeout) { + $timeout.cancel(showTimeout); + showTimeout = null; + } + + if (positionTimeout) { + $timeout.cancel(positionTimeout); + positionTimeout = null; + } + // First things first: we don't show it anymore. ttScope.$evalAsync(function() { ttScope.isOpen = false; - if (isOpenParse && angular.isFunction(isOpenParse.assign)) { - isOpenParse.assign(ttScope.origScope, ttScope.isOpen); + assignIsOpen(false); + // And now we remove it from the DOM. However, if we have animation, we + // need to wait for it to expire beforehand. + // FIXME: this is a placeholder for a port of the transitions library. + // The fade transition in TWBS is 150ms. + if (ttScope.animation) { + if (!transitionTimeout) { + transitionTimeout = $timeout(removeTooltip, 150, false); + } + } else { + removeTooltip(); } }); - - //if tooltip is going to be shown after delay, we must cancel this - $timeout.cancel(popupTimeout); - popupTimeout = null; - - $timeout.cancel(positionTimeout); - positionTimeout = null; - - // And now we remove it from the DOM. However, if we have animation, we - // need to wait for it to expire beforehand. - // FIXME: this is a placeholder for a port of the transitions library. - if (ttScope.animation) { - if (!transitionTimeout) { - transitionTimeout = $timeout(removeTooltip, ttScope.popupCloseDelay); - } - } else { - removeTooltip(); - } } function createTooltip() { @@ -327,6 +335,12 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s ttScope.popupCloseDelay = !isNaN(closeDelay) ? closeDelay : options.popupCloseDelay; } + function assignIsOpen(isOpen) { + if (isOpenParse && angular.isFunction(isOpenParse.assign)) { + isOpenParse.assign(scope, isOpen); + } + } + ttScope.contentExp = function() { return ttScope.content; }; @@ -335,9 +349,9 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s * Observe the relevant attributes. */ attrs.$observe('disabled', function(val) { - if (popupTimeout && val) { - $timeout.cancel(popupTimeout); - popupTimeout = null; + if (showTimeout && val) { + $timeout.cancel(showTimeout); + showTimeout = null; } if (val && ttScope.isOpen) { @@ -482,7 +496,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(popupTimeout); + $timeout.cancel(showTimeout); + $timeout.cancel(hideTimeout); $timeout.cancel(positionTimeout); unregisterTriggers(); removeTooltip();