Skip to content

Commit e74cc75

Browse files
committed
fix(tooltip): update placement on content change
Since the recompute of position is a heavy calculation and given that this happens only when tooltip is visible, ie position is already calculated, we can reuse it to update the position when widht/height changes. Closes angular-ui#96
1 parent 41bea46 commit e74cc75

File tree

1 file changed

+51
-48
lines changed

1 file changed

+51
-48
lines changed

src/tooltip/tooltip.js

Lines changed: 51 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
116116
var triggers = getTriggers( undefined );
117117
var hasRegisteredTriggers = false;
118118
var hasEnableExp = angular.isDefined(attrs[prefix+'Enable']);
119+
var position;
119120

120121
// By default, the tooltip is not open.
121122
// TODO add ability to start tooltip opened
@@ -147,77 +148,74 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
147148
});
148149
}
149150

150-
// Show the tooltip popup element.
151-
function show() {
152-
var position,
153-
ttWidth,
154-
ttHeight,
151+
// Calculate tootip's position
152+
function updatePosition() {
153+
var ttWidth = tooltip.prop( 'offsetWidth' ),
154+
ttHeight = tooltip.prop( 'offsetHeight' ),
155155
ttPosition;
156-
157-
// Don't show empty tooltips.
158-
if ( ! scope.tt_content ) {
159-
return;
160-
}
161-
162-
// If there is a pending remove transition, we must cancel it, lest the
163-
// tooltip be mysteriously removed.
164-
if ( transitionTimeout ) {
165-
$timeout.cancel( transitionTimeout );
166-
}
167-
168-
// Set the initial positioning.
169-
tooltip.css({ top: 0, left: 0, display: 'block' });
170-
171-
// Now we add it to the DOM because need some info about it. But it's not
172-
// visible yet anyway.
173-
if ( appendToBody ) {
174-
$document.find( 'body' ).append( tooltip );
175-
} else {
176-
element.after( tooltip );
177-
}
178-
179-
// Get the position of the directive element.
180-
position = appendToBody ? $position.offset( element ) : $position.position( element );
181-
182-
// Get the height and width of the tooltip so we can center it.
183-
ttWidth = tooltip.prop( 'offsetWidth' );
184-
ttHeight = tooltip.prop( 'offsetHeight' );
185156

186157
// Calculate the tooltip's top and left coordinates to center it with
187158
// this directive.
188159
switch ( scope.tt_placement ) {
189160
case 'right':
190161
ttPosition = {
191-
top: position.top + position.height / 2 - ttHeight / 2,
192-
left: position.left + position.width
162+
top: position.top + position.height / 2 - ttHeight / 2 + 'px',
163+
left: position.left + position.width + 'px'
193164
};
194165
break;
195166
case 'bottom':
196167
ttPosition = {
197-
top: position.top + position.height,
198-
left: position.left + position.width / 2 - ttWidth / 2
168+
top: position.top + position.height + 'px',
169+
left: position.left + position.width / 2 - ttWidth / 2 + 'px'
199170
};
200171
break;
201172
case 'left':
202173
ttPosition = {
203-
top: position.top + position.height / 2 - ttHeight / 2,
204-
left: position.left - ttWidth
174+
top: position.top + position.height / 2 - ttHeight / 2 + 'px',
175+
left: position.left - ttWidth + 'px'
205176
};
206177
break;
207178
default:
208179
ttPosition = {
209-
top: position.top - ttHeight,
210-
left: position.left + position.width / 2 - ttWidth / 2
180+
top: position.top - ttHeight + 'px',
181+
left: position.left + position.width / 2 - ttWidth / 2 + 'px'
211182
};
212183
break;
213184
}
214185

215-
ttPosition.top += 'px';
216-
ttPosition.left += 'px';
217-
218186
// Now set the calculated positioning.
219187
tooltip.css( ttPosition );
220-
188+
}
189+
190+
// Show the tooltip popup element.
191+
function show() {
192+
// Don't show empty tooltips.
193+
if ( ! scope.tt_content ) {
194+
return;
195+
}
196+
197+
// If there is a pending remove transition, we must cancel it, lest the
198+
// tooltip be mysteriously removed.
199+
if ( transitionTimeout ) {
200+
$timeout.cancel( transitionTimeout );
201+
}
202+
203+
tooltip.css({ display: 'block' });
204+
205+
// Now we add it to the DOM because need some info about it. But it's not
206+
// visible yet anyway.
207+
if ( appendToBody ) {
208+
$document.find( 'body' ).append( tooltip );
209+
} else {
210+
element.after( tooltip );
211+
}
212+
213+
// Get the position of the directive element.
214+
position = appendToBody ? $position.offset( element ) : $position.position( element );
215+
216+
// Place tooltip
217+
updatePosition();
218+
221219
// And show the tooltip.
222220
scope.tt_isOpen = true;
223221
}
@@ -248,8 +246,13 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
248246
attrs.$observe( type, function ( val ) {
249247
scope.tt_content = val;
250248

251-
if (!val && scope.tt_isOpen ) {
252-
hide();
249+
if (scope.tt_isOpen) {
250+
if (!val) {
251+
hide();
252+
} else {
253+
// Adjust based on the last known position of the directive element.
254+
$timeout(updatePosition);
255+
}
253256
}
254257
});
255258

0 commit comments

Comments
 (0)