17

The following Bootstrap code gives me "sticky" popover (so users can interact with the content inside the popover). The issue is that when a popover is opened, other popovers should be closed (hidden). Any idea how I can implement this?

$("[rel=popover]").popover({placement:'bottom', trigger:'manual'}).hover(function(){
    $(this).popover('show');
    e.preventDefault(); 
});
farjam
  • 2,089
  • 8
  • 40
  • 77

15 Answers15

23

There's a very simple solution here (not my solution, but works beautifully):

$('.link-popover').click(function(){
    $('.link-popover').not(this).popover('hide'); //all but this
});
kristinalim
  • 3,459
  • 18
  • 27
adam
  • 359
  • 3
  • 7
  • Couldnt get this working without bugs appearing. For others looking into a simple solution like this, I added the following code to the "Show Popover event" in my solution which simply closes all other popovers $('.popover').not(this).hide(); – Dean Meehan Feb 12 '14 at 12:05
  • You nailed it :), you can cache link-popover, `var $link = $('.link-popover')` and then use the cached variable `$link.click ...`. – topless May 20 '14 at 09:26
  • 2
    demo link is broken. What is `.link-popover`? -- is that the trigger link or the popover container? – chovy Jul 30 '15 at 21:46
17

As per the bootstrap docs: Use the focus trigger to dismiss popovers on the next click that the user makes.

<a href="#" tabindex="0" class="btn btn-lg btn-danger" role="button" data-toggle="popover" data-   trigger="focus" title="Dismissible popover" data-content="And here's some amazing content. It's very engaging. Right?">Dismissible popover</a>
alexoviedo999
  • 6,761
  • 1
  • 26
  • 17
15

I've been having a play about with this and there's a few other problems regarding triggering the manual show/hide to get this to play nicely. Hover is actually mousein and mouseout and unless you add in some additional checks, you will come across the problems that I just did!

Here is my solution in action and I'll try to explain what I've done.

$(function () {

    var overPopup = false;

    $('[rel=popover]').popover({
        trigger: 'manual',
        placement: 'bottom'

    // replacing hover with mouseover and mouseout
    }).mouseover(function (e) {
        // when hovering over an element which has a popover, hide
        // them all except the current one being hovered upon
        $('[rel=popover]').not('#' + $(this).attr('id')).popover('hide');
        var $popover = $(this);
        $popover.popover('show');

        // set a flag when you move from button to popover
        // dirty but only way I could think of to prevent
        // closing the popover when you are navigate across
        // the white space between the two
        $popover.data('popover').tip().mouseenter(function () {
            overPopup = true;
        }).mouseleave(function () {
            overPopup = false;
            $popover.popover('hide');
        });

    }).mouseout(function (e) {
        // on mouse out of button, close the related popover
        // in 200 milliseconds if you're not hovering over the popover
        var $popover = $(this);
        setTimeout(function () {
            if (!overPopup) {
                $popover.popover('hide');
            }
        }, 200);
    });
});

This worked perfectly for me with the following html:

<a href="#" id="example1" class="btn large primary" rel="popover" data-content="Example 1!!!" data-original-title="Example 1 title">Button 1</a>
<a href="#" id="example2" class="btn large primary" rel="popover" data-content="Example 2!!!" data-original-title="Example 2 title">Button 2</a>
<a href="#" id="example3" class="btn large primary" rel="popover" data-content="Example 3!!!" data-original-title="Example 3 title">Button 3</a>

Hope that sorts you out :)

