Search code examples
twitter-bootstrappopover

How to dismiss a Twitter Bootstrap popover by clicking outside?


Can we get popovers to be dismissable in the same way as modals, ie. make them close when user clicks somewhere outside of them?

Unfortunately I can't just use real modal instead of popover, because modal means position:fixed and that would be no popover anymore. :(


Solution

  • Update: A slightly more robust solution: http://jsfiddle.net/mattdlockyer/C5GBU/72/

    For buttons containing text only:

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

    For buttons containing icons use (this code has a bug in Bootstrap 3.3.6, see the fix below in this answer)

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

    For JS Generated Popovers Use '[data-original-title]' in place of '[data-toggle="popover"]'

    Caveat: The solution above allows multiple popovers to be open at once.

    One popover at a time please:

    Update: Bootstrap 3.0.x, see code or fiddle http://jsfiddle.net/mattdlockyer/C5GBU/2/

    $('body').on('click', function (e) {
        $('[data-toggle="popover"]').each(function () {
            //the 'is' for buttons that trigger popups
            //the 'has' for icons within a button that triggers a popup
            if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
                $(this).popover('hide');
            }
        });
    });
    

    This handles closing of popovers already open and not clicked on or their links have not been clicked.


    Update: Bootstrap 3.3.6, see fiddle

    Fixes issue where after closing, takes 2 clicks to re-open

    $(document).on('click', function (e) {
        $('[data-toggle="popover"],[data-original-title]').each(function () {
            //the 'is' for buttons that trigger popups
            //the 'has' for icons within a button that triggers a popup
            if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {                
                (($(this).popover('hide').data('bs.popover')||{}).inState||{}).click = false  // fix for BS 3.3.6
            }
    
        });
    });
    

    Update: Using the conditional of the previous improvement, this solution was achieved. Fix the problem of double click and ghost popover:

    $(document).on("shown.bs.popover",'[data-toggle="popover"]', function(){
        $(this).attr('someattr','1');
    });
    $(document).on("hidden.bs.popover",'[data-toggle="popover"]', function(){
        $(this).attr('someattr','0');
    });
    $(document).on('click', function (e) {
        $('[data-toggle="popover"],[data-original-title]').each(function () {
            //the 'is' for buttons that trigger popups
            //the 'has' for icons within a button that triggers a popup
            if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
                if($(this).attr('someattr')=="1"){
                    $(this).popover("toggle");
                }
            }
        });
    });