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

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

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:

  • User
  • 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’);

    Related:  How to Know Which HTML Element is Causing Vertical Scroll Bar

    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)
    });

    Solutions/Answers:

    Solution 1:

    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.

    Related:  Rails 5 - Uncaught Error: Bootstrap dropdown require Popper.js

    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');
        });
    

    Solution 2:

    Very simple, add hover to data-trigger as follows:

    <span rel="popover" data-trigger="hover click" data-container="body" data-placement="auto" data-content="Body Text"></span>
    

    Solution 3:

    Here’s a hybrid popover/tooltip that could give you the functionality that you are looking for both options, toggles on click and hover):

    Hybrid popover/tooltip fiddle

    HTML:

    <button id="tip1" type="button" class="btn btn-default" data-toggle="tooltip" data-placement="bottom" title='this text!'>What's hidden?</button>
    

    JS:

    var $tip1 = $('#tip1');
    
    $tip1.tooltip({trigger: 'hover'})
      .on('click', function() {
        $tip1.tooltip('toggle');
    });
    

    Solution 4:

    Here’s the way I accomplished the hover/pin functionality using Bootstrap and JQuery:

    $(function () {
        var clicked = false;
    
        var onLeave = function() {
            if (!clicked) { $(this).popover('hide'); }
        };
    
        var onEnter = function () {
            if (!clicked) { $(this).popover('show'); }
        };
    
        var clickToggle = function() {
            if (clicked) { $(this).popover('hide'); }
            clicked = !clicked;
        }
        $('.popover-div-class').popover({ trigger: "manual"})
            .on('mouseenter', onEnter)
            .on('mouseleave', onLeave)
            .on('click', clickToggle);
    });
    

    I’m not sure it’ll work in all scenarios, but it worked in mine. Big shoutout to @hajpoj and @Trevor for the inspiration.

    Related:  Possible to install just Bootstrap CSS with Bower?

    JSFiddle: https://jsfiddle.net/5m2ob3yf/ (Doesn’t work yet, but you can get the gist).

    References