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

feat($tooltip): support for custom triggers #364

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/popover/docs/demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ <h4>Positional</h4>
<button popover-placement="right" popover="On the Right!" class="btn">Right</button>
<button popover-placement="bottom" popover="On the Bottom!" class="btn">Bottom</button>
</div>
<div>
<h4>Triggers</h4>
<button popover="I appeared on mouse enter!" popover-trigger="mouseenter" class="btn">Mouseenter</button>
<input type="text" value="Click me!"
popover="I appeared on focus! Click away and I'll vanish..."
popover-trigger="focus" />
</div>
<div>
<h4>Other</h4>
<button Popover-animation="true" popover="I fade in and out!" class="btn">fading</button>
Expand Down
2 changes: 2 additions & 0 deletions src/popover/docs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ will display:
- `popover-animation`: Should it fade in and out? Defaults to "true".
- `popover-popup-delay`: For how long should the user have to have the mouse
over the element before the popover shows (in milliseconds)? Defaults to 0.
- `popover-trigger`: What should trigger the show of the popover? See the
`tooltip` directive for supported values.

The popover directives require the `$position` service.

86 changes: 0 additions & 86 deletions src/popover/test/popoverSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,92 +44,6 @@ describe('popover', function() {
elm.trigger( 'click' );
expect( elmScope.tt_isOpen ).toBe( false );
}));

it('should have default placement of "top"', inject(function() {
elm.trigger( 'click' );
expect( elmScope.tt_placement ).toBe( "top" );
}));

it('should allow specification of placement', inject( function( $compile ) {
elm = $compile( angular.element(
'<span popover="popover text" popover-placement="bottom">Selector Text</span>'
) )( scope );
elmScope = elm.scope();

elm.trigger( 'click' );
expect( elmScope.tt_placement ).toBe( "bottom" );
}));

it('should work inside an ngRepeat', inject( function( $compile ) {

elm = $compile( angular.element(
'<ul>'+
'<li ng-repeat="item in items">'+
'<span popover="{{item.popover}}">{{item.name}}</span>'+
'</li>'+
'</ul>'
) )( scope );

scope.items = [
{ name: "One", popover: "First popover" }
];

scope.$digest();

var tt = angular.element( elm.find("li > span")[0] );

tt.trigger( 'click' );

expect( tt.text() ).toBe( scope.items[0].name );
expect( tt.scope().tt_content ).toBe( scope.items[0].popover );

tt.trigger( 'click' );
}));

it('should only have an isolate scope on the popup', inject( function ( $compile ) {
var ttScope;

scope.popoverContent = "Popover Content";
scope.popoverTitle = "Popover Title";
scope.alt = "Alt Message";

elmBody = $compile( angular.element(
'<div><span alt={{alt}} popover="{{popoverContent}}" popover-title="{{popoverTitle}}">Selector Text</span></div>'
) )( scope );

$compile( elmBody )( scope );
scope.$digest();
elm = elmBody.find( 'span' );
elmScope = elm.scope();

elm.trigger( 'click' );
expect( elm.attr( 'alt' ) ).toBe( scope.alt );

ttScope = angular.element( elmBody.children()[1] ).scope();
expect( ttScope.placement ).toBe( 'top' );
expect( ttScope.title ).toBe( scope.popoverTitle );
expect( ttScope.content ).toBe( scope.popoverContent );

elm.trigger( 'click' );
}));


it( 'should allow specification of delay', inject( function ($timeout, $compile) {

elm = $compile( angular.element(
'<span popover="popover text" popover-popup-delay="1000">Selector Text</span>'
) )( scope );
elmScope = elm.scope();
scope.$digest();

elm.trigger( 'click' );
expect( elmScope.tt_isOpen ).toBe( false );

$timeout.flush();
expect( elmScope.tt_isOpen ).toBe( true );

} ) );

});


7 changes: 7 additions & 0 deletions src/tooltip/docs/demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,12 @@
<p>
I can even contain HTML. <a><span tooltip-html-unsafe="{{htmlTooltip}}">Check me out!</span></a>
</p>
<p>
Or use custom triggers, like focus:
<input type="text" value="Click me!"
tooltip="See? Now click away..."
tooltip-trigger="focus"
tooltip-placement="right" />
</p>
</div>
</div>
13 changes: 13 additions & 0 deletions src/tooltip/docs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,19 @@ will display:
- `tooltip-animation`: Should it fade in and out? Defaults to "true".
- `tooltip-popup-delay`: For how long should the user have to have the mouse
over the element before the tooltip shows (in milliseconds)? Defaults to 0.
- `tooltip-trigger`: What should trigger a show of the tooltip?

The tooltip directives require the `$position` service.

**Triggers**

The following show triggers are supported out of the box, along with their
provided hide triggers:

