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

Commit f8eab55

Browse files
committed
fix(tooltip): properly gc timeout on toggle of disabled
- When `disabled` attribute changes, properly garbage collect the timeout Closes #4210 Fixes #4204
1 parent 71e0b8a commit f8eab55

File tree

2 files changed

+41
-18
lines changed

2 files changed

+41
-18
lines changed

Diff for: src/tooltip/test/tooltip.spec.js

+35-13
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,10 @@ describe('tooltip', function() {
246246
});
247247

248248
describe('with specified popup delay', function() {
249-
beforeEach(inject(function($compile) {
250-
scope.delay='1000';
249+
var $timeout;
250+
beforeEach(inject(function($compile, _$timeout_) {
251+
$timeout = _$timeout_;
252+
scope.delay = '1000';
251253
elm = $compile(angular.element(
252254
'<span tooltip="tooltip text" tooltip-popup-delay="{{delay}}" ng-disabled="disabled">Selector Text</span>'
253255
))(scope);
@@ -256,22 +258,22 @@ describe('tooltip', function() {
256258
scope.$digest();
257259
}));
258260

259-
it('should open after timeout', inject(function($timeout) {
261+
it('should open after timeout', function() {
260262
elm.trigger('mouseenter');
261263
expect(tooltipScope.isOpen).toBe(false);
262264

263265
$timeout.flush();
264266
expect(tooltipScope.isOpen).toBe(true);
265-
}));
267+
});
266268

267-
it('should not open if mouseleave before timeout', inject(function($timeout) {
269+
it('should not open if mouseleave before timeout', function() {
268270
elm.trigger('mouseenter');
269271
expect(tooltipScope.isOpen).toBe(false);
270272

271273
elm.trigger('mouseleave');
272274
$timeout.flush();
273275
expect(tooltipScope.isOpen).toBe(false);
274-
}));
276+
});
275277

276278
it('should use default popup delay if specified delay is not a number', function() {
277279
scope.delay='text1000';
@@ -280,7 +282,7 @@ describe('tooltip', function() {
280282
expect(tooltipScope.isOpen).toBe(true);
281283
});
282284

283-
it('should not open if disabled is present', inject(function($timeout) {
285+
it('should not open if disabled is present', function() {
284286
elm.trigger('mouseenter');
285287
expect(tooltipScope.isOpen).toBe(false);
286288

@@ -291,10 +293,30 @@ describe('tooltip', function() {
291293

292294
$timeout.flush();
293295
expect(tooltipScope.isOpen).toBe(false);
294-
}));
296+
});
297+
298+
it('should open when not disabled after being disabled - issue #4204', function() {
299+
elm.trigger('mouseenter');
300+
expect(tooltipScope.isOpen).toBe(false);
301+
302+
$timeout.flush(500);
303+
elmScope.disabled = true;
304+
elmScope.$digest();
305+
306+
$timeout.flush(500);
307+
expect(tooltipScope.isOpen).toBe(false);
308+
309+
elmScope.disabled = false;
310+
elmScope.$digest();
311+
312+
elm.trigger('mouseenter');
313+
$timeout.flush();
314+
315+
expect(tooltipScope.isOpen).toBe(true);
316+
});
295317
});
296-
297-
describe( 'with an is-open attribute', function() {
318+
319+
describe('with an is-open attribute', function() {
298320
beforeEach(inject(function ($compile) {
299321
scope.isOpen = false;
300322
elm = $compile(angular.element(
@@ -304,7 +326,7 @@ describe('tooltip', function() {
304326
tooltipScope = elmScope.$$childTail;
305327
scope.$digest();
306328
}));
307-
329+
308330
it( 'should show and hide with the controller value', function() {
309331
expect(tooltipScope.isOpen).toBe(false);
310332
elmScope.isOpen = true;
@@ -314,7 +336,7 @@ describe('tooltip', function() {
314336
elmScope.$digest();
315337
expect(tooltipScope.isOpen).toBe(false);
316338
});
317-
339+
318340
it( 'should update the controller value', function() {
319341
elm.trigger('mouseenter');
320342
expect(elmScope.isOpen).toBe(true);
@@ -412,7 +434,7 @@ describe('tooltip', function() {
412434
elm.trigger('fakeTriggerAttr');
413435
expect( tooltipScope.isOpen ).toBeFalsy();
414436
}));
415-
437+
416438
it( 'should not show when trigger is set to "none"', inject(function($compile) {
417439
elmBody = angular.element(
418440
'<div><input tooltip="Hello!" tooltip-trigger="none" /></div>'

Diff for: src/tooltip/tooltip.js

+6-5
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.b
215215
if (isOpenExp) {
216216
isOpenExp.assign(ttScope.origScope, ttScope.isOpen);
217217
}
218-
218+
219219
if (!$rootScope.$$phase) {
220220
ttScope.$apply(); // digest required as $apply is not called
221221
}
@@ -232,7 +232,7 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.b
232232
if (isOpenExp) {
233233
isOpenExp.assign(ttScope.origScope, ttScope.isOpen);
234234
}
235-
235+
236236
//if tooltip is going to be shown after delay, we must cancel this
237237
$timeout.cancel(popupTimeout);
238238
popupTimeout = null;
@@ -269,7 +269,7 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.b
269269
hide();
270270
}
271271
});
272-
272+
273273
tooltipLinkedScope.$watch(function() {
274274
if (!repositionScheduled) {
275275
repositionScheduled = true;
@@ -281,7 +281,7 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.b
281281
});
282282
}
283283
});
284-
284+
285285
}
286286
}
287287

@@ -325,6 +325,7 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.b
325325
attrs.$observe('disabled', function(val) {
326326
if (popupTimeout && val) {
327327
$timeout.cancel(popupTimeout);
328+
popupTimeout = null;
328329
}
329330

330331
if (val && ttScope.isOpen) {
@@ -345,7 +346,7 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.b
345346
}, 0, false);
346347
}
347348
});
348-
349+
349350
if (isOpenExp) {
350351
scope.$watch(isOpenExp, function(val) {
351352
if (val !== ttScope.isOpen) {

0 commit comments

Comments
 (0)