ryzh
ryzh

Reputation: 263

Executing functions BEFORE Bootstrap popover is displayed?

I've recently started using Twitter's new Bootstrap 2.0.1 and its Javascript popovers.

I want to write a script so that no more than one popover can be displayed at one time. In other words, when a new popover is generated for whatever reason (e.g. the client clicks or hovers over a new element with a popover), all of the PREVIOUSLY displayed popovers are hidden first.

Here's the function that initially sets up all of the popovers for my webpage:

$(function (){
    $("[rel=popover]").popover({placement:'left', trigger:'click', html:true});
});

What I need, I think, is to write a function that hides all popovers. I would call that function BEFORE displaying every popover, to ensure that only one popover is displayed at a time. The function might look like this, I imagine:

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

But my problem is figuring out WHERE (or HOW) to call this hidePopovers function. I want to call it when a popover is triggered, but before the popover is displayed. Help?

Oh, and just to clear up any confusion, the new Bootstrap now has a 'click' trigger that allows you to display popovers upon clicking. More details about it can be found here.

Thank you so much!

Upvotes: 3

Views: 6212

Answers (2)

merv
merv

Reputation: 76810

Considering what you have presented as the problem to solve, I think that it would be much more efficient to simply store a reference to the last popover open, rather than execute the hide() method on every single popover element you might select on the page. As far as I understand it, you only want a single popover to be open in the first place, so there should only ever be at most a single one to hide.

The following would do the trick:

var $visiblePopover;

$('body').on('click', '[rel="popover"]', function() {
  var $this = $(this);

  // check if the one clicked is now shown
  if ($this.data('popover').tip().hasClass('in')) {

    // if another was showing, hide it
    $visiblePopover && $visiblePopover.popover('hide');

    // then store reference to current popover
    $visiblePopover = $this;

  } else { // if it was hidden, then nothing must be showing
    $visiblePopover = '';
  }
});​

JSFiddle

Technically, you could potentially change the selector where the delegate handler is attached (in the example code 'body' is used) to a more specific element of the page, allowing you to attach the only-one-visible-at-a-time behavior to only a subset of the popovers on the page.

For instance, if you had a specific form where the popovers would appear too close together, but other popups on the page wouldn't collide/overlap, you could select just the form (e.g., '#some_form_id'), and only the popups in the form would have the behavior.

JSFiddle

Note: In this latter example, I also optimized the code a bit by changing the stored reference to only use the actual Popover object, rather than the jQuery-ized DOM element it is attached to.

Upvotes: 9

msc
msc

Reputation: 3800

Haven't tested this but something like this might work:

Set the trigger to manual. Listen for click events and on click, call hidePopovers(), and then show the clicked popover.

$(function (){
    function hidePopovers(){
        $(function (){
            $("[rel=popover]").popover('hide');
        });
    }
    $("[rel=popover]").popover({placement:'left', trigger:'manual', html:true});
    $("[rel=popover]").click(function() { hidePopovers(); $(this).popover('show');});
});

Upvotes: 1

Related Questions