- `mouseenter`: `mouseleave`
- `click`: `click`
- `focus`: `blur`

For any non-supported value, the trigger will be used to both show and hide the
tooltip.

113 changes: 102 additions & 11 deletions src/tooltip/test/tooltip.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ describe('tooltip', function() {
elm = $compile( angular.element(
'<span tooltip="tooltip text" tooltip-placement="bottom">Selector Text</span>'
) )( scope );
scope.$apply();
elmScope = elm.scope();

elm.trigger( 'mouseenter' );
Expand Down Expand Up @@ -161,6 +162,46 @@ describe('tooltip', function() {

});

describe( 'with a trigger attribute', function() {
var scope, elmBody, elm, elmScope;

beforeEach( inject( function( $rootScope ) {
scope = $rootScope;
}));

it( 'should use it to show but set the hide trigger based on the map for mapped triggers', inject( function( $compile ) {
elmBody = angular.element(
'<div><input tooltip="Hello!" tooltip-trigger="focus" /></div>'
);
$compile(elmBody)(scope);
scope.$apply();
elm = elmBody.find('input');
elmScope = elm.scope();

expect( elmScope.tt_isOpen ).toBeFalsy();
elm.trigger('focus');
expect( elmScope.tt_isOpen ).toBeTruthy();
elm.trigger('blur');
expect( elmScope.tt_isOpen ).toBeFalsy();
}));

it( 'should use it as both the show and hide triggers for unmapped triggers', inject( function( $compile ) {
elmBody = angular.element(
'<div><input tooltip="Hello!" tooltip-trigger="fakeTriggerAttr" /></div>'
);
$compile(elmBody)(scope);
scope.$apply();
elm = elmBody.find('input');
elmScope = elm.scope();

expect( elmScope.tt_isOpen ).toBeFalsy();
elm.trigger('fakeTriggerAttr');
expect( elmScope.tt_isOpen ).toBeTruthy();
elm.trigger('fakeTriggerAttr');
expect( elmScope.tt_isOpen ).toBeFalsy();
}));
});

});

describe( 'tooltipHtmlUnsafe', function() {
Expand Down Expand Up @@ -202,13 +243,13 @@ describe( 'tooltipHtmlUnsafe', function() {
});

describe( '$tooltipProvider', function() {

describe( 'popupDelay', function() {
var elm,
var elm,
elmBody,
scope,
elmScope;
scope,
elmScope,
body;

describe( 'popupDelay', function() {
beforeEach(module('ui.bootstrap.tooltip', function($tooltipProvider){
$tooltipProvider.options({popupDelay: 1000});
}));
Expand Down Expand Up @@ -241,12 +282,6 @@ describe( '$tooltipProvider', function() {
});

describe('appendToBody', function() {
var elm,
elmBody,
scope,
elmScope,
body;

// load the tooltip code
beforeEach(module('ui.bootstrap.tooltip', function ( $tooltipProvider ) {
$tooltipProvider.options({ appendToBody: true });
Expand Down Expand Up @@ -275,5 +310,61 @@ describe( '$tooltipProvider', function() {
expect( $body.children().length ).toEqual( bodyLength + 1 );
}));
});

describe( 'triggers', function() {
describe( 'triggers with a mapped value', function() {
beforeEach(module('ui.bootstrap.tooltip', function($tooltipProvider){
$tooltipProvider.options({trigger: 'focus'});
}));

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

it( 'should use the show trigger and the mapped value for the hide trigger', inject( function ( $rootScope, $compile ) {
elmBody = angular.element(
'<div><input tooltip="tooltip text" /></div>'
);

scope = $rootScope;
$compile(elmBody)(scope);
scope.$digest();
elm = elmBody.find('input');
elmScope = elm.scope();

expect( elmScope.tt_isOpen ).toBeFalsy();
elm.trigger('focus');
expect( elmScope.tt_isOpen ).toBeTruthy();
elm.trigger('blur');
expect( elmScope.tt_isOpen ).toBeFalsy();
}));
});

describe( 'triggers without a mapped value', function() {
beforeEach(module('ui.bootstrap.tooltip', function($tooltipProvider){
$tooltipProvider.options({trigger: 'fakeTrigger'});
}));

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

it( 'should use the show trigger to hide', inject( function ( $rootScope, $compile ) {
elmBody = angular.element(
'<div><span tooltip="tooltip text">Selector Text</span></div>'
);

scope = $rootScope;
$compile(elmBody)(scope);
scope.$digest();
elm = elmBody.find('span');
elmScope = elm.scope();

expect( elmScope.tt_isOpen ).toBeFalsy();
elm.trigger('fakeTrigger');
expect( elmScope.tt_isOpen ).toBeTruthy();
elm.trigger('fakeTrigger');
expect( elmScope.tt_isOpen ).toBeFalsy();
}));
});
});
});

Loading