Skip to content

Commit

Permalink
fix(tooltip): update placement on content change
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bekos committed Dec 18, 2013
1 parent 1fbcb5d commit 88f00d1
Showing 1 changed file with 52 additions and 48 deletions.
100 changes: 52 additions & 48 deletions src/tooltip/tooltip.js
Expand Up @@ -116,6 +116,7 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
var triggers = getTriggers( undefined );
var hasRegisteredTriggers = false;
var hasEnableExp = angular.isDefined(attrs[prefix+'Enable']);
var position;

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

// Show the tooltip popup element.
function show() {
var position,
ttWidth,
ttHeight,
// Calculate tootip's position
function updatePosition() {
var ttWidth = tooltip.prop( 'offsetWidth' ),
ttHeight = tooltip.prop( 'offsetHeight' ),
ttPosition;

// Don't show empty tooltips.
if ( ! scope.tt_content ) {
return;
}

// 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' });

// Now we add it to the DOM because need some info about it. But it's not
// visible yet anyway.
if ( appendToBody ) {
$document.find( 'body' ).append( tooltip );
} else {
element.after( tooltip );
}

// Get the position of the directive element.
position = appendToBody ? $position.offset( element ) : $position.position( element );

// Get the height and width of the tooltip so we can center it.
ttWidth = tooltip.prop( 'offsetWidth' );
ttHeight = tooltip.prop( 'offsetHeight' );

// Calculate the tooltip's top and left coordinates to center it with
// this directive.
switch ( scope.tt_placement ) {
case 'right':
ttPosition = {
top: position.top + position.height / 2 - ttHeight / 2,
left: position.left + position.width
top: position.top + position.height / 2 - ttHeight / 2 + 'px',
left: position.left + position.width + 'px'
};
break;
case 'bottom':
ttPosition = {
top: position.top + position.height,
left: position.left + position.width / 2 - ttWidth / 2
top: position.top + position.height + 'px',
left: position.left + position.width / 2 - ttWidth / 2 + 'px'
};
break;
case 'left':
ttPosition = {
top: position.top + position.height / 2 - ttHeight / 2,
left: position.left - ttWidth
top: position.top + position.height / 2 - ttHeight / 2 + 'px',
left: position.left - ttWidth + 'px'
};
break;
default:
ttPosition = {
top: position.top - ttHeight,
left: position.left + position.width / 2 - ttWidth / 2
top: position.top - ttHeight + 'px',
left: position.left + position.width / 2 - ttWidth / 2 + 'px'
};
break;
}

ttPosition.top += 'px';
ttPosition.left += 'px';

// Now set the calculated positioning.
tooltip.css( ttPosition );

}

// Show the tooltip popup element.
function show() {
// Don't show empty tooltips.
if ( ! scope.tt_content ) {
return;
}

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

tooltip.css({ display: 'block' });

// Now we add it to the DOM because need some info about it. But it's not
// visible yet anyway.
if ( appendToBody ) {
$document.find( 'body' ).append( tooltip );
} else {
element.after( tooltip );
}

// Get the position of the directive element.
position = appendToBody ? $position.offset( element ) : $position.position( element );

// Place tooltip
updatePosition();

// And show the tooltip.
scope.tt_isOpen = true;
}
Expand Down Expand Up @@ -248,8 +246,14 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
attrs.$observe( type, function ( val ) {
scope.tt_content = val;

if (!val && scope.tt_isOpen ) {
hide();
if (scope.tt_isOpen) {
if (!val) {
hide();
} else {
// Wait for content to be set on the tooltip element and adjust position
// based on the new width/height and last known position of the directive element.
$timeout(updatePosition);
}
}
});

Expand Down

0 comments on commit 88f00d1

Please sign in to comment.