From 632aa8204b94179f2f3683f4470663e57c2fe2fe Mon Sep 17 00:00:00 2001 From: Chad von Nau Date: Mon, 20 Jul 2015 14:37:27 -0700 Subject: [PATCH] fix(tooltip): prevent 1px shift in Webkit/Blink - Only update tooltip position when content changes, instead of every $digest Fixes #3964 --- src/tooltip/test/tooltip.spec.js | 10 ++++++---- src/tooltip/tooltip.js | 11 +++++++---- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/tooltip/test/tooltip.spec.js b/src/tooltip/test/tooltip.spec.js index 5245d032e0..4e6d555ae4 100644 --- a/src/tooltip/test/tooltip.spec.js +++ b/src/tooltip/test/tooltip.spec.js @@ -474,24 +474,26 @@ describe( 'tooltip positioning', function() { tooltipScope = elmScope.$$childTail; })); - it( 'should re-position on every digest', inject( function ($timeout) { + it( 'should re-position when value changes', inject( function ($timeout) { elm.trigger( 'mouseenter' ); scope.$digest(); $timeout.flush(); var startingPositionCalls = $position.positionElements.calls.count(); + scope.text = 'New Text'; scope.$digest(); $timeout.flush(); + expect(elm.attr('tooltip')).toBe( 'New Text' ); expect($position.positionElements.calls.count()).toEqual(startingPositionCalls + 1); // Check that positionElements was called with elm expect($position.positionElements.calls.argsFor(startingPositionCalls)[0][0]) .toBe(elm[0]); scope.$digest(); - $timeout.flush(); - expect($position.positionElements.calls.count()).toEqual(startingPositionCalls + 2); - expect($position.positionElements.calls.argsFor(startingPositionCalls + 1)[0][0]) + $timeout.verifyNoPendingTasks(); + expect($position.positionElements.calls.count()).toEqual(startingPositionCalls + 1); + expect($position.positionElements.calls.argsFor(startingPositionCalls)[0][0]) .toBe(elm[0]); scope.$digest(); })); diff --git a/src/tooltip/tooltip.js b/src/tooltip/tooltip.js index 9c6db85413..31faa39705 100644 --- a/src/tooltip/tooltip.js +++ b/src/tooltip/tooltip.js @@ -136,6 +136,10 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap tooltip.css( ttPosition ); }; + var positionTooltipAsync = function () { + $timeout(positionTooltip, 0, false); + }; + // Set up the correct scope to allow transclusion later ttScope.origScope = scope; @@ -246,12 +250,9 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap } }); - tooltipLinkedScope.$watch(function () { - $timeout(positionTooltip, 0, false); - }); - if (options.useContentExp) { tooltipLinkedScope.$watch('contentExp()', function (val) { + positionTooltipAsync(); if (!val && ttScope.isOpen ) { hide(); } @@ -287,6 +288,7 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap if (!options.useContentExp) { attrs.$observe( type, function ( val ) { ttScope.content = val; + positionTooltipAsync(); if (!val && ttScope.isOpen ) { hide(); @@ -302,6 +304,7 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap attrs.$observe( prefix+'Title', function ( val ) { ttScope.title = val; + positionTooltipAsync(); }); function prepPopupClass() {