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

feat(tooltip,popover): logic moved to $tooltip svc #210

Closed
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
3 changes: 3 additions & 0 deletions src/popover/docs/readme.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
A lightweight, extensible directive for fancy popover creation. The popover
directive supports multiple placements, optional transition animation, and more.

Like the Twitter Bootstrap jQuery plugin, the popover **requires** the tooltip
module.
144 changes: 4 additions & 140 deletions src/popover/popover.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,152 +3,16 @@
* function, placement as a function, inside, support for more triggers than
* just mouse enter/leave, html popovers, and selector delegatation.
*/
angular.module( 'ui.bootstrap.popover', [] )
angular.module( 'ui.bootstrap.popover', [ 'ui.bootstrap.tooltip' ] )
.directive( 'popoverPopup', function () {
return {
restrict: 'EA',
replace: true,
scope: { popoverTitle: '@', popoverContent: '@', placement: '@', animation: '&', isOpen: '&' },
scope: { title: '@', content: '@', placement: '@', animation: '&', isOpen: '&' },
templateUrl: 'template/popover/popover.html'
};
})
.directive( 'popover', [ '$compile', '$timeout', '$parse', '$window', function ( $compile, $timeout, $parse, $window ) {

var template =
'<popover-popup '+
'popover-title="{{tt_title}}" '+
'popover-content="{{tt_popover}}" '+
'placement="{{tt_placement}}" '+
'animation="tt_animation()" '+
'is-open="tt_isOpen"'+
'>'+
'</popover-popup>';

return {
scope: true,
link: function ( scope, element, attr ) {
var popover = $compile( template )( scope ),
transitionTimeout;

attr.$observe( 'popover', function ( val ) {
scope.tt_popover = val;
});

attr.$observe( 'popoverTitle', function ( val ) {
scope.tt_title = val;
});

attr.$observe( 'popoverPlacement', function ( val ) {
// If no placement was provided, default to 'top'.
scope.tt_placement = val || 'top';
});

attr.$observe( 'popoverAnimation', function ( val ) {
scope.tt_animation = $parse( val );
});

// By default, the popover is not open.
scope.tt_isOpen = false;

// Calculate the current position and size of the directive element.
function getPosition() {
var boundingClientRect = element[0].getBoundingClientRect();
return {
width: element.prop( 'offsetWidth' ),
height: element.prop( 'offsetHeight' ),
top: boundingClientRect.top + $window.pageYOffset,
left: boundingClientRect.left + $window.pageXOffset
};
}

function show() {
var position,
ttWidth,
ttHeight,
ttPosition;

// If there is a pending remove transition, we must cancel it, lest the
// toolip be mysteriously removed.
if ( transitionTimeout ) {
$timeout.cancel( transitionTimeout );
}

// Set the initial positioning.
popover.css({ top: 0, left: 0, display: 'block' });

// Now we add it to the DOM because need some info about it. But it's not
// visible yet anyway.
element.after( popover );

// Get the position of the directive element.
position = getPosition();

// Get the height and width of the popover so we can center it.
ttWidth = popover.prop( 'offsetWidth' );
ttHeight = popover.prop( 'offsetHeight' );

// Calculate the popover's top and left coordinates to center it with
// this directive.
switch ( scope.tt_placement ) {
case 'right':
ttPosition = {
top: (position.top + position.height / 2 - ttHeight / 2) + 'px',
left: (position.left + position.width) + 'px'
};
break;
case 'bottom':
ttPosition = {
top: (position.top + position.height) + 'px',
left: (position.left + position.width / 2 - ttWidth / 2) + 'px'
};
break;
case 'left':
ttPosition = {
top: (position.top + position.height / 2 - ttHeight / 2) + 'px',
left: (position.left - ttWidth) + 'px'
};
break;
default:
ttPosition = {
top: (position.top - ttHeight) + 'px',
left: (position.left + position.width / 2 - ttWidth / 2) + 'px'
};
break;
}

// Now set the calculated positioning.
popover.css( ttPosition );

// And show the popover.
scope.tt_isOpen = true;
}

// Hide the popover popup element.
function hide() {
// First things first: we don't show it anymore.
//popover.removeClass( 'in' );
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.tt_animation ) && scope.tt_animation() ) {
transitionTimeout = $timeout( function () { popover.remove(); }, 500 );
} else {
popover.remove();
}
}

// Register the event listeners.
element.bind( 'click', function() {
if(scope.tt_isOpen){
scope.$apply( hide );
} else {
scope.$apply( show );
}

});
}
};
.directive( 'popover', [ '$compile', '$timeout', '$parse', '$window', '$tooltip', function ( $compile, $timeout, $parse, $window, $tooltip ) {
return $tooltip( 'popover', 'click' );
}]);

12 changes: 6 additions & 6 deletions src/popover/test/popoverSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,20 +81,20 @@ describe('popover', function() {
tt.trigger( 'click' );

expect( tt.text() ).toBe( scope.items[0].name );
expect( tt.scope().tt_popover ).toBe( scope.items[0].popover );
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.popoverMsg = "popover Text";
scope.popoverTitle = "popover Text";
scope.popoverContent = "Popover Content";
scope.popoverTitle = "Popover Title";
scope.alt = "Alt Message";

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

$compile( elmBody )( scope );
Expand All @@ -107,8 +107,8 @@ describe('popover', function() {

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

elm.trigger( 'click' );
}));
Expand Down
2 changes: 1 addition & 1 deletion src/tooltip/docs/demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
nunc sed velit dignissim sodales ut eu sem integer vitae. Turpis egestas
<a><span tooltip-placement="bottom" tooltip="On the Bottom!">bottom</span></a>
pharetra convallis posuere morbi leo urna,
<a><span tooltip-animation="true" tooltip="I fade in and out!">fading</span></a>
<a><span tooltip-animation="false" tooltip="I don't fade. :-(">fading</span></a>
at elementum eu, facilisis sed odio morbi quis commodo odio. In cursus
turpis massa tincidunt dui ut.
</p>
Expand Down
4 changes: 2 additions & 2 deletions src/tooltip/test/tooltip.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ describe('tooltip', function() {
tt.trigger( 'mouseenter' );

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

tt.trigger( 'mouseleave' );
}));
Expand All @@ -106,7 +106,7 @@ describe('tooltip', function() {

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

elm.trigger( 'mouseleave' );
}));
Expand Down
Loading