diff --git a/src/popover/test/popoverSpec.js b/src/popover/test/popoverSpec.js
index 633aeb8b2c..81e37d4734 100644
--- a/src/popover/test/popoverSpec.js
+++ b/src/popover/test/popoverSpec.js
@@ -1,7 +1,7 @@
describe('popover', function() {
- var elm,
+ var elm,
elmBody,
- scope,
+ scope,
elmScope;
// load the popover code
@@ -11,8 +11,8 @@ describe('popover', function() {
beforeEach(module('template/popover/popover.html'));
beforeEach(inject(function($rootScope, $compile) {
- elmBody = angular.element(
- '
Selector Text
'
+ elmBody = angular.element(
+ 'Selector Text
'
);
scope = $rootScope;
@@ -24,7 +24,7 @@ describe('popover', function() {
it('should not be open initially', inject(function() {
expect( elmScope.tt_isOpen ).toBe( false );
-
+
// We can only test *that* the popover-popup element wasn't created as the
// implementation is templated and replaced.
expect( elmBody.children().length ).toBe( 1 );
@@ -51,8 +51,8 @@ describe('popover', function() {
}));
it('should allow specification of placement', inject( function( $compile ) {
- elm = $compile( angular.element(
- 'Selector Text'
+ elm = $compile( angular.element(
+ 'Selector Text'
) )( scope );
elmScope = elm.scope();
@@ -62,7 +62,7 @@ describe('popover', function() {
it('should work inside an ngRepeat', inject( function( $compile ) {
- elm = $compile( angular.element(
+ elm = $compile( angular.element(
''+
'- '+
'{{item.name}}'+
@@ -73,11 +73,11 @@ describe('popover', function() {
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 );
@@ -93,7 +93,7 @@ describe('popover', function() {
scope.popoverTitle = "Popover Title";
scope.alt = "Alt Message";
- elmBody = $compile( angular.element(
+ elmBody = $compile( angular.element(
'
Selector Text
'
) )( scope );
@@ -101,7 +101,7 @@ describe('popover', function() {
scope.$digest();
elm = elmBody.find( 'span' );
elmScope = elm.scope();
-
+
elm.trigger( 'click' );
expect( elm.attr( 'alt' ) ).toBe( scope.alt );
@@ -113,6 +113,23 @@ describe('popover', function() {
elm.trigger( 'click' );
}));
+
+ it( 'should allow specification of delay', inject( function ($timeout, $compile) {
+
+ elm = $compile( angular.element(
+ 'Selector Text'
+ ) )( scope );
+ elmScope = elm.scope();
+ scope.$digest();
+
+ elm.trigger( 'click' );
+ expect( elmScope.tt_isOpen ).toBe( false );
+
+ $timeout.flush();
+ expect( elmScope.tt_isOpen ).toBe( true );
+
+ } ) );
+
});
diff --git a/src/tooltip/docs/demo.html b/src/tooltip/docs/demo.html
index 954c70e57e..737d8d5f28 100644
--- a/src/tooltip/docs/demo.html
+++ b/src/tooltip/docs/demo.html
@@ -13,8 +13,8 @@
bottom
pharetra convallis posuere morbi leo urna,
fading
- at elementum eu, facilisis sed odio morbi quis commodo odio. In cursus
- turpis massa tincidunt dui ut.
+ at elementum eu, facilisis sed odio morbi quis commodo odio. In cursus
+ delayed turpis massa tincidunt dui ut.
diff --git a/src/tooltip/test/tooltip.spec.js b/src/tooltip/test/tooltip.spec.js
index b9849df338..524de5ea4b 100644
--- a/src/tooltip/test/tooltip.spec.js
+++ b/src/tooltip/test/tooltip.spec.js
@@ -121,6 +121,84 @@ describe('tooltip', function() {
expect(elmBody.children().length).toBe(1);
}));
+
+ describe('with specified popup delay', function () {
+
+ beforeEach(inject(function ($compile) {
+ scope.delay='1000';
+ elm = $compile(angular.element(
+ 'Selector Text'
+ ))(scope);
+ elmScope = elm.scope();
+ scope.$digest();
+ }));
+
+ it('should open after timeout', inject(function ($timeout) {
+
+ elm.trigger('mouseenter');
+ expect(elmScope.tt_isOpen).toBe(false);
+
+ $timeout.flush();
+ expect(elmScope.tt_isOpen).toBe(true);
+
+ }));
+
+ it('should not open if mouseleave before timeout', inject(function ($timeout) {
+ elm.trigger('mouseenter');
+ expect(elmScope.tt_isOpen).toBe(false);
+
+ elm.trigger('mouseleave');
+ $timeout.flush();
+ expect(elmScope.tt_isOpen).toBe(false);
+ }));
+
+ it('should use default popup delay if specified delay is not a number', function(){
+ scope.delay='text1000';
+ scope.$digest();
+ elm.trigger('mouseenter');
+ expect(elmScope.tt_isOpen).toBe(true);
+ });
+
+ });
+
+});
+
+describe('tooltip with popup delay configured through provider', function(){
+
+ var elm,
+ elmBody,
+ scope,
+ elmScope;
+
+ beforeEach(module('ui.bootstrap.tooltip', function($tooltipProvider){
+ $tooltipProvider.options({popupDelay: 1000});
+ }));
+
+ // load the template
+ beforeEach(module('template/tooltip/tooltip-popup.html'));
+
+ beforeEach(inject(function($rootScope, $compile) {
+ elmBody = angular.element(
+ 'Selector Text
'
+ );
+
+ scope = $rootScope;
+ $compile(elmBody)(scope);
+ scope.$digest();
+ elm = elmBody.find('span');
+ elmScope = elm.scope();
+ }));
+
+ it('should open after timeout', inject(function($timeout) {
+
+ elm.trigger( 'mouseenter' );
+ expect( elmScope.tt_isOpen ).toBe( false );
+
+ $timeout.flush();
+ expect( elmScope.tt_isOpen ).toBe( true );
+
+ }));
+
});
diff --git a/src/tooltip/tooltip.js b/src/tooltip/tooltip.js
index 15617274a8..affe7f9f0a 100644
--- a/src/tooltip/tooltip.js
+++ b/src/tooltip/tooltip.js
@@ -1,5 +1,5 @@
/**
- * The following features are still outstanding: popup delay, animation as a
+ * The following features are still outstanding: animation as a
* function, placement as a function, inside, support for more triggers than
* just mouse enter/leave, html tooltips, and selector delegation.
*/
@@ -13,7 +13,8 @@ angular.module( 'ui.bootstrap.tooltip', [] )
// The default options tooltip and popover.
var defaultOptions = {
placement: 'top',
- animation: true
+ animation: true,
+ popupDelay: 0
};
// The options specified to the provider globally.
@@ -66,7 +67,8 @@ angular.module( 'ui.bootstrap.tooltip', [] )
scope: true,
link: function link ( scope, element, attrs ) {
var tooltip = $compile( template )( scope ),
- transitionTimeout;
+ transitionTimeout,
+ popupTimeout;
attrs.$observe( type, function ( val ) {
scope.tt_content = val;
@@ -84,9 +86,23 @@ angular.module( 'ui.bootstrap.tooltip', [] )
scope.tt_animation = angular.isDefined( val ) ? $parse( val ) : function(){ return options.animation; };
});
+ attrs.$observe( type+'PopupDelay', function ( val ) {
+ var delay = parseInt( val, 10 );
+ scope.tt_popupDelay = ! isNaN(delay) ? delay : options.popupDelay;
+ });
+
// By default, the tooltip is not open.
// TODO add ability to start tooltip opened
scope.tt_isOpen = false;
+
+ //show the tooltip with delay if specified, otherwise show it immediately
+ function showWithDelay() {
+ if( scope.tt_popupDelay ){
+ popupTimeout = $timeout( show, scope.tt_popupDelay );
+ }else {
+ scope.$apply( show );
+ }
+ }
// Show the tooltip popup element.
function show() {
@@ -101,7 +117,7 @@ angular.module( 'ui.bootstrap.tooltip', [] )
}
// If there is a pending remove transition, we must cancel it, lest the
- // toolip be mysteriously removed.
+ // tooltip be mysteriously removed.
if ( transitionTimeout ) {
$timeout.cancel( transitionTimeout );
}
@@ -161,6 +177,9 @@ angular.module( 'ui.bootstrap.tooltip', [] )
// First things first: we don't show it anymore.
//tooltip.removeClass( 'in' );
scope.tt_isOpen = false;
+
+ //if tooltip is going to be shown after delay, we must cancel this
+ $timeout.cancel( popupTimeout );
// And now we remove it from the DOM. However, if we have animation, we
// need to wait for it to expire beforehand.
@@ -178,14 +197,14 @@ angular.module( 'ui.bootstrap.tooltip', [] )
if ( ! angular.isDefined( defaultTriggerHide ) ) {
element.bind( defaultTriggerShow, function toggleTooltipBind () {
if ( ! scope.tt_isOpen ) {
- scope.$apply( show );
+ showWithDelay();
} else {
scope.$apply( hide );
}
});
} else {
element.bind( defaultTriggerShow, function showTooltipBind() {
- scope.$apply( show );
+ showWithDelay();
});
element.bind( defaultTriggerHide, function hideTooltipBind() {
scope.$apply( hide );