Dev
Dev

Reputation: 467

Hide Bootstrap Popover when clicked outside of the popover

I have the following setup for a bootstrap popover. The popover appears when the page is loaded and if I click on the popover, it disappears. What I would really like though is for it to disappear if I click outside the popover or even better on the next click. Any ideas on how to make this work?

$('div').on('hide.bs.popover', function (e) {
        e.preventDefault();
    });

    $(document).ready(function() {
        $("div").popover("show");
    });



    $('body').on('click', '.popover', function () {
        $(this).hide();
    });
<div class="dropdown pull-right" data-toggle="popover" data-placement="left" data-content="Main menu" style="right: -2px; top: 3px;">

<a href="#" class="glyphicon glyphicon-th dropdown-toggle" data-toggle="dropdown" style="color: #317EAC; text-decoration: none !important; font-size: 22px;"></a>
</div>

Upvotes: 1

Views: 6802

Answers (4)

Big Zak
Big Zak

Reputation: 1100

This is for non jquery version (bootstrap 5+), the trick here is to take advantage of html tabindex attribute so that we can listen to focusout event

let pCustomClass = "my_popover"; // this is very important as we will use it to track our parent popover class

let trigger = document.querySelector(".popover_trigger")

let _popover = new bootstrap.Popover(trigger, {
    fallbackPlacements: ["left", "top"],
    trigger:'click',
    customClass: pCustomClass, // dont forget the custom class  
})


// after the popover is shown, lets add a tabindex and then focus the parent element 
trigger.addEventListener('shown.bs.popover',  () => {
    let el = document.querySelector("."+pCustomClass)
    
    if(!el) return;

    // set the tabindex to -1, -1 is required as we do not need 
    // keyboard tab feature, we want only the focus 
    el.setAttribute("tabindex", -1)
  
    el.addEventListener("focusout", async (e) => {
        if(!el.contains( e.relatedTarget)){
            // hide the popover when focused out
            _popover.hide()
        }
    })

    // finally, focus the parent .popover element
    el.focus() 
})

//once closed, remove the focus event 
trigger.addEventListener('hide.bs.popover',  () => {
    let el = document.querySelector("."+pCustomClass)
    if(!el) return;
    el.removeEventListener("focusout", ()=>{})
})

Upvotes: 2

Dev
Dev

Reputation: 467

Found the solution for this:

$(document).ready(function() {
    $("div").popover("show");
});

$('body').on('click', function (e) {
    if ($(e.target).data('toggle') !== 'popover'
        && $(e.target).parents('.popover.in').length === 0) {
        $('[data-toggle="popover"]').popover('hide');
    }
});

Upvotes: 2

Rohit Verma
Rohit Verma

Reputation: 299

As per documentation: Use the focus trigger to dismiss popovers on the next click that the user makes. So use data-trigger="focus"

Specific markup required for dismiss-on-next-click For proper cross-browser and cross-platform behavior, you must use the tag, not the tag, and you also must include the role="button" and tabindex attributes.

<a 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>

Upvotes: 2

Abdo-Host
Abdo-Host

Reputation: 4173

$('body').on('click', function (e) {
    $('[data-toggle=popover]').each(function () {
        // hide any open popovers when the anywhere else in the body is clicked
        if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
            $(this).popover('hide');
        }
    });
});

Upvotes: 1

Related Questions