Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

Commit

Permalink
feat(tooltip): add tooltip-html directive
Browse files Browse the repository at this point in the history
This directive replaces tooltip-html-unsafe use cases. It requires
safe HTML content from $sce.

Closes #3496
  • Loading branch information
chrisirhc authored and wesleycho committed Apr 7, 2015
1 parent 9ca9d7f commit e31fcf0
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/tooltip/docs/demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
</p>

<p>
I can even contain HTML. <a href="#" tooltip-html-unsafe="{{htmlTooltip}}">Check me out!</a>
I can even contain HTML. <a href="#" tooltip-html="htmlTooltip">Check me out!</a>
</p>

<p>
Expand Down
4 changes: 2 additions & 2 deletions src/tooltip/docs/demo.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
angular.module('ui.bootstrap.demo').controller('TooltipDemoCtrl', function ($scope) {
angular.module('ui.bootstrap.demo').controller('TooltipDemoCtrl', function ($scope, $sce) {
$scope.dynamicTooltip = 'Hello, World!';
$scope.dynamicTooltipText = 'dynamic';
$scope.htmlTooltip = 'I\'ve been made <b>bold</b>!';
$scope.htmlTooltip = $sce.trustAsHtml('I\'ve been made <b>bold</b>!');
});
54 changes: 53 additions & 1 deletion src/tooltip/test/tooltip.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -498,8 +498,54 @@ describe( 'tooltip positioning', function() {

});

describe( 'tooltipHtml', function() {
var elm, elmBody, elmScope, tooltipScope, scope;

// load the tooltip code
beforeEach(module('ui.bootstrap.tooltip', function ( $tooltipProvider ) {
$tooltipProvider.options({ animation: false });
}));

// load the template
beforeEach(module('template/tooltip/tooltip-html-popup.html'));

beforeEach(inject(function($rootScope, $compile, $sce) {
scope = $rootScope;
scope.html = 'I say: <strong class="hello">Hello!</strong>';
scope.safeHtml = $sce.trustAsHtml(scope.html);

elmBody = $compile( angular.element(
'<div><span tooltip-html="safeHtml">Selector Text</span></div>'
))( scope );
scope.$digest();
elm = elmBody.find('span');
elmScope = elm.scope();
tooltipScope = elmScope.$$childTail;
}));

it( 'should render html properly', inject( function () {
elm.trigger( 'mouseenter' );
expect( elmBody.find('.tooltip-inner').html() ).toBe( scope.html );
}));

it( 'should show on mouseenter and hide on mouseleave', inject( function ($sce) {
expect( tooltipScope.isOpen ).toBe( false );

elm.trigger( 'mouseenter' );
expect( tooltipScope.isOpen ).toBe( true );
expect( elmBody.children().length ).toBe( 2 );

expect( $sce.getTrustedHtml(tooltipScope.contentExp()) ).toEqual( scope.html );

elm.trigger( 'mouseleave' );
expect( tooltipScope.isOpen ).toBe( false );
expect( elmBody.children().length ).toBe( 1 );
}));
});

describe( 'tooltipHtmlUnsafe', function() {
var elm, elmBody, elmScope, tooltipScope, scope;
var logWarnSpy;

// load the tooltip code
beforeEach(module('ui.bootstrap.tooltip', function ( $tooltipProvider ) {
Expand All @@ -509,10 +555,12 @@ describe( 'tooltipHtmlUnsafe', function() {
// load the template
beforeEach(module('template/tooltip/tooltip-html-unsafe-popup.html'));

beforeEach(inject(function($rootScope, $compile) {
beforeEach(inject(function($rootScope, $compile, $log) {
scope = $rootScope;
scope.html = 'I say: <strong class="hello">Hello!</strong>';

logWarnSpy = spyOn($log, 'warn');

elmBody = $compile( angular.element(
'<div><span tooltip-html-unsafe="{{html}}">Selector Text</span></div>'
))( scope );
Expand All @@ -522,6 +570,10 @@ describe( 'tooltipHtmlUnsafe', function() {
tooltipScope = elmScope.$$childTail;
}));

it( 'should warn that this is deprecated', function () {
expect(logWarnSpy).toHaveBeenCalledWith(jasmine.stringMatching('deprecated'));
});

it( 'should render html properly', inject( function () {
elm.trigger( 'mouseenter' );
expect( elmBody.find('.tooltip-inner').html() ).toBe( scope.html );
Expand Down
26 changes: 25 additions & 1 deletion src/tooltip/tooltip.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
'<div '+ directiveName +'-popup '+
'title="'+startSym+'title'+endSym+'" '+
'content="'+startSym+'content'+endSym+'" '+
'content-exp="contentExp()" '+
'placement="'+startSym+'placement'+endSym+'" '+
'class="'+startSym+'class'+endSym+'" '+
'animation="animation" '+
Expand Down Expand Up @@ -265,6 +266,10 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
prepPopupDelay();
}

ttScope.contentExp = function () {
return scope.$eval(attrs[type]);
};

/**
* Observe the relevant attributes.
*/
Expand Down Expand Up @@ -469,6 +474,19 @@ function ($animate , $sce , $compile , $templateRequest) {
return $tooltip( 'tooltipTemplate', 'tooltip', 'mouseenter' );
}])

.directive( 'tooltipHtmlPopup', function () {
return {
restrict: 'EA',
replace: true,
scope: { contentExp: '&', placement: '@', class: '@', animation: '&', isOpen: '&' },
templateUrl: 'template/tooltip/tooltip-html-popup.html'
};
})

.directive( 'tooltipHtml', [ '$tooltip', function ( $tooltip ) {
return $tooltip( 'tooltipHtml', 'tooltip', 'mouseenter' );
}])

/*
Deprecated
*/
Expand All @@ -481,6 +499,12 @@ Deprecated
};
})

.directive( 'tooltipHtmlUnsafe', [ '$tooltip', function ( $tooltip ) {
.value('tooltipHtmlUnsafeSuppressDeprecated', false)
.directive( 'tooltipHtmlUnsafe', [
'$tooltip', 'tooltipHtmlUnsafeSuppressDeprecated', '$log',
function ( $tooltip , tooltipHtmlUnsafeSuppressDeprecated , $log) {
if (!tooltipHtmlUnsafeSuppressDeprecated) {
$log.warn('tooltip-html-unsafe is now deprecated. Use tooltip-html or tooltip-template instead.');
}
return $tooltip( 'tooltipHtmlUnsafe', 'tooltip', 'mouseenter' );
}]);
4 changes: 4 additions & 0 deletions template/tooltip/tooltip-html-popup.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<div class="tooltip {{placement}} {{class}}" ng-class="{ in: isOpen(), fade: animation() }">
<div class="tooltip-arrow"></div>
<div class="tooltip-inner" ng-bind-html="contentExp()"></div>
</div>

0 comments on commit e31fcf0

Please sign in to comment.