Keep Bootstrap Popover open when you hover over content

Popover with 'trigger: hover' option disappears when you move mouse away from the trigger element – even if you move mouse to the actual popover. Try to click a darn link in the popover. Sometimes while moving mouse from popover trigger to actual popover content diagonally, you hover over elements below. I wanted to handle such situations – as long as you reach popover content before the timeout fires, you're save (the popover won't disappear). It requires delay option. This hack basically overrides Popover leave function, but calls the original (which starts timer to hide the popover). Then it attaches a one-off listener to mouseenter popover content element's. If mouse enters the popover, the timer is cleared. Then it turns it listens to mouseleave on popover and if it's triggered, it calls the original leave function so that it could start hide timer.

by HugeHugh

HTML

<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<p id='container'>
<button class='btn btn-primary btn-large' data-popover="true" data-html=true data-content="<a href='http://www.hughanderson.com' target='blank' >click me, I'll try not to disappear</a>">hover here</button>
</p>

<a target="_top" href="http://stackoverflow.com/questions/15989591/how-can-i-keep-bootstrap-popover-alive-while-the-popover-is-being-hovered">See the Stack Overflow question</a>
<br/>

<a target="_top" href="http://www.hughanderson.com">www.hughanderson.com</a>

CSS

#container {
    text-align: center;
    margin: 8em 3em;
}

JavaScript

// make popover stay when hovered
    var originalLeave = $.fn.popover.Constructor.prototype.leave;
    $.fn.popover.Constructor.prototype.leave = function(obj){
      var self = obj instanceof this.constructor ?
        obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type);

      originalLeave.call(this, obj);

      if(obj.currentTarget) {
        var container = $(obj.currentTarget).next('.popover')
        container.one('mouseenter.tooltip.extra', function() {
            self.hoverState = 'in'
          // mouse entered the popover, so cancel the current timer
          clearTimeout(self.timeout);
          // attach events to popover content instead
          container.one('mouseleave.tooltip.extra', function(){
            $.fn.popover.Constructor.prototype.leave.call(self, self);
          });
        })
      }
    };
    
    var originalShow = $.fn.popover.Constructor.prototype.show;
    $.fn.popover.Constructor.prototype.show = function() {
        var thisTip = this.tip();
        // make only one popover able to be displayed
        $('.popover').not(thisTip).popover('hide');
        if (!thisTip.is(':visible')) {
            originalShow.call(this);
        }
    }
    
$('body').popover({ selector: '[data-popover]', trigger: 'click hover', placement: 'auto', delay: {show: 50, hide: 400}});