如何点击外面关闭Twitter Bootstrap popover?

问题描述 投票:272回答:38

我们能否以与模态相同的方式使弹出窗口被解雇,即。当用户点击它们之外的某个地方时,让它们关闭?

不幸的是我不能只使用真正的模态而不是弹出模式,因为模态意味着位置:固定并且不再是弹出模式。 :(

twitter-bootstrap popover
38个回答
439
投票

更新:一个稍微强大的解决方案:http://jsfiddle.net/mattdlockyer/C5GBU/72/

对于仅包含文本的按钮:

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

对于包含图标使用的按钮(此代码在Bootstrap 3.3.6中有一个错误,请参阅此答案中的下面的修复)

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

对于JS Generated Popovers使用'[data-original-title]'代替'[data-toggle="popover"]'

警告:上面的解决方案允许一次打开多个弹出窗口。

一次一个popover请:

更新:Bootstrap 3.0.x,请参阅代码或小提琴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');
        }
    });
});

这样可以处理已经打开但没有点击的弹出窗口的关闭或者没有点击它们的链接。


更新:Bootstrap 3.3.6,see fiddle

修复问题在关闭后,需要2次点击才能重新打开

$(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
        }

    });
});

3
投票

派对迟到了......但我想我会分享它。我喜欢popover但它的内置功能很少。我写了一个bootstrap扩展名.bubble(),这就是我想要的东西。四种解雇方式。单击“外部”,在链接上切换,单击X,然后单击“转义”。

它自动定位,因此它永远不会离开页面。

here

这不是一个无偿的自我宣传...我一生中已经多次抓住别人的代码,我想提供自己的努力。给它一个旋转,看看它是否适合你。


3
投票

修改了接受的解我所经历的是,在隐藏了一些弹出窗口之后,必须再点击两次才能再次出现。这就是我所做的,以确保不会在已经隐藏的弹出窗口上调用popover('hide')。

https://github.com/Itumac/bootstrap-bubble

3
投票

只需使用元素添加此属性即可

$('body').on('click', function (e) {
    $('[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) {
            var popoverElement = $(this).data('bs.popover').tip();
            var popoverWasVisible = popoverElement.is(':visible');

            if (popoverWasVisible) {
                $(this).popover('hide');
                $(this).click(); // double clicking required to reshow the popover if it was open, so perform one click now
            }
        }
    });
});

2
投票
data-trigger="focus"

2
投票

您还可以使用事件冒泡来从DOM中删除弹出窗口。它有点脏,但工作正常。

jQuery("#menu").click(function(){ return false; });
jQuery(document).one("click", function() { jQuery("#menu").fadeOut(); });

在你的html中,将.popover-close类添加到应该关闭popover的popover中的内容。


2
投票

如果使用选择器委托创建弹出框,似乎“隐藏”方法不起作用,而必须使用“destroy”。

我让它像那样工作:

$('body').on('click touchstart', '.popover-close', function(e) {
  return $(this).parents('.popover').remove();
});

