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 29, 2013
1 parent c61e697 commit 85cc3ca
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 9 deletions.
38 changes: 36 additions & 2 deletions src/tooltip/test/tooltip2.spec.js
@@ -1,14 +1,15 @@
describe('tooltip directive', function () {

var $rootScope, $compile, $document, $timeout;
var $rootScope, $compile, $document, $timeout, $position;

beforeEach(module('ui.bootstrap.tooltip'));
beforeEach(module('template/tooltip/tooltip-popup.html'));
beforeEach(inject(function (_$rootScope_, _$compile_, _$document_, _$timeout_) {
beforeEach(inject(function (_$rootScope_, _$compile_, _$document_, _$timeout_, _$position_) {
$rootScope = _$rootScope_;
$compile = _$compile_;
$document = _$document_;
$timeout = _$timeout_;
$position = _$position_;
}));

beforeEach(function(){
Expand Down Expand Up @@ -102,4 +103,37 @@ describe('tooltip directive', function () {
});

});

describe('position', function() {

beforeEach(function() {
spyOn($position, 'position').andCallThrough();
});

it('is called once on mouse enter and leave', function () {
var fragment = compileTooltip('<span tooltip="tooltip text">Trigger here</span>');

expect($position.position).not.toHaveBeenCalled();

fragment.find('span').trigger( 'mouseenter' );
expect($position.position.calls.length).toEqual(1);

closeTooltip(fragment.find('span'));
expect($position.position.calls.length).toEqual(1);
});

it('is called once for content updates when is open', function () {
$rootScope.content = 'some text';
var fragment = compileTooltip('<span tooltip="{{ content }}">Trigger here</span>');

expect($position.position).not.toHaveBeenCalled();

fragment.find('span').trigger( 'mouseenter' );
expect($position.position.calls.length).toEqual(1);

$rootScope.content = 'some new text';
$rootScope.$digest();
expect($position.position.calls.length).toEqual(1);
});
});
});
22 changes: 15 additions & 7 deletions src/tooltip/tooltip.js
Expand Up @@ -64,7 +64,7 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
* Returns the actual instance of the $tooltip service.
* TODO support multiple triggers
*/
this.$get = [ '$window', '$compile', '$timeout', '$parse', '$document', '$position', '$interpolate', function ( $window, $compile, $timeout, $parse, $document, $position, $interpolate ) {
this.$get = [ '$compile', '$timeout', '$parse', '$document', '$position', '$interpolate', function ( $compile, $timeout, $parse, $document, $position, $interpolate ) {
return function $tooltip ( type, prefix, defaultTriggerShow ) {
var options = angular.extend( {}, defaultOptions, globalOptions );

Expand Down Expand Up @@ -116,14 +116,12 @@ 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;

var positionTooltip = function (){
var position,
ttWidth,
var ttWidth,
ttHeight,
ttPosition;
// 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' );
Expand Down Expand Up @@ -222,7 +220,11 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
} else {
element.after( tooltip );
}

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

// Place tooltip
positionTooltip();

// And show the tooltip.
Expand Down Expand Up @@ -259,8 +261,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 DOM to be updated and adjust position based on the new tooltip dimensions
// and the last known position of the directive element.
scope.$evalAsync(positionTooltip);
}
}
});

Expand Down

0 comments on commit 85cc3ca

Please sign in to comment.