Bootstrap 3 Popover: display on hover AND on click, aka. Pin a Popover

stk11067 picture stk11067 · Sep 11, 2013 · Viewed 62.5k times · Source

Making a popover appear with the hover trigger works fine.

Making a popover appear with the click trigger works fine.

Now, how do I go about making the popover appear when the triggering image is hovered over, but then if the user clicks on the image, cancel the hover and initiate a click toggle? In other words, hovering shows the popover and clicking 'pins' the popover.

The HTML is pretty standard:

<li>User<span class="glyphicon glyphicon-user" rel="popover" data-trigger="click" data-container="body" data-placement="auto left" data-content="Body Text" data-original-title="Title Text"></span></li>

And the popover initialization, even more boring:

$(function () { 
    $("[rel=popover]").popover();   
});

From what I have seen so far, it seems likely that the solution is a nice complex set of popover('show'), popover('hide'), and popover('toggle') calls, but my javascript / jQuery-foo is not up to the task.

EDIT:

Using the code provided by @hajpoj as a base, I added a function to listen to the hidden.bs.popover event to try to re-enable the mouseenter and mouseleave events after triggering the click event, but although it does make the 'hover' work again, it kills the click...

var $btn2 = $('#btn2');

    var enterShow = function() {
        $btn2.popover('show');
    };

    var exitHide = function() {
        $btn2.popover('hide');
    }

    $btn2.popover({trigger: 'manual'})
            .on('mouseenter', enterShow)
            .on('mouseleave', exitHide)
            .one('click', function() {
                   $btn2.off('mouseenter', enterShow)
                        .off('mouseleave', exitHide)
                        .on('click', function() {
                            $btn2.popover('toggle');
                        });
            });

$('#btn2').on('hidden.bs.popover', function () {
  $btn2.on('mouseenter', enterShow)
       .on('mouseleave', exitHide)
});

Answer

hajpoj picture hajpoj · Sep 12, 2013

Edit:

Heres an updated solutions based off your comment. It doesn't stay in a 'click' state but returns to the hover state.

jsfiddle: http://jsfiddle.net/hajpoj/JJQS9/15/

html:

<a href="#" id="btn2" class="btn btn-lg btn-danger" data-toggle="popover" title="" data-content="And here's some amazing content. It's very engaging. right?" data-original-title="A Title">Click to toggle popover</a>

js:

var $btn2 = $('#btn2');
$btn2.data('state', 'hover');

var enterShow = function () {
    if ($btn2.data('state') === 'hover') {
        $btn2.popover('show');
    }
};
var exitHide = function () {
    if ($btn2.data('state') === 'hover') {
        $btn2.popover('hide');
    }
};

var clickToggle = function () {
    if ($btn2.data('state') === 'hover') {
        $btn2.data('state', 'pinned');
    } else {
        $btn2.data('state', 'hover')
        $btn.popover('hover');
    }
};

$btn2.popover({trigger: 'manual'})
    .on('mouseenter', enterShow)
    .on('mouseleave', exitHide)
    .on('click', clickToggle);

Old:

I believe this is what you are looking for:

http://jsfiddle.net/JJQS9/1/

html:

<a href="#" id="btn2" class="btn btn-lg btn-danger" data-toggle="popover" title="" data-content="And here's some amazing content. It's very engaging. right?" data-original-title="A Title">Click to toggle popover</a>

js:

var $btn2 = $('#btn2');

var enterShow = function() {
    $btn2.popover('show');
};

var exitHide = function() {
    $btn2.popover('hide');
}

$btn2.popover({trigger: 'manual'})
        .on('mouseenter', enterShow)
        .on('mouseleave', exitHide)
        .one('click', function() {
            $btn2.off('mouseenter', enterShow)
                    .off('mouseleave', exitHide)
                    .on('click', function() {
                        $btn2.popover('toggle');
                    });
        });

Basically you manually pop open/close the popover on the mouseenter and mouseleave events, but once someone clicks on the popover for the first time, you remove those event handlers, and add a new handler on the click event that toggles the popover.

Edit: an alternative js code. simpler code, but there is a small visual blip when you use it: http://jsfiddle.net/hajpoj/r3Ckt/1/

var $btn2 = $('#btn2');

$btn2.popover({trigger: 'hover'})
    .one('click', function() {
        $btn2.popover('destroy')
            .popover({ trigger: 'click'})
            .popover('show');
    });