diff --git a/src/tooltip/test/tooltip.spec.js b/src/tooltip/test/tooltip.spec.js
index 01f6423fe7..90be4f6907 100644
--- a/src/tooltip/test/tooltip.spec.js
+++ b/src/tooltip/test/tooltip.spec.js
@@ -98,7 +98,7 @@ describe('tooltip', function() {
     scope.alt = "Alt Message";
 
     elmBody = $compile( angular.element( 
-      '<div><span alt={{alt}} tooltip="{{tooltipMsg}}">Selector Text</span></div>' 
+      '<div><span alt={{alt}} tooltip="{{tooltipMsg}}" tooltip-animation="false">Selector Text</span></div>'
     ) )( scope );
 
     $compile( elmBody )( scope );
@@ -114,6 +114,13 @@ describe('tooltip', function() {
     expect( ttScope.content ).toBe( scope.tooltipMsg );
 
     elm.trigger( 'mouseleave' );
+
+    //Isolate scope contents should be the same after hiding and showing again (issue 1191)
+    elm.trigger( 'mouseenter' );
+
+    ttScope = angular.element( elmBody.children()[1] ).scope();
+    expect( ttScope.placement ).toBe( 'top' );
+    expect( ttScope.content ).toBe( scope.tooltipMsg );
   }));
 
   it('should not show tooltips if there is nothing to show - issue #129', inject(function ($compile) {
@@ -136,6 +143,24 @@ describe('tooltip', function() {
     expect( elmBody.children().length ).toBe( 0 );
   }));
 
+  it('issue 1191 - isolate scope on the popup should always be child of correct element scope', inject( function ( $compile ) {
+    var ttScope;
+    elm.trigger( 'mouseenter' );
+
+    ttScope = angular.element( elmBody.children()[1] ).scope();
+    expect( ttScope.$parent ).toBe( elmScope );
+
+    elm.trigger( 'mouseleave' );
+
+    // After leaving and coming back, the scope's parent should be the same
+    elm.trigger( 'mouseenter' );
+
+    ttScope = angular.element( elmBody.children()[1] ).scope();
+    expect( ttScope.$parent ).toBe( elmScope );
+
+    elm.trigger( 'mouseleave' );
+  }));
+
   describe('with specified enable expression', function() {
 
     beforeEach(inject(function ($compile) {
@@ -323,18 +348,12 @@ describe('tooltip', function() {
 
       elm = elmBody.find('input');
       elmScope = elm.scope();
+      elm.trigger('fooTrigger');
       tooltipScope = elmScope.$$childTail;
     }));
 
-    it( 'should not contain a cached reference', function() {
-      expect( inCache() ).toBeTruthy();
-      elmScope.$destroy();
-      expect( inCache() ).toBeFalsy();
-    });
-
     it( 'should not contain a cached reference when visible', inject( function( $timeout ) {
       expect( inCache() ).toBeTruthy();
-      elm.trigger('fooTrigger');
       elmScope.$destroy();
       expect( inCache() ).toBeFalsy();
     }));
diff --git a/src/tooltip/tooltip.js b/src/tooltip/tooltip.js
index f6d116647f..c6a610f8f3 100644
--- a/src/tooltip/tooltip.js
+++ b/src/tooltip/tooltip.js
@@ -108,224 +108,245 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
       return {
         restrict: 'EA',
         scope: true,
-        link: function link ( scope, element, attrs ) {
-          var tooltip = $compile( template )( scope );
-          var transitionTimeout;
-          var popupTimeout;
-          var appendToBody = angular.isDefined( options.appendToBody ) ? options.appendToBody : false;
-          var triggers = getTriggers( undefined );
-          var hasRegisteredTriggers = false;
-          var hasEnableExp = angular.isDefined(attrs[prefix+'Enable']);
-
-          var positionTooltip = function (){
-            var position,
-              ttWidth,
-              ttHeight,
-              ttPosition;
-            // Get the position of the directive element.
-            position = appendToBody ? $position.offset( element ) : $position.position( element );
-
-            // Get the height and width of the tooltip so we can center it.
-            ttWidth = tooltip.prop( 'offsetWidth' );
-            ttHeight = tooltip.prop( 'offsetHeight' );
-
-            // Calculate the tooltip'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,
-                  left: position.left + position.width
-                };
-                break;
-              case 'bottom':
-                ttPosition = {
-                  top: position.top + position.height,
-                  left: position.left + position.width / 2 - ttWidth / 2
-                };
-                break;
-              case 'left':
-                ttPosition = {
-                  top: position.top + position.height / 2 - ttHeight / 2,
-                  left: position.left - ttWidth
-                };
-                break;
-              default:
-                ttPosition = {
-                  top: position.top - ttHeight,
-                  left: position.left + position.width / 2 - ttWidth / 2
-                };
-                break;
+        compile: function (tElem, tAttrs) {
+          var tooltipLinker = $compile( template );
+
+          return function link ( scope, element, attrs ) {
+            var tooltip;
+            var transitionTimeout;
+            var popupTimeout;
+            var appendToBody = angular.isDefined( options.appendToBody ) ? options.appendToBody : false;
+            var triggers = getTriggers( undefined );
+            var hasRegisteredTriggers = false;
+            var hasEnableExp = angular.isDefined(attrs[prefix+'Enable']);
+
+            var positionTooltip = function (){
+              var position,
+                ttWidth,
+                ttHeight,
+                ttPosition;
+              // Get the position of the directive element.
+              position = appendToBody ? $position.offset( element ) : $position.position( element );
+
+              // Get the height and width of the tooltip so we can center it.
+              ttWidth = tooltip.prop( 'offsetWidth' );
+              ttHeight = tooltip.prop( 'offsetHeight' );
+
+              // Calculate the tooltip'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,
+                    left: position.left + position.width
+                  };
+                  break;
+                case 'bottom':
+                  ttPosition = {
+                    top: position.top + position.height,
+                    left: position.left + position.width / 2 - ttWidth / 2
+                  };
+                  break;
+                case 'left':
+                  ttPosition = {
+                    top: position.top + position.height / 2 - ttHeight / 2,
+                    left: position.left - ttWidth
+                  };
+                  break;
+                default:
+                  ttPosition = {
+                    top: position.top - ttHeight,
+                    left: position.left + position.width / 2 - ttWidth / 2
+                  };
+                  break;
+              }
+
+              ttPosition.top += 'px';
+              ttPosition.left += 'px';
+
+              // Now set the calculated positioning.
+              tooltip.css( ttPosition );
+
+            };
+
+            // By default, the tooltip is not open.
+            // TODO add ability to start tooltip opened
+            scope.tt_isOpen = false;
+
+            function toggleTooltipBind () {
+              if ( ! scope.tt_isOpen ) {
+                showTooltipBind();
+              } else {
+                hideTooltipBind();
+              }
             }
 
-            ttPosition.top += 'px';
-            ttPosition.left += 'px';
+            // Show the tooltip with delay if specified, otherwise show it immediately
+            function showTooltipBind() {
+              if(hasEnableExp && !scope.$eval(attrs[prefix+'Enable'])) {
+                return;
+              }
+              if ( scope.tt_popupDelay ) {
+                popupTimeout = $timeout( show, scope.tt_popupDelay, false );
+                popupTimeout.then(function(reposition){reposition();});
+              } else {
+                show()();
+              }
+            }
 
-            // Now set the calculated positioning.
-            tooltip.css( ttPosition );
+            function hideTooltipBind () {
+              scope.$apply(function () {
+                hide();
+              });
+            }
 
-          };
+            // Show the tooltip popup element.
+            function show() {
 
-          // By default, the tooltip is not open.
-          // TODO add ability to start tooltip opened
-          scope.tt_isOpen = false;
 
-          function toggleTooltipBind () {
-            if ( ! scope.tt_isOpen ) {
-              showTooltipBind();
-            } else {
-              hideTooltipBind();
-            }
-          }
-          
-          // Show the tooltip with delay if specified, otherwise show it immediately
-          function showTooltipBind() {
-            if(hasEnableExp && !scope.$eval(attrs[prefix+'Enable'])) {
-              return;
-            }
-            if ( scope.tt_popupDelay ) {
-              popupTimeout = $timeout( show, scope.tt_popupDelay );
-              popupTimeout.then(function(reposition){reposition();});
-            } else {
-              scope.$apply( show )();
-            }
-          }
+              // Don't show empty tooltips.
+              if ( ! scope.tt_content ) {
+                return angular.noop;
+              }
 
-          function hideTooltipBind () {
-            scope.$apply(function () {
-              hide();
-            });
-          }
-          
-          // Show the tooltip popup element.
-          function show() {
+              createTooltip();
 
+              // If there is a pending remove transition, we must cancel it, lest the
+              // tooltip be mysteriously removed.
+              if ( transitionTimeout ) {
+                $timeout.cancel( transitionTimeout );
+              }
 
-            // Don't show empty tooltips.
-            if ( ! scope.tt_content ) {
-              return angular.noop;
-            }
+              // Set the initial positioning.
+              tooltip.css({ top: 0, left: 0, display: 'block' });
 
-            // If there is a pending remove transition, we must cancel it, lest the
-            // tooltip be mysteriously removed.
-            if ( transitionTimeout ) {
-              $timeout.cancel( transitionTimeout );
-            }
-            
-            // Set the initial positioning.
-            tooltip.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.
-            if ( appendToBody ) {
-                $document.find( 'body' ).append( tooltip );
-            } else {
-              element.after( tooltip );
+              // Now we add it to the DOM because need some info about it. But it's not 
+              // visible yet anyway.
+              if ( appendToBody ) {
+                  $document.find( 'body' ).append( tooltip );
+              } else {
+                element.after( tooltip );
+              }
+
+              positionTooltip();
+
+              // And show the tooltip.
+              scope.tt_isOpen = true;
+              scope.$digest(); // digest required as $apply is not called
+
+              // Return positioning function as promise callback for correct
+              // positioning after draw.
+              return positionTooltip;
             }
 
-            positionTooltip();
+            // Hide the tooltip popup element.
+            function hide() {
+              // First things first: we don't show it anymore.
+              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.
+              // FIXME: this is a placeholder for a port of the transitions library.
+              if ( scope.tt_animation ) {
+                transitionTimeout = $timeout(removeTooltip, 500);
+              } else {
+                removeTooltip();
+              }
+            }
 
-            // And show the tooltip.
-            scope.tt_isOpen = true;
+            function createTooltip() {
+              // There can only be one tooltip element per directive shown at once.
+              if (tooltip) {
+                removeTooltip();
+              }
+              tooltip = tooltipLinker(scope, function () {});
 
-            // Return positioning function as promise callback for correct
-            // positioning after draw.
-            return positionTooltip;
-          }
-          
-          // Hide the tooltip popup element.
-          function hide() {
-            // First things first: we don't show it anymore.
-            scope.tt_isOpen = false;
+              // Get contents rendered into the tooltip
+              scope.$digest();
+            }
 
-            //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.
-            // FIXME: this is a placeholder for a port of the transitions library.
-            if ( scope.tt_animation ) {
-              transitionTimeout = $timeout(function () {
+            function removeTooltip() {
+              if (tooltip) {
                 tooltip.remove();
-              }, 500);
-            } else {
-              tooltip.remove();
+                tooltip = null;
+              }
             }
-          }
 
-          /**
-           * Observe the relevant attributes.
-           */
-          attrs.$observe( type, function ( val ) {
-            scope.tt_content = val;
+            /**
+             * Observe the relevant attributes.
+             */
+            attrs.$observe( type, function ( val ) {
+              scope.tt_content = val;
 
-            if (!val && scope.tt_isOpen ) {
-              hide();
-            }
-          });
+              if (!val && scope.tt_isOpen ) {
+                hide();
+              }
+            });
 
-          attrs.$observe( prefix+'Title', function ( val ) {
-            scope.tt_title = val;
-          });
+            attrs.$observe( prefix+'Title', function ( val ) {
+              scope.tt_title = val;
+            });
 
-          attrs.$observe( prefix+'Placement', function ( val ) {
-            scope.tt_placement = angular.isDefined( val ) ? val : options.placement;
-          });
+            attrs.$observe( prefix+'Placement', function ( val ) {
+              scope.tt_placement = angular.isDefined( val ) ? val : options.placement;
+            });
 
-          attrs.$observe( prefix+'PopupDelay', function ( val ) {
-            var delay = parseInt( val, 10 );
-            scope.tt_popupDelay = ! isNaN(delay) ? delay : options.popupDelay;
-          });
+            attrs.$observe( prefix+'PopupDelay', function ( val ) {
+              var delay = parseInt( val, 10 );
+              scope.tt_popupDelay = ! isNaN(delay) ? delay : options.popupDelay;
+            });
 
-          var unregisterTriggers = function() {
-            if (hasRegisteredTriggers) {
-              element.unbind( triggers.show, showTooltipBind );
-              element.unbind( triggers.hide, hideTooltipBind );
-            }
-          };
+            var unregisterTriggers = function() {
+              if (hasRegisteredTriggers) {
+                element.unbind( triggers.show, showTooltipBind );
+                element.unbind( triggers.hide, hideTooltipBind );
+              }
+            };
 
-          attrs.$observe( prefix+'Trigger', function ( val ) {
-            unregisterTriggers();
+            attrs.$observe( prefix+'Trigger', function ( val ) {
+              unregisterTriggers();
 
-            triggers = getTriggers( val );
+              triggers = getTriggers( val );
 
-            if ( triggers.show === triggers.hide ) {
-              element.bind( triggers.show, toggleTooltipBind );
-            } else {
-              element.bind( triggers.show, showTooltipBind );
-              element.bind( triggers.hide, hideTooltipBind );
-            }
+              if ( triggers.show === triggers.hide ) {
+                element.bind( triggers.show, toggleTooltipBind );
+              } else {
+                element.bind( triggers.show, showTooltipBind );
+                element.bind( triggers.hide, hideTooltipBind );
+              }
 
-            hasRegisteredTriggers = true;
-          });
+              hasRegisteredTriggers = true;
+            });
 
-          var animation = scope.$eval(attrs[prefix + 'Animation']);
-          scope.tt_animation = angular.isDefined(animation) ? !!animation : options.animation;
+            var animation = scope.$eval(attrs[prefix + 'Animation']);
+            scope.tt_animation = angular.isDefined(animation) ? !!animation : options.animation;
 
-          attrs.$observe( prefix+'AppendToBody', function ( val ) {
-            appendToBody = angular.isDefined( val ) ? $parse( val )( scope ) : appendToBody;
-          });
+            attrs.$observe( prefix+'AppendToBody', function ( val ) {
+              appendToBody = angular.isDefined( val ) ? $parse( val )( scope ) : appendToBody;
+            });
 
-          // if a tooltip is attached to <body> we need to remove it on
-          // location change as its parent scope will probably not be destroyed
-          // by the change.
-          if ( appendToBody ) {
-            scope.$on('$locationChangeSuccess', function closeTooltipOnLocationChangeSuccess () {
-            if ( scope.tt_isOpen ) {
-              hide();
+            // if a tooltip is attached to <body> we need to remove it on
+            // location change as its parent scope will probably not be destroyed
+            // by the change.
+            if ( appendToBody ) {
+              scope.$on('$locationChangeSuccess', function closeTooltipOnLocationChangeSuccess () {
+              if ( scope.tt_isOpen ) {
+                hide();
+              }
+            });
             }
-          });
-          }
-
-          // Make sure tooltip is destroyed and removed.
-          scope.$on('$destroy', function onDestroyTooltip() {
-            $timeout.cancel( transitionTimeout );
-            $timeout.cancel( popupTimeout );
-            unregisterTriggers();
-            tooltip.remove();
-            tooltip.unbind();
-            tooltip = null;
-          });
+
+            // Make sure tooltip is destroyed and removed.
+            scope.$on('$destroy', function onDestroyTooltip() {
+              $timeout.cancel( transitionTimeout );
+              $timeout.cancel( popupTimeout );
+              unregisterTriggers();
+              removeTooltip();
+            });
+          };
         }
       };
     };