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

Commit 2b429f5

Browse files
chrisirhcpkozlowski-opensource
authored andcommittedMay 1, 2014
fix(tooltip): animation causes tooltip to hide on show
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
1 parent 60cee9d commit 2b429f5

File tree

2 files changed

+50
-9
lines changed

2 files changed

+50
-9
lines changed
 

‎src/tooltip/test/tooltip2.spec.js

+31
Original file line numberDiff line numberDiff line change
@@ -102,4 +102,35 @@ describe('tooltip directive', function () {
102102
});
103103

104104
});
105+
106+
it('should show even after close trigger is called multiple times - issue #1847', function () {
107+
var fragment = compileTooltip('<span tooltip="tooltip text">Trigger here</span>');
108+
109+
fragment.find('span').trigger( 'mouseenter' );
110+
expect(fragment).toHaveOpenTooltips();
111+
112+
closeTooltip(fragment.find('span'), null, true);
113+
// Close trigger is called again before timer completes
114+
// The close trigger can be called any number of times (even after close has already been called)
115+
// since users can trigger the hide triggers manually.
116+
closeTooltip(fragment.find('span'), null, true);
117+
expect(fragment).toHaveOpenTooltips();
118+
119+
fragment.find('span').trigger( 'mouseenter' );
120+
expect(fragment).toHaveOpenTooltips();
121+
122+
$timeout.flush();
123+
expect(fragment).toHaveOpenTooltips();
124+
});
125+
126+
it('should hide even after show trigger is called multiple times', function () {
127+
var fragment = compileTooltip('<span tooltip="tooltip text" tooltip-popup-delay="1000">Trigger here</span>');
128+
129+
fragment.find('span').trigger( 'mouseenter' );
130+
fragment.find('span').trigger( 'mouseenter' );
131+
132+
closeTooltip(fragment.find('span'));
133+
expect(fragment).not.toHaveOpenTooltips();
134+
});
135+
105136
});

‎src/tooltip/tooltip.js

+19-9
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,12 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
147147
return;
148148
}
149149
if ( scope.tt_popupDelay ) {
150-
popupTimeout = $timeout( show, scope.tt_popupDelay, false );
151-
popupTimeout.then(function(reposition){reposition();});
150+
// Do nothing if the tooltip was already scheduled to pop-up.
151+
// This happens if show is triggered multiple times before any hide is triggered.
152+
if (!popupTimeout) {
153+
popupTimeout = $timeout( show, scope.tt_popupDelay, false );
154+
popupTimeout.then(function(reposition){reposition();});
155+
}
152156
} else {
153157
show()();
154158
}
@@ -163,6 +167,14 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
163167
// Show the tooltip popup element.
164168
function show() {
165169

170+
popupTimeout = null;
171+
172+
// If there is a pending remove transition, we must cancel it, lest the
173+
// tooltip be mysteriously removed.
174+
if ( transitionTimeout ) {
175+
$timeout.cancel( transitionTimeout );
176+
transitionTimeout = null;
177+
}
166178

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

172184
createTooltip();
173185

174-
// If there is a pending remove transition, we must cancel it, lest the
175-
// tooltip be mysteriously removed.
176-
if ( transitionTimeout ) {
177-
$timeout.cancel( transitionTimeout );
178-
}
179-
180186
// Set the initial positioning.
181187
tooltip.css({ top: 0, left: 0, display: 'block' });
182188

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

207213
//if tooltip is going to be shown after delay, we must cancel this
208214
$timeout.cancel( popupTimeout );
215+
popupTimeout = null;
209216

210217
// And now we remove it from the DOM. However, if we have animation, we
211218
// need to wait for it to expire beforehand.
212219
// FIXME: this is a placeholder for a port of the transitions library.
213220
if ( scope.tt_animation ) {
214-
transitionTimeout = $timeout(removeTooltip, 500);
221+
if (!transitionTimeout) {
222+
transitionTimeout = $timeout(removeTooltip, 500);
223+
}
215224
} else {
216225
removeTooltip();
217226
}
@@ -229,6 +238,7 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
229238
}
230239

231240
function removeTooltip() {
241+
transitionTimeout = null;
232242
if (tooltip) {
233243
tooltip.remove();
234244
tooltip = null;

0 commit comments

Comments
 (0)