如何通过点击外部解雇Twitter Bootstrappopup窗口?
我们能不能像模式一样使pop-up成为可以忽略的。 当用户点击他们之外的地方时,让他们closures?
不幸的是,我不能仅仅使用真正的模态而不是popup式,因为模式意味着位置:固定的,那将不再是popup式的。 🙁
更新:一个更健壮的解决scheme: http : //jsfiddle.net/mattdlockyer/C5GBU/72/
对于仅包含文本的button:
$('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'); } });
对于包含图标的button使用(此代码在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生成的Popovers使用'[data-original-title]'
代替'[data-toggle="popover"]'
警告:上面的解决scheme允许多个popup一次打开。
一次一个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'); } }); });
这处理closures已经打开并没有点击的链接,或者链接没有被点击。
更新: Bootstrap 3.3.6, 看小提琴
修复了closures后的问题,需要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 } }); });
$('html').on('mouseup', function(e) { if(!$(e.target).closest('.popover').length) { $('.popover').each(function(){ $(this.previousSibling).popover('hide'); }); } });
如果您点击popup窗口以外的任何位置,则会closures所有popup窗口
最简单,最安全的版本 ,适用于任何引导版本。
演示: http : //jsfiddle.net/guya/24mmM/
演示2:在点击popup窗口内容时不放弃http://jsfiddle.net/guya/fjZja/
演示3:多个popovers: http : //jsfiddle.net/guya/6YCjW/
只需调用这一行就可以忽略所有的stream行:
$('[data-original-title]').popover('hide');
使用此代码在外部点击时closures所有popup窗口:
$('html').on('click', function(e) { if (typeof $(e.target).data('original-title') == 'undefined') { $('[data-original-title]').popover('hide'); } });
上面的代码片段在主体上附加了一个点击事件。 当用户点击一个popover时,它将像正常一样运行。 当用户点击某个不是popup窗口的东西时,它将closures所有popup窗口。
它也将使用Javascript启动的popovers,而不是其他一些不起作用的例子。 (看演示)
如果您不想在点击popup窗口内容时解雇,请使用此代码(请参阅第二个演示的链接):
$('html').on('click', function(e) { if (typeof $(e.target).data('original-title') == 'undefined' && !$(e.target).parents().is('.popover.in')) { $('[data-original-title]').popover('hide'); } });
这基本上不是很复杂,但有一些检查,以避免小故障。
演示(jsfiddle)
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'); });
使用bootstrap 2.3.2,你可以设置触发器为“焦点”,它只是工作:
$('#el').popover({trigger:'focus'});
没有人认为我的答案是正确的。 当打开和closures(通过点击其他元素)第一次popup时,每个导致一个错误,它不会再次打开,直到你在触发链接而不是一个点击。
所以我修改了一下:
$(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'); } }); })
我做了一个jsfiddle,告诉你如何做到这一点:
这个想法是当你点击button时显示popup窗口,当你点击button外时隐藏popup窗口。
HTML
<a id="button" href="#" class="btn btn-danger">Click for popover</a>
JS
$('#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'); });
这已经在这里被问过。 我给出的同样的答案仍然适用:
我也有类似的需求,并且发现了Lee Carmichael推出的Twitter Bootstrap Popover的一个很好的扩展,名为BootstrapX – clickover 。 他在这里也有一些用法示例。 基本上,它会将popup窗口变成一个交互式的组件,当你点击页面上的其他地方,或者popup窗口中的closuresbutton时,它将closures。 这也将允许一次打开多个popup窗口和一堆其他不错的function。
这是晚了…但我想我会分享它。 我喜欢popover,但内置的function很less。 我写了一个bootstrap扩展.bubble(),这就是我想popover的一切。 四种解雇方式。 点击外面的链接,点击X,然后点击转义。
它自动定位,所以它永远不会离开页面。
https://github.com/Itumac/bootstrap-bubble
这不是一个无偿的自我推销…我一辈子都抓了别人的代码,我想提供自己的努力。 给它一个旋转,看看它是否适合你。
jQuery("#menu").click(function(){ return false; }); jQuery(document).one("click", function() { jQuery("#menu").fadeOut(); });
您还可以使用事件冒泡从DOM中删除popup窗口。 这有点脏,但工作正常。
$('body').on('click touchstart', '.popover-close', function(e) { return $(this).parents('.popover').remove(); });
在你的html中,将.popover-close类添加到应该closurespopup窗口的popup窗口中。
根据http://getbootstrap.com/javascript/#popovers ,
<button type="button" class="popover-dismiss" data-toggle="popover" title="Dismissible popover" data-content="Popover Content">Dismissible popover</button>
使用焦点触发器closures用户下一次点击的popup。
$('.popover-dismiss').popover({ trigger: 'focus' })
看起来'隐藏'方法不起作用,如果你使用select器委托创buildpopover,而不是'destroy'必须被使用。
我做了这样的工作:
$('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'); } }); });
JSfiddle在这里
我们发现我们的解决scheme来自@mattdlockyer(感谢解决scheme!)。 当使用popup式构造函数的select器属性像这样…
$(document.body').popover({selector: '[data-toggle=popover]'});
…为BS3提出的解决scheme将无法正常工作。 相反,它会在$(this)
创build第二个popover实例。 这是我们的解决scheme,以防止:
$(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(); } }); });
如上所述$(this).popover('hide');
将由于委派的监听器而创build第二个实例。 提供的解决scheme只隐藏已经实例化的popovers。
我希望我能救一些时间。
修改后接受的解决 我所经历的是,在隐藏了一些popup之后,必须再次点击两次以再次出现。 这是我做了什么来确保popover('hide')没有在已经隐藏的popovers上被调用。
$('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 } } }); });
Bootstrap 本地支持 :
JS斌演示
特定标记需要解雇的下一次点击
对于正确的跨浏览器和跨平台行为,您必须使用
<a>
标记, 而不是<button>
标记,还必须包含role="button"
和tabindex
属性。
这个解决scheme在第二次显示popover时摆脱了讨厌的第二次点击
使用Bootstrap v3.3.7进行testing
$('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(); } }); });
只需将该属性添加到该元素即可
data-trigger="focus"
显示新的popup窗口之前,我只删除其他活动的弹窗(引导程序3):
$(".my-popover").popover(); $(".my-popover").on('show.bs.popover',function () { $('.popover.in').remove(); });
演示: http : //jsfiddle.net/nessajtr/yxpM5/1/
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; });
}
这是我的解决scheme。
这种方法确保您可以通过单击页面上的任何位置来closurespopup窗口。 如果你点击另一个可点击的实体,它隐藏所有其他的popup。 animation:假是必须的,否则你会在你的控制台中得到一个jQuery的.remove错误。
$('.clickable').popover({ trigger: 'manual', animation: false }).click (evt) -> $('.clickable').popover('hide') evt.stopPropagation() $(this).popover('show') $('html').on 'click', (evt) -> $('.clickable').popover('hide')
好吧,这是我第一次尝试在stackoverflow上实际回答的东西,所以这里什么也不做:P
看起来,这个function实际上在最新的引导程序中是可以实现的(不过,如果你愿意在用户可以点击的地方妥协的话,这个function并不是很清楚),我不确定你是否必须把点击hover“,但在iPad上,单击工具作为切换。
最终的结果是,在桌面上,你可以hover或点击(大多数用户将hover)。 在触摸设备上,触摸该元件将会提起,然后再次触摸它会将其取下。 当然,这是从你原来的要求轻微的妥协,但至less你的代码现在是干净的:)
$(“。my-popover”)。popover({trigger:'click hover'});
我想出了这个:我的场景在同一页面上包含了更多的popup窗口,隐藏它们只是使它们不可见,正因为如此,点击popover后面的项目是不可能的。 这个想法是把特定的popover-link标记为“active”,然后你可以简单地“切换”活动的popover。 这样做会完全closurespopover $('。popover-link')。popover({html:true,container:'body'})
$('.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"
以Matt Lockyer的代码,我做了一个简单的重置,所以dom没有被隐藏的元素覆盖。
马特的代码: http : //mattlockyer.com/2013/04/08/close-a-twitter-bootstrap-popover-when-clicking-outside/
小提琴: http : //jsfiddle.net/mrsmith/Wd2qS/
$('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'); } }); });
我有mattdlockyer的解决scheme的问题,因为我使用这样的代码dynamic地设置popup链接:
$('body').popover({ selector : '[rel="popover"]' });
所以我不得不像这样修改它。 它为我解决了很多问题:
$('html').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'); } }); });
请记住,摧毁摆脱元素,所以select器部分是非常重要的初始化popup。
@guya的答案是有效的,除非你在popover中有一个类似于datepicker或timepicker的东西。 为了解决这个问题,这就是我所做的。
if (typeof $(e.target).data('original-title') === 'undefined' && !$(e.target).parents().is('.popover.in')) { var x = $(this).parents().context; if(!$(x).hasClass("datepicker") && !$(x).hasClass("ui-timepicker-wrapper")){ $('[data-original-title]').popover('hide'); } }
$('html').on('click.popover', function (e) { var allpopins = $('.popover.in'); if (allpopins.has(e.target).length > 0 && !$('.btn', allpopins).is(e.target)) return; // recognise pop-up var id = $(e.target).attr('aria-describedby'); var popin = $("#" + id); //on any button click in entire pop-up hide this pop-ups $(popin).on(".btn", function () { popin.remove(); }); // on any place out of entire popup hide all pop-ups $('.popover.in').not(popin).remove(); });
这是我最好的性能解决scheme。 干杯。
答案很好,只要添加一个angular度指令,以防你使用像我这样的angular度:
app.directive('popover', ['$document', function($document) { return { restrict: 'EA', link: function(scope, elem, attrs) { $(document).ready(function() { $('[data-toggle="popover"]').popover(); }); elem.bind('click', function(e) { $('#notification').popover('toggle'); }) $('body').on('click', function (e) { //the 'is' for buttons that trigger popups //the 'has' for icons within a button that triggers a popup if (!elem.is(e.target) && elem.has(e.target).length === 0 && $('.popover').has(e.target).length === 0) { elem.popover('hide'); } }); } }; }]);
html代码:
<a popover tabindex="0" role="button" id="notification" data-toggle="popover" data-trigger="manual" data-container="body" data-placement="bottom" data-content="This is a popover"> Popover button </a>
它应该像使用data-trigger='click focus'
一样简单,因为根据bootstrap:
popup如何触发 – 单击| hover| 重点| 手册。 你可能传递多个触发器; 用空格分开。 手动不能与任何其他触发器组合。
但是,一起使用点击和聚焦不适用于我不知道的原因,而不得不手动切换。
用3.3.6进行testing,第二次点击就OK了
$('[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'); } }); });