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

Commit

Permalink
fix(tooltip): animation causes tooltip to hide on show
Browse files Browse the repository at this point in the history
Add logic to handle cases where hide/show can be called multiple times
even before their timeouts complete.

This is more ugly logic to handle degenerate cases. Hopefully switching
over to ngAnimate and cleaning up the logic of tooltips will be better.

Fixes #1847

Closes #1940
  • Loading branch information
chrisirhc authored and pkozlowski-opensource committed May 1, 2014
1 parent 60cee9d commit 2b429f5
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 9 deletions.
31 changes: 31 additions & 0 deletions src/tooltip/test/tooltip2.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,35 @@ describe('tooltip directive', function () {
});

});

it('should show even after close trigger is called multiple times - issue #1847', function () {
var fragment = compileTooltip('<span tooltip="tooltip text">Trigger here</span>');

fragment.find('span').trigger( 'mouseenter' );
expect(fragment).toHaveOpenTooltips();

closeTooltip(fragment.find('span'), null, true);
// Close trigger is called again before timer completes
// The close trigger can be called any number of times (even after close has already been called)
// since users can trigger the hide triggers manually.
closeTooltip(fragment.find('span'), null, true);
expect(fragment).toHaveOpenTooltips();

fragment.find('span').trigger( 'mouseenter' );
expect(fragment).toHaveOpenTooltips();

$timeout.flush();
expect(fragment).toHaveOpenTooltips();
});

it('should hide even after show trigger is called multiple times', function () {
var fragment = compileTooltip('<span tooltip="tooltip text" tooltip-popup-delay="1000">Trigger here</span>');

fragment.find('span').trigger( 'mouseenter' );
fragment.find('span').trigger( 'mouseenter' );

closeTooltip(fragment.find('span'));
expect(fragment).not.toHaveOpenTooltips();
});

});
28 changes: 19 additions & 9 deletions src/tooltip/tooltip.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,12 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
return;
}
if ( scope.tt_popupDelay ) {
popupTimeout = $timeout( show, scope.tt_popupDelay, false );
popupTimeout.then(function(reposition){reposition();});
// 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, scope.tt_popupDelay, false );
popupTimeout.then(function(reposition){reposition();});
}
} else {
show()();
}
Expand All @@ -163,6 +167,14 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
// Show the tooltip popup element.
function show() {

popupTimeout = null;

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

// Don't show empty tooltips.
if ( ! scope.tt_content ) {
Expand All @@ -171,12 +183,6 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap

createTooltip();

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

// Set the initial positioning.
tooltip.css({ top: 0, left: 0, display: 'block' });

Expand Down Expand Up @@ -206,12 +212,15 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap

//if tooltip is going to be shown after delay, we must cancel this
$timeout.cancel( popupTimeout );
popupTimeout = 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 ( scope.tt_animation ) {
transitionTimeout = $timeout(removeTooltip, 500);
if (!transitionTimeout) {
transitionTimeout = $timeout(removeTooltip, 500);
}
} else {
removeTooltip();
}
Expand All @@ -229,6 +238,7 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
}

function removeTooltip() {
transitionTimeout = null;
if (tooltip) {
tooltip.remove();
tooltip = null;
Expand Down

0 comments on commit 2b429f5

Please sign in to comment.