Skip to content

Commit c92072b

Browse files
committed
fix(tooltip): link on demand
- Calling $digest is enough as we only need to digest the watchers in this scope and its children. No need to call $apply. - No need to test for cached reference when tooltip isn't visible as the tooltip has no scope. Fixes angular-ui#1450 and angular-ui#1191
1 parent 2d5d632 commit c92072b

File tree

2 files changed

+31
-16
lines changed

2 files changed

+31
-16
lines changed

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

+1-7
Original file line numberDiff line numberDiff line change
@@ -348,18 +348,12 @@ describe('tooltip', function() {
348348

349349
elm = elmBody.find('input');
350350
elmScope = elm.scope();
351+
elm.trigger('fooTrigger');
351352
tooltipScope = elmScope.$$childTail;
352353
}));
353354

354-
it( 'should not contain a cached reference', function() {
355-
expect( inCache() ).toBeTruthy();
356-
elmScope.$destroy();
357-
expect( inCache() ).toBeFalsy();
358-
});
359-
360355
it( 'should not contain a cached reference when visible', inject( function( $timeout ) {
361356
expect( inCache() ).toBeTruthy();
362-
elm.trigger('fooTrigger');
363357
elmScope.$destroy();
364358
expect( inCache() ).toBeFalsy();
365359
}));

Diff for: src/tooltip/tooltip.js

+30-9
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,11 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
108108
return {
109109
restrict: 'EA',
110110
scope: true,
111-
link: function link ( scope, element, attrs ) {
112-
var tooltip = $compile( template )( scope );
111+
compile: function (tElem, tAttrs) {
112+
var tooltipLinker = $compile( template );
113+
114+
return function link ( scope, element, attrs ) {
115+
var tooltip;
113116
var transitionTimeout;
114117
var popupTimeout;
115118
var appendToBody = angular.isDefined( options.appendToBody ) ? options.appendToBody : false;
@@ -137,7 +140,7 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
137140
if ( scope.tt_popupDelay ) {
138141
popupTimeout = $timeout( show, scope.tt_popupDelay );
139142
} else {
140-
scope.$apply( show );
143+
show();
141144
}
142145
}
143146

@@ -159,6 +162,9 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
159162
return;
160163
}
161164

165+
createTooltip();
166+
scope.$digest();
167+
162168
// If there is a pending remove transition, we must cancel it, lest the
163169
// tooltip be mysteriously removed.
164170
if ( transitionTimeout ) {
@@ -220,6 +226,9 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
220226

221227
// And show the tooltip.
222228
scope.tt_isOpen = true;
229+
230+
// Apply changes
231+
scope.$digest();
223232
}
224233

225234
// Hide the tooltip popup element.
@@ -234,11 +243,24 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
234243
// need to wait for it to expire beforehand.
235244
// FIXME: this is a placeholder for a port of the transitions library.
236245
if ( scope.tt_animation ) {
237-
transitionTimeout = $timeout(function () {
238-
tooltip.remove();
239-
}, 500);
246+
transitionTimeout = $timeout(removeTooltip, 500);
240247
} else {
248+
removeTooltip();
249+
}
250+
}
251+
252+
function createTooltip() {
253+
// There can only be one tooltip element per directive shown at once.
254+
if (tooltip) {
255+
removeTooltip();
256+
}
257+
tooltip = tooltipLinker(scope, function () {});
258+
}
259+
260+
function removeTooltip() {
261+
if (tooltip) {
241262
tooltip.remove();
263+
tooltip = null;
242264
}
243265
}
244266

@@ -313,10 +335,9 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
313335
$timeout.cancel( transitionTimeout );
314336
$timeout.cancel( popupTimeout );
315337
unregisterTriggers();
316-
tooltip.remove();
317-
tooltip.unbind();
318-
tooltip = null;
338+
removeTooltip();
319339
});
340+
};
320341
}
321342
};
322343
};

0 commit comments

Comments
 (0)