$('body').popover({ selector: '[data-toggle="popover"]' }); $('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('destroy'); } }); });


2
投票

我们发现@mattdlockyer的解决方案存在问题(感谢解决方案!)。当像这样使用popover构造函数的selector属性时......

JSfiddle here

...建议的BS3解决方案不起作用。相反,它会在$(document.body').popover({selector: '[data-toggle=popover]'}); 本地创建第二个popover实例。这是我们的解决方案,以防止:

$(this)

如前所述,由于委托的监听器,$(document.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) { var bsPopover = $(this).data('bs.popover'); // Here's where the magic happens if (bsPopover) bsPopover.hide(); } }); }); 将创建第二个实例。提供的解决方案只隐藏已经实例化的popovers。

我希望我能救你们一些时间。


2
投票

Bootstrap $(this).popover('hide');

natively supports this

解雇下一次点击所需的特定标记

对于正确的跨浏览器和跨平台行为,您必须使用JS Bin Demo标记,而不是<a>标记,并且还必须包含<button>role="button"属性。


2
投票

这个解决方案在第二次显示弹出窗口时摆脱了讨厌的第二次点击

使用Bootstrap v3.3.7进行测试

tabindex

1
投票

我只是在显示新的弹出窗口之前删除其他活动的弹出窗口(bootstrap 3):

$('body').on('click', function (e) {
    $('.popover').each(function () {
        var popover = $(this).data('bs.popover');
        if (!popover.$element.is(e.target)) {
            popover.inState.click = false;
            popover.hide();                
        }
    });
});

54
投票
$('html').on('mouseup', function(e) {
    if(!$(e.target).closest('.popover').length) {
        $('.popover').each(function(){
            $(this.previousSibling).popover('hide');
        });
    }
});

如果您点击弹出窗口以外的任何地方,这将关闭所有弹出窗口

Bootstrap 4.1的更新

$("html").on("mouseup", function (e) {
    var l = $(e.target);
    if (l[0].className.indexOf("popover") == -1) {
        $(".popover").each(function () {
            $(this).popover("hide");
        });
    }
});

1
投票

用3.3.6测试,然后第二次点击就可以了

$(".my-popover").popover();

$(".my-popover").on('show.bs.popover',function () {
    $('.popover.in').remove();
});              

1
投票

我已经尝试了很多以前的答案,对我来说真的没什么用,但是这个解决方案做了:

$('[data-toggle="popover"]').popover() .click(function () { $(this).popover('toggle'); });; $(document).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'); } }); });

他们建议使用锚标记而不是按钮,并注意role =“button”+ data-trigger =“focus”+ tabindex =“0”属性。

例如:

https://getbootstrap.com/docs/3.3/javascript/#dismiss-on-next-click

1
投票

此解决方案工作正常:

<a tabindex="0" class="btn btn-lg btn-danger" role="button" data-toggle="popover" 
data-trigger="focus" title="Dismissible popover" data-content="amazing content">
Dismissible popover</a>

0
投票

但是:ぁzxswい

$("body")   .on('click'     ,'[data-toggle="popover"]', function(e) { 
    e.stopPropagation();
});

$("body")   .on('click'     ,'.popover' , function(e) { 
     e.stopPropagation();
});

$("body")   .on('click'  , function(e) {
        $('[data-toggle="popover"]').popover('hide');
});

}

这是我的解决方案。


0
投票

此方法可确保您可以通过单击页面上的任意位置来关闭弹出窗口。如果单击另一个可单击的实体,它将隐藏所有其他弹出窗口。动画:false是必需的,否则你的控制台会出现jquery .remove错误。

http://jsfiddle.net/nessajtr/yxpM5/1/

0
投票

好的,这是我第一次尝试在stackoverflow上回答一些事情,所以这里什么都没有:P

似乎不太清楚这个功能在最新的bootstrap上实际开箱即用(好吧,如果你愿意妥协用户可以点击的地方。我不确定你是否必须放'点击悬停'本身但在iPad上,点击作为切换。

最终结果是,在桌面上您可以悬停或单击(大多数用户将悬停)。在触摸设备上,触摸元素会将其抬起,再次触摸它会将其取下。当然,这与您原来的要求略有不同,但至少您的代码现在更干净了:)

$(“。my-popover”)。popover({trigger:'click hover'});


0
投票

我想出了这个:我的场景在同一页面上包含了更多的弹出窗口,隐藏它们只是让它们看不见,因此,点击弹出窗口后面的项目是不可能的。我们的想法是将特定的popover-link标记为“active”,然后您可以简单地“切换”活动的popover。这样做会完全关闭popover $('。popover-link')。popover({html:true,container:'body'})

var clickOver = clickOver || {};
clickOver.uniqueId = $.now();

clickOver.ClickOver = function (selector, options) {
    var self = this;

    //default values
    var isVisible, clickedAway = false;

    var callbackMethod = options.content;
var uniqueDiv = document.createElement("div");
var divId = uniqueDiv.id = ++clickOver.uniqueId;
uniqueDiv.innerHTML = options.loadingContent();

options.trigger = 'manual';
options.animation = false;
options.content = uniqueDiv;

self.onClose = function () {
    $("#" + divId).html(options.loadingContent());
    $(selector).popover('hide')
    isVisible = clickedAway = false;
};
self.onCallback = function (result) {
    $("#" + divId).html(result);
};

$(selector).popover(options);

//events
$(selector).bind("click", function (e) {
    $(selector).filter(function (f) {
        return $(selector)[f] != e.target;
    }).popover('hide');

    $(selector).popover("show");
    callbackMethod(self.onCallback);

    isVisible = !(clickedAway = false);
});

$(document).bind("click", function (e) {
    if (isVisible && clickedAway && $(e.target).parents(".popover").length == 0) {
        self.onClose();
        isVisible = clickedAway = false;
    } else clickedAway = true;
});

0
投票

以Matt Lockyer的代码为例,我做了一个简单的重置,因此dom不会被hide上的元素覆盖。

马特的代码:$('.clickable').popover({ trigger: 'manual', animation: false }).click (evt) -> $('.clickable').popover('hide') evt.stopPropagation() $(this).popover('show') $('html').on 'click', (evt) -> $('.clickable').popover('hide')

小提琴:$('.popover-link').popover().on 'shown.bs.popover', -> $(this).addClass('toggled') $('.popover-link').popover().on 'hidden.bs.popover', -> $(this).removeClass('toggled') $("body").on "click", (e) -> $openedPopoverLink = $(".popover-link.toggled") if $openedPopoverLink.has(e.target).length == 0 $openedPopoverLink.popover "toggle" $openedPopoverLink.removeClass "toggled"

http://mattlockyer.com/2013/04/08/close-a-twitter-bootstrap-popover-when-clicking-outside/

0
投票

试试这个,这将通过点击外部隐藏。

http://jsfiddle.net/mrsmith/Wd2qS/

0
投票

我遇到了mattdlockyer解决方案的问题,因为我使用这样的代码动态设置popover链接:

    $('body').on('click', function (e) {
    //hide popover from dom to prevent covering elements
    $('.popover').css('display', 'none');
    //bring popover back if trigger element is clicked
    $('[data-toggle="popover"]').each(function () {
        if ($(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
            $('.popover').css('display', 'block');
        }
    });
    //hide popover with .popover method
    $('[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');
        }
    });
});

所以我不得不像这样修改它。它为我解决了很多问题:

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

请记住,destroy会删除元素,因此选择器部分对初始化弹出窗口很重要。


36
投票

最简单,大多数故障安全版本,适用于任何引导版本。

但是:ぁzxswい

演示2:在弹出内容http://jsfiddle.net/guya/24mmM/中单击时不要忽略

演示3:多个弹出窗口:http://jsfiddle.net/guya/fjZja/


简单地调用此行将解除所有弹出窗口:

http://jsfiddle.net/guya/6YCjW/

使用此代码单击外部时,关闭所有弹出窗口:

$('[data-original-title]').popover('hide');

上面的代码段会在主体上附加一个点击事件。当用户单击一个弹出框时,它将表现正常。当用户点击不是popover的东西时,它将关闭所有弹出窗口。

它也适用于使用Javascript启动的弹出窗口,而不是其他一些不起作用的示例。 (见演示)

如果您不想在单击popover内容时忽略,请使用此代码(请参阅第2个演示的链接):

$('html').on('click', function(e) {
  if (typeof $(e.target).data('original-title') == 'undefined') {
    $('[data-original-title]').popover('hide');
  }
});

0
投票

来自@guya的答案有效,除非你在popover中有类似日期选择器或时间戳的东西。要解决这个问题,这就是我所做的。

$('body').popover({
        selector : '[rel="popover"]'
});

19
投票

使用bootstrap 2.3.2,您可以将触发器设置为“焦点”,它只是起作用:

$('html').on('click', function(e) {
  if (typeof $(e.target).data('original-title') == 'undefined' && !$(e.target).parents().is('.popover.in')) {
    $('[data-original-title]').popover('hide');
  }
});

18
投票

这基本上不是很复杂,但有一些检查可以避免故障。

$('#el').popover({trigger:'focus'});

Demo (jsfiddle)

15
投票

所谓的高投票解决方案都没有正确地为我工作。每次打开和关闭(通过单击其他元素)弹出窗口时,每个都会导致错误,它不再打开,直到您在触发链接而不是一次点击两次。

所以我稍微修改了一下:

var $poped = $('someselector');

// Trigger for the popover
$poped.each(function() {
    var $this = $(this);
    $this.on('hover',function() {
            var popover = $this.data('popover');
            var shown = popover && popover.tip().is(':visible');
            if(shown) return;        // Avoids flashing
            $this.popover('show');
    });
});

// Trigger for the hiding
 $('html').on('click.popover.data-api',function() {
    $poped.popover('hide');
});

11
投票

我做了一个jsfiddle来告诉你如何做到这一点:

$(document).on('click', function (e) { var $popover, $target = $(e.target); //do nothing if there was a click on popover content if ($target.hasClass('popover') || $target.closest('.popover').length) { return; } $('[data-toggle="popover"]').each(function () { $popover = $(this); if (!$popover.is(e.target) && $popover.has(e.target).length === 0 && $('.popover').has(e.target).length === 0) { $popover.popover('hide'); } else { //fixes issue described above $popover.popover('toggle'); } }); })

想法是在单击按钮时显示弹出窗口,并在单击按钮外部时隐藏弹出窗口。

HTML

http://jsfiddle.net/3yHTH/

JS

<a id="button" href="#" class="btn btn-danger">Click for popover</a>

4
投票

根据$('#button').popover({ trigger: 'manual', position: 'bottom', title: 'Example', content: 'Popover example for SO' }).click(function(evt) { evt.stopPropagation(); $(this).popover('show'); }); $('html').click(function() { $('#button').popover('hide'); });

http://getbootstrap.com/javascript/#popovers

使用焦点触发器可以在用户下次单击时关闭弹出窗口。

<button type="button" class="popover-dismiss" data-toggle="popover" title="Dismissible popover" data-content="Popover Content">Dismissible popover</button>

3
投票

这是在$('.popover-dismiss').popover({ trigger: 'focus' }) 之前被问到的。我给出的答案仍然适用:

我有类似的需求,发现这个here。他还有一些用法例子great little extension of the Twitter Bootstrap Popover by Lee Carmichael, called BootstrapX - clickover。基本上它会将popover更改为一个交互式组件,当您单击页面上的其他位置或弹出窗口中的关闭按钮时,该组件将关闭。这也将允许一次打开多个弹出窗口和一堆其他不错的功能。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.