diff --git a/src/tooltip/test/tooltipSpec.js b/src/tooltip/test/tooltipSpec.js index f52a34d79f..9ebfddb0c1 100644 --- a/src/tooltip/test/tooltipSpec.js +++ b/src/tooltip/test/tooltipSpec.js @@ -23,7 +23,7 @@ describe('tooltip', function() { })); it('should not be open initially', inject(function() { - expect( elmScope.isOpen ).toBe( false ); + expect( elmScope.tt_isOpen ).toBe( false ); // We can only test *that* the tooltip-popup element wasn't created as the // implementation is templated and replaced. @@ -32,7 +32,7 @@ describe('tooltip', function() { it('should open on mouseenter', inject(function() { elm.trigger( 'mouseenter' ); - expect( elmScope.isOpen ).toBe( true ); + expect( elmScope.tt_isOpen ).toBe( true ); // We can only test *that* the tooltip-popup element was created as the // implementation is templated and replaced. @@ -42,12 +42,12 @@ describe('tooltip', function() { it('should close on mouseleave', inject(function() { elm.trigger( 'mouseenter' ); elm.trigger( 'mouseleave' ); - expect( elmScope.isOpen ).toBe( false ); + expect( elmScope.tt_isOpen ).toBe( false ); })); it('should have default placement of "top"', inject(function() { elm.trigger( 'mouseenter' ); - expect( elmScope.placement ).toBe( "top" ); + expect( elmScope.tt_placement ).toBe( "top" ); })); it('should allow specification of placement', inject( function( $compile ) { @@ -57,7 +57,7 @@ describe('tooltip', function() { elmScope = elm.scope(); elm.trigger( 'mouseenter' ); - expect( elmScope.placement ).toBe( "bottom" ); + expect( elmScope.tt_placement ).toBe( "bottom" ); })); it('should work inside an ngRepeat', inject( function( $compile ) { @@ -65,7 +65,7 @@ describe('tooltip', function() { elm = $compile( angular.element( '' ) )( scope ); @@ -80,15 +80,37 @@ describe('tooltip', function() { tt.trigger( 'mouseenter' ); - // Due to the transclusion, the contents of the element are in a span, so - // we select the tooltip's child and ensure its content matches. - expect( tt.children().text() ).toBe( scope.items[0].name ); - - // And the tooltip text should still match. - expect( tt.scope().tooltipTitle ).toBe( scope.items[0].tooltip ); + expect( tt.text() ).toBe( scope.items[0].name ); + expect( tt.scope().tt_tooltip ).toBe( scope.items[0].tooltip ); tt.trigger( 'mouseleave' ); })); + + it('should only have an isolate scope on the popup', inject( function ( $compile ) { + var ttScope; + + scope.tooltipMsg = "Tooltip Text"; + scope.alt = "Alt Message"; + + elmBody = $compile( angular.element( + '
Selector Text
' + ) )( scope ); + + $compile( elmBody )( scope ); + scope.$digest(); + elm = elmBody.find( 'span' ); + elmScope = elm.scope(); + + elm.trigger( 'mouseenter' ); + expect( elm.attr( 'alt' ) ).toBe( scope.alt ); + + ttScope = angular.element( elmBody.children()[1] ).scope(); + expect( ttScope.placement ).toBe( 'top' ); + expect( ttScope.tooltipTitle ).toBe( scope.tooltipMsg ); + + elm.trigger( 'mouseleave' ); + })); + }); diff --git a/src/tooltip/tooltip.js b/src/tooltip/tooltip.js index 65050bfcc3..27d70542bd 100644 --- a/src/tooltip/tooltip.js +++ b/src/tooltip/tooltip.js @@ -8,28 +8,42 @@ angular.module( 'ui.bootstrap.tooltip', [] ) return { restrict: 'E', replace: true, + scope: { tooltipTitle: '@', placement: '@', animation: '&', isOpen: '&' }, templateUrl: 'template/tooltip/tooltip-popup.html' }; }) -.directive( 'tooltip', [ '$compile', '$timeout', function ( $compile, $timeout ) { +.directive( 'tooltip', [ '$compile', '$timeout', '$parse', function ( $compile, $timeout, $parse ) { var template = - ''; + ''+ + ''; return { - transclude: true, - scope: { tooltipTitle: '@tooltip', placement: '@tooltipPlacement', animation: '&tooltipAnimation' }, - controller: ['$transclude', '$element', function($transclude, $element) { - $transclude(function(clone) { - $element.append(clone); - }); - }], + scope: true, link: function ( scope, element, attr ) { var tooltip = $compile( template )( scope ), transitionTimeout; + attr.$observe( 'tooltip', function ( val ) { + scope.tt_tooltip = val; + }); + + attr.$observe( 'tooltipPlacement', function ( val ) { + // If no placement was provided, default to 'top'. + scope.tt_placement = val || 'top'; + }); + + attr.$observe( 'tooltipAnimation', function ( val ) { + scope.tt_animation = $parse( val ); + }); + // By default, the tooltip is not open. - scope.isOpen = false; + scope.tt_isOpen = false; // Calculate the current position and size of the directive element. function getPosition() { @@ -48,9 +62,6 @@ angular.module( 'ui.bootstrap.tooltip', [] ) ttHeight, ttPosition; - // If no placement was provided, default to 'top'. - scope.placement = scope.placement || 'top'; - // If there is a pending remove transition, we must cancel it, lest the // toolip be mysteriously removed. if ( transitionTimeout ) { @@ -73,7 +84,7 @@ angular.module( 'ui.bootstrap.tooltip', [] ) // Calculate the tooltip's top and left coordinates to center it with // this directive. - switch ( scope.placement ) { + switch ( scope.tt_placement ) { case 'right': ttPosition = { top: (position.top + position.height / 2 - ttHeight / 2) + 'px', @@ -104,19 +115,19 @@ angular.module( 'ui.bootstrap.tooltip', [] ) tooltip.css( ttPosition ); // And show the tooltip. - scope.isOpen = true; + scope.tt_isOpen = true; } // Hide the tooltip popup element. function hide() { // First things first: we don't show it anymore. //tooltip.removeClass( 'in' ); - scope.isOpen = false; + scope.tt_isOpen = false; // And now we remove it from the DOM. However, if we have animation, we // need to wait for it to expire beforehand. // FIXME: this is a placeholder for a port of the transitions library. - if ( angular.isDefined( scope.animation ) && scope.animation() ) { + if ( angular.isDefined( scope.tt_animation ) && scope.tt_animation() ) { transitionTimeout = $timeout( function () { tooltip.remove(); }, 500 ); } else { tooltip.remove(); diff --git a/template/tooltip/tooltip-popup.html b/template/tooltip/tooltip-popup.html index caa0c9d34d..77d35de8e2 100644 --- a/template/tooltip/tooltip-popup.html +++ b/template/tooltip/tooltip-popup.html @@ -1,4 +1,4 @@ -
+