David Spence
  • 7,999
  • 3
  • 39
  • 63
  • Thanks, this works great. Is it possible to tweak this so the popover goes away when you mouse off the popover anywhere else on the document? Right now in your version, the popover goes away if you mouse over another item, but if you mouse off anywhere else on the page, the popover still stays open. – farjam Feb 08 '13 at 16:36
  • A bit confused... So you want it sticky until you hover in and out of the popup? – David Spence Feb 08 '13 at 21:12
  • I want it sticky the whole time you are interacting inside the popover. However, if the user moves on to the footer for example (not another popover-enabled item) the popover still remains open/active. This also happens in your own demo, try mousing over the last item, and continue moving your mouse to the right. You can see the popover never goes away. – farjam Feb 08 '13 at 21:24
  • I have updated my answer although I find your comments confusing... You would like the solution tweaked so the popover goes away when you mouse off of it anywhere else on the document, but if the user moves to the footer the popover should remain open/active... (unless you referring to the popover as the footer..?) – David Spence Feb 09 '13 at 02:52
  • Thanks, this is great. [Updated jsfiddle based on your edits](http://jsfiddle.net/sEKtD/111/). – farjam Feb 09 '13 at 22:50
  • Does anybody else find this glitchy after the first hover event has passed? Try moving the mouse back and forth between the 3 buttons a few times. – emc Jun 20 '13 at 06:11
  • 2
    `$popover.data('popover')` doesn't work as of today. Use `$popover.data('bs.popover')` instead. – khajvah Aug 25 '15 at 15:28
  • @npc - check if you are using id or not.without id it is missing popover in second time. – Bugfixer Jan 27 '16 at 07:50
8

Using Bootstrap 3's event callbacks you can do:

$(document).on('show.bs.popover', function() {
  $('.popover').not(this).popover('hide');
});

and in coffeescript

$(document).on 'show.bs.popover', ->
    $('.popover').not(this).popover('hide')
saneshark
  • 1,243
  • 13
  • 25
  • 3
    Introduces the double click bug. You have to click two times to get other popovers to open. – JPeG Dec 02 '16 at 21:16
4

Simpiet solution to close all other popovers. This can be added to any event where a popup will appear such as click/hover etc. Just before you show the popover paste in the following code:

$('.popover').not(this).hide(); //Hides all other popovers

This will remove all popovers on page except the current one

Dean Meehan
  • 2,511
  • 22
  • 36
  • how to convert it to coffe – andilabs Apr 11 '14 at 10:48
  • I've never used CoffeeJS but I used an online converter http://js2coffee.org/ that output this as the translation? $('.popover').not(this).hide(); //Hides all other popovers – Dean Meehan Apr 11 '14 at 10:51
  • Works great i updated using this [link](http://stackoverflow.com/questions/1403615/use-jquery-to-hide-a-div-when-the-user-clicks-outside-of-it) . – cabaji99 Jun 17 '15 at 21:06
3
$('li').popover({
    title: 'My title',
    content: 'My content'
})
.on('show.bs.popover', function() {
    if (window._bsPopover) {
        $(window._bsPopover).popover('hide')
    }
    window._bsPopover= this;
})
.on('hide.bs.popover', function() {
   window._bsPopover= null; // see Peter Jacoby's comment
});
Abdullah
  • 968
  • 12
  • 17
  • To avoid the issue where a popover will not open again after being closed, you can add this to reset the parameter: .on('hide.bs.popover', function () { window.activePopover = null; }) – Peter Jacoby Feb 18 '16 at 19:30
1

I used a function for my content, so I have (in coffeescript) :

provideContentForPopover = (element) ->
  $('.some-selector').not(element).popover 'hide'
  "some content to be returned"

$('.some-selector').popover
  content: -> provideContentForPopover @
jni
  • 391
  • 2
  • 3
1

I used a function for my content and it is work properly.

$(function () {                     
    $('[data-toggle="popover"]').click(function(){
        $(this).popover('toggle');
        $('[data-toggle="popover"]').not(this).popover('hide'); //all but this
    });
})
saddam
  • 301
  • 3
  • 11
0
$('.allThePopovers').click(function () {
    if ($(this).hasClass('popoverIsOpen')) {
        $(this).removeClass('popoverIsOpen');
    } else {
        $('.popoverIsOpen').popover('hide');
        $('.allThePopovers').removeClass('popoverIsOpen');
        $(this).addClass('popoverIsOpen');
});

Just replace click with hover or mousein to suit your needs.

friggle
  • 3,362
  • 3
  • 35
  • 47
  • Can the downvoter explain to me what's wrong with this solution? Constructive criticism is appreciated on this site. – friggle Oct 18 '13 at 15:44
0

This works fine if you want to have only one popover opened at once, opened and closed by a click (cursor-position is irrelevant):

$('[data-toggle="popover"]').popover({  html: true }).bind("click", function(){ 

  if(!$(this).parent().children("a").first().is(":hover"))
   $( '[data-toggle="popover"]').popover("hide"); 
  else
   $( '[data-toggle="popover"]').not($(this).parent().children("a").first()).popover("hide"); 

 return false;  
});

It is important that every popover has an individual parent, like

<ul> <li> <popover> </li> <li> <popover> </li> </ul>

HTML:

 <li>  
  <a id="quickmenu-i-305" data-toggle="popover" data-placement="bottom" data-title="Title" data-content='<h2>Plesk Login</h2>' href="Plesk Login">Ihr Kundenbereich</a> 
 </li>
Qullbrune
  • 1,925
  • 2
  • 20
  • 20
0

I was able to accomplish similar by just hiding whichever popover was not the one that was clicked on. I'm not sure, but it seems to work well for me. This is for the popover being displayed on click and stays alive. It is hidden when another popover is clicked on.

<script>
$(function () {
    $('[rel=popover]').popover({
    }).click(function (e) {
        $('[rel=popover]').not('#friend_' + $(this).attr('id')).popover('hide');
    });
});
</script>
kobaltz
  • 6,980
  • 1
  • 35
  • 52
0

more simple way to do the job:

$('[rel=popover]').popover({
    trigger: 'manual',
    placement: 'bottom'
}).click(function(e) {
    $('[rel=popover]').not('#' + $(this).attr('id')).popover('hide');
    var $popover = $(this);
    $popover.popover('toggle');
});

just make sure, that your popover has unique id ;] your popover will behave as it does by default, just one popover at once.

Lukas Liesis
  • 24,652
  • 10
  • 111
  • 109
0

i found that there is some troubles with dynamic popovers, so here is 2 solutions for static and dynamic popovers:

first solution is to use popover option triger:'focus' but this option will not work at some android devices

and the second one:

$('body').popover({
    html: true,
    //this is for static and dynamic popovers
    selector: '[data-toggle="popover"]',
    trigger: 'click',
    content: function () {
        //i am using predefined content for popovers. replace with your code or remove at all
        return $($(this).data('templateselector') + ' .content').html();
    },
    title: function () {
        return $($(this).data('templateselector') + ' .title').html();
    },
    container: 'body'
}).on('show.bs.popover', function (e) {
    // i've found that showed popovers has aria-describedby
    // and $('[data-toggle="popover"]).not(this) not working for dynamic popovers so i came with this:
    $('[data-toggle="popover"][aria-describedby]').popover('hide');
    var trigger = $(e.target);
    // this is for adding custom class for popover container
    // just remove it if you dont need
    trigger.data('bs.popover').tip().addClass($(trigger).data('class'));
});
taburetkin
  • 313
  • 3
  • 17
0

Use this method to hide all other popover when you hover over or click other element for popover to open

one two three four

$(document).ready(function(){    
    $('.btnPopover').mouseover(function(){    
    $(this).popover({
        html: true,
        trigger: 'manual'
    }).popover('show');
        $('.btnPopover').not(this).popover('hide');
    }); 
});

Make sure you add bootstrap.js and bootstrap.css to you page. Hope this helps.

Cheers!! Suraj Kumar

Lord Loh.
  • 2,437
  • 7
  • 39
  • 64
0

You must use an <a> anchor tag for compatibility.

My Fiddle: https://jsfiddle.net/oneflame/pnb8Ltj3/

Bootstrap Link -- http://getbootstrap.com/javascript/#dismiss-on-next-click

<div id="FragmentText1">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, est laborum.
</div>

$(document).ready(function(){               
  $('a.LexicalEntry').popover({ 
    html : true,    
    content: function() {
      return getLexicalDefinition($(this).text());
    }   ,   
    trigger: 'focus',
    placement: 'auto',
    html: true,
    container: 'body'
  });
});

// *** Injects HTML into raw text.
// *** Splits the content string using a whitespace regular expression. 
$('#FragmentText1').each(function() {

    // var words = $.trim( $(this).text() ).split(/\s+/g);

    var $this = $(this);
    $this.html(
        $this.text().trim().replace(/\b(\w+)\b/g,
            "<a tabindex='0' class='LexicalEntry'' role='button' title='Definition: $1'>$1</a>"
        ));

});
elika kohen
  • 147
  • 8