Как закрыть вкладку "Bootstrap Twitter" щелчком из любого места на странице?
В настоящее время я использую popovers с Twitter Bootstrap, инициированный следующим образом:
$('.popup-marker').popover({
html: true,
trigger: 'manual'
}).click(function(e) {
$(this).popover('toggle');
e.preventDefault();
});
Как вы можете видеть, они запускаются вручную, и нажатие на .popup-marker (который является div с фоновым изображением) переключает popover. Это отлично работает, но я также хотел бы закрыть popover щелчком в любом месте на странице (но не на самом popover!).
Я пробовал несколько разных вещей, в том числе следующее, но без результатов для него:
$('body').click(function(e) {
$('.popup-marker').popover('hide');
});
Как я могу закрыть popover щелчком в любом месте страницы, но не щелкнуть по самому popover?
Ответы
Ответ 1
Предполагая, что в любой момент можно видеть только один popover, вы можете использовать набор флагов для отметки, когда видимое изображение видимо, и только затем скрывать их.
Если вы установите прослушиватель событий в теле документа, он будет срабатывать, когда вы нажмете элемент, отмеченный "всплывающим маркером". Поэтому вам придется вызвать stopPropagation()
объекта события. И примените тот же трюк, щелкнув по самому popover.
Ниже приведен рабочий код JavaScript, который делает это. Он использует jQuery >= 1.7
jQuery(function() {
var isVisible = false;
var hideAllPopovers = function() {
$('.popup-marker').each(function() {
$(this).popover('hide');
});
};
$('.popup-marker').popover({
html: true,
trigger: 'manual'
}).on('click', function(e) {
// if any other popovers are visible, hide them
if(isVisible) {
hideAllPopovers();
}
$(this).popover('show');
// handle clicking on the popover itself
$('.popover').off('click').on('click', function(e) {
e.stopPropagation(); // prevent event for bubbling up => will not get caught with document.onclick
});
isVisible = true;
e.stopPropagation();
});
$(document).on('click', function(e) {
hideAllPopovers();
isVisible = false;
});
});
http://jsfiddle.net/AFffL/539/
Единственное предостережение в том, что вы не сможете одновременно открыть 2 popovers. Но я думаю, что это будет запутать для пользователя, так или иначе: -)
Ответ 2
Это еще проще:
$('html').click(function(e) {
$('.popup-marker').popover('hide');
});
$('.popup-marker').popover({
html: true,
trigger: 'manual'
}).click(function(e) {
$(this).popover('toggle');
e.stopPropagation();
});
Ответ 3
У меня была аналогичная потребность, и я нашел это большое небольшое расширение Twitter Bootstrap Popover Ли Кармайкл, названное BootstrapX - clickover. У него также есть примеры использования здесь. В основном это изменит popover на интерактивный компонент, который закроется, когда вы нажмете в другом месте на странице или на кнопке закрытия внутри popover. Это также позволит открывать сразу несколько popovers и множество других приятных функций.
Плагин можно найти здесь.
Пример использования
<button rel="clickover" data-content="Show something here.
<button data-dismiss='clickover'
>Close Clickover</button>"
>Show clickover</button>
javascript:
// load click overs using 'rel' attribute
$('[rel="clickover"]').clickover();
Ответ 4
Принятое решение дало мне некоторые проблемы (щелчок по элементу ".popup-marker" открытого popover заставил popovers не работать после этого). Я придумал это другое решение, которое отлично работает для меня, и это довольно просто (я использую Bootstrap 2.3.1):
$('.popup-marker').popover({
html: true,
trigger: 'manual'
}).click(function(e) {
$('.popup-marker').not(this).popover('hide');
$(this).popover('toggle');
});
$(document).click(function(e) {
if (!$(e.target).is('.popup-marker, .popover-title, .popover-content')) {
$('.popup-marker').popover('hide');
}
});
UPDATE: этот код также работает с Bootstrap 3!
Ответ 5
читать "Отклонить при следующем нажатии"
здесь http://getbootstrap.com/javascript/#popovers
Вы можете использовать триггер фокуса, чтобы отклонять popovers при следующем щелчке, но вам нужно использовать тег <a>
, а не тег <button>
, и вы также должны включить атрибут tabindex
...
Пример:
<a href="#" tabindex="0" class="btn btn-lg btn-danger"
data-toggle="popover" data-trigger="focus" title="Dismissible popover"
data-content="And here some amazing content. It very engaging. Right?">
Dismissible popover
</a>
Ответ 6
Все существующие ответы довольно слабы, так как они полагаются на захват всех событий документа, а затем поиск активных popovers или изменение вызова на .popover()
.
Гораздо лучший подход - прослушивать события show.bs.popover
на теле документа, а затем реагировать соответствующим образом. Ниже приведен код, который будет закрывать popovers при нажатии на документ или нажатие esc, только привязка прослушивателей событий при появлении popovers:
function closePopoversOnDocumentEvents() {
var visiblePopovers = [];
var $body = $("body");
function hideVisiblePopovers() {
$.each(visiblePopovers, function() {
$(this).popover("hide");
});
}
function onBodyClick(event) {
if (event.isDefaultPrevented())
return;
var $target = $(event.target);
if ($target.data("bs.popover"))
return;
if ($target.parents(".popover").length)
return;
hideVisiblePopovers();
}
function onBodyKeyup(event) {
if (event.isDefaultPrevented())
return;
if (event.keyCode != 27) // esc
return;
hideVisiblePopovers();
event.preventDefault();
}
function onPopoverShow(event) {
if (!visiblePopovers.length) {
$body.on("click", onBodyClick);
$body.on("keyup", onBodyKeyup);
}
visiblePopovers.push(event.target);
}
function onPopoverHide(event) {
var target = event.target;
var index = visiblePopovers.indexOf(target);
if (index > -1) {
visiblePopovers.splice(index, 1);
}
if (visiblePopovers.length == 0) {
$body.off("click", onBodyClick);
$body.off("keyup", onBodyKeyup);
}
}
$body.on("show.bs.popover", onPopoverShow);
$body.on("hide.bs.popover", onPopoverHide);
}
Ответ 7
https://github.com/lecar-red/bootstrapx-clickover
Это расширение twitter bootstrap popover и решит проблему очень просто.
Ответ 8
По какой-то причине ни одно из других решений для меня не работало. Однако после многого устранения неполадок я наконец пришел к этому методу, который отлично работает (по крайней мере для меня).
$('html').click(function(e) {
if( !$(e.target).parents().hasClass('popover') ) {
$('#popover_parent').popover('destroy');
}
});
В моем случае я добавлял popover к таблице и полностью позиционировал его выше/ниже td
, который был нажат. Выбор таблицы был обработан с помощью jQuery-UI Selectable, поэтому я не уверен, что это мешало. Однако всякий раз, когда я щелкнул внутри popover, мой обработчик кликов, который нацелился на $('.popover')
, никогда не работал, и обработка событий всегда была делегирована обработчику кликов $(html)
. Я новичок в JS, поэтому, возможно, я просто что-то пропустил?
В любом случае я надеюсь, что это поможет кому-то!
Ответ 9
Я отдаю все свои popovers, привязывая класс activate_popover
. Я активирую их сразу при загрузке
$('body').popover({selector: '.activate-popover', html : true, container: 'body'})
чтобы получить функциональность щелчка, которую я использую (в кофе script):
$(document).on('click', (e) ->
clickedOnActivate = ($(e.target).parents().hasClass("activate-popover") || $(e.target).hasClass("activate-popover"))
clickedAway = !($(e.target).parents().hasClass("popover") || $(e.target).hasClass("popover"))
if clickedAway && !clickedOnActivate
$(".popover.in").prev().popover('hide')
if clickedOnActivate
$(".popover.in").prev().each () ->
if !$(this).is($(e.target).closest('.activate-popover'))
$(this).popover('hide')
)
Что отлично работает с загрузкой 2.3.1
Ответ 10
Несмотря на то, что здесь есть много решений, я тоже хотел бы предложить мой, я не знаю, есть ли там какое-то решение, которое решает все это, но я попробовал 3 из них, и у них были проблемы, например, щелчок по popover, который он сам заставляет скрывать, другие, если бы у меня были другие кнопки popover, которые щелкнули оба/несколько popovers, все равно появятся (например, в выбранном решении). Как всегда, Это фиксировало все это
var curr_popover_btn = null;
// Hide popovers function
function hide_popovers(e)
{
var container = $(".popover.in");
if (!container.is(e.target) // if the target of the click isn't the container...
&& container.has(e.target).length === 0) // ... nor a descendant of the container
{
if( curr_popover_btn != null )
{
$(curr_popover_btn).popover('hide');
curr_popover_btn = null;
}
container.hide();
}
}
// Hide popovers when out of focus
$('html').click(function(e) {
hide_popovers(e);
});
$('.popover-marker').popover({
trigger: 'manual'
}).click(function(e) {
hide_popovers(e);
var $popover_btns = $('.popover-marker');
curr_popover_btn = this;
var $other_popover_btns = jQuery.grep($($popover_btns), function(popover_btn){
return ( popover_btn !== curr_popover_btn );
});
$($other_popover_btns).popover('hide');
$(this).popover('toggle');
e.stopPropagation();
});
Ответ 11
Вот решение, которое работало очень хорошо для меня, если оно может помочь:
/**
* Add the equals method to the jquery objects
*/
$.fn.equals = function(compareTo) {
if (!compareTo || this.length !== compareTo.length) {
return false;
}
for (var i = 0; i < this.length; ++i) {
if (this[i] !== compareTo[i]) {
return false;
}
}
return true;
};
/**
* Activate popover message for all concerned fields
*/
var popoverOpened = null;
$(function() {
$('span.btn').popover();
$('span.btn').unbind("click");
$('span.btn').bind("click", function(e) {
e.stopPropagation();
if($(this).equals(popoverOpened)) return;
if(popoverOpened !== null) {
popoverOpened.popover("hide");
}
$(this).popover('show');
popoverOpened = $(this);
e.preventDefault();
});
$(document).click(function(e) {
if(popoverOpened !== null) {
popoverOpened.popover("hide");
popoverOpened = null;
}
});
});
Ответ 12
Здесь мое решение, для чего оно стоит:
// Listen for clicks or touches on the page
$("html").on("click.popover.data-api touchend.popover.data-api", function(e) {
// Loop through each popover on the page
$("[data-toggle=popover]").each(function() {
// Hide this popover if it visible and if the user clicked outside of it
if ($(this).next('div.popover:visible').length && $(".popover").has(e.target).length === 0) {
$(this).popover("hide");
}
});
});
Ответ 13
У меня возникла проблема, чтобы заставить его работать над загрузкой. 2.3.2.
Но я так увлек его:
$(function () {
$(document).mouseup(function (e) {
if(($('.popover').length > 0) && !$(e.target).hasClass('popInfo')) {
$('.popover').each(function(){
$(this).prev('.popInfo').popover('hide');
});
}
});
$('.popInfo').popover({
trigger: 'click',
html: true
});
});
Ответ 14
слегка изменил решение @David Wolever:
function closePopoversOnDocumentEvents() {
var visiblePopovers = [];
var $body = $("body");
function hideVisiblePopovers() {
/* this was giving problems and had a bit of overhead
$.each(visiblePopovers, function() {
$(this).popover("hide");
});
*/
while (visiblePopovers.length !== 0) {
$(visiblePopovers.pop()).popover("hide");
}
}
function onBodyClick(event) {
if (event.isDefaultPrevented())
return;
var $target = $(event.target);
if ($target.data("bs.popover"))
return;
if ($target.parents(".popover").length)
return;
hideVisiblePopovers();
}
function onBodyKeyup(event) {
if (event.isDefaultPrevented())
return;
if (event.keyCode != 27) // esc
return;
hideVisiblePopovers();
event.preventDefault();
}
function onPopoverShow(event) {
if (!visiblePopovers.length) {
$body.on("click", onBodyClick);
$body.on("keyup", onBodyKeyup);
}
visiblePopovers.push(event.target);
}
function onPopoverHide(event) {
var target = event.target;
var index = visiblePopovers.indexOf(target);
if (index > -1) {
visiblePopovers.splice(index, 1);
}
if (visiblePopovers.length == 0) {
$body.off("click", onBodyClick);
$body.off("keyup", onBodyKeyup);
}
}
$body.on("show.bs.popover", onPopoverShow);
$body.on("hide.bs.popover", onPopoverHide);
}
Ответ 15
Этот вопрос также задавался здесь, и мой ответ предоставляет не только способ понять методы обхода JQuery DOM, но и 2 варианта обработки закрытия popovers, щелкнув внешний вид.
Откройте несколько popovers сразу или один popup за раз.
Плюс эти небольшие фрагменты кода могут обрабатывать закрытие кнопок, содержащих значки!
fooobar.com/questions/27741/...
Ответ 16
Это работает как шарм, и я использую его.
Он откроет popover, когда вы нажмете, и если вы нажмете еще раз, он закроется, также если вы нажмете за пределы popover, popover будет закрыт.
Это также работает с более чем 1 popover.
function hideAllPopovers(){
$('[data-toggle="popover"]').each(function() {
if ($(this).data("showing") == "true"){
$(this).data("showing", "false");
$(this).popover('hide');
}
});
}
$('[data-toggle="popover"]').each(function() {
$(this).popover({
html: true,
trigger: 'manual'
}).click(function(e) {
if ($(this).data("showing") != "true"){
hideAllPopovers();
$(this).data("showing", "true");
$(this).popover('show');
}else{
hideAllPopovers();
}
e.stopPropagation();
});
});
$(document).click(function(e) {
hideAllPopovers();
});
Ответ 17
Я бы поставил фокус на вновь созданный pop-over и удалил его при размытии. Таким образом, не нужно было проверять, какой элемент DOM был нажат, и щелкнуть по щелчку и выбрать тоже: он не потеряет фокус и не исчезнет.
Код:
$('.popup-marker').popover({
html: true,
trigger: 'manual'
}).click(function(e) {
$(this).popover('toggle');
// set the focus on the popover itself
jQuery(".popover").attr("tabindex",-1).focus();
e.preventDefault();
});
// live event, will delete the popover by clicking any part of the page
$('body').on('blur','.popover',function(){
$('.popup-marker').popover('hide');
});
Ответ 18
Я делаю это как ниже
$("a[rel=popover]").click(function(event){
if(event.which == 1)
{
$thisPopOver = $(this);
$thisPopOver.popover('toggle');
$thisPopOver.parent("li").click(function(event){
event.stopPropagation();
$("html").click(function(){
$thisPopOver.popover('hide');
});
});
}
});
Надеюсь, это поможет!
Ответ 19
Если вы пытаетесь использовать twitter bootstrap popover с pjax, это сработало для меня:
App.Utils.Popover = {
enableAll: function() {
$('.pk-popover').popover(
{
trigger: 'click',
html : true,
container: 'body',
placement: 'right',
}
);
},
bindDocumentClickEvent: function(documentObj) {
$(documentObj).click(function(event) {
if( !$(event.target).hasClass('pk-popover') ) {
$('.pk-popover').popover('hide');
}
});
}
};
$(document).on('ready pjax:end', function() {
App.Utils.Popover.enableAll();
App.Utils.Popover.bindDocumentClickEvent(this);
});
Ответ 20
@RayOnAir, у меня такая же проблема с предыдущими решениями. Я тоже приближаюсь к решению @RayOnAir. Одна вещь, которая улучшилась, уже закрыта, когда вы нажимаете на другой маркер popover. Итак, мой код:
var clicked_popover_marker = null;
var popover_marker = '#pricing i';
$(popover_marker).popover({
html: true,
trigger: 'manual'
}).click(function (e) {
clicked_popover_marker = this;
$(popover_marker).not(clicked_popover_marker).popover('hide');
$(clicked_popover_marker).popover('toggle');
});
$(document).click(function (e) {
if (e.target != clicked_popover_marker) {
$(popover_marker).popover('hide');
clicked_popover_marker = null;
}
});
Ответ 21
Я нашел это модифицированным решением предложения pbaron выше, потому что его решение активировало popover ('hide') для всех элементов с помощью всплывающего маркера класса. Однако, когда вы используете popover() для содержимого html вместо содержимого данных, как я делаю ниже, любые клики внутри этого html-всплывающего окна фактически активируют popover ('hide'), который быстро закрывает окно. Этот метод ниже проходит через каждый элемент .popup-marker и сначала обнаруживается, если родительский элемент связан с идентификатором .popup-marker, который был нажат, и если это так, то не скрывает его. Все остальные divs скрыты...
$(function(){
$('html').click(function(e) {
// this is my departure from pbaron code above
// $('.popup-marker').popover('hide');
$('.popup-marker').each(function() {
if ($(e.target).parents().children('.popup-marker').attr('id')!=($(this).attr('id'))) {
$(this).popover('hide');
}
});
});
$('.popup-marker').popover({
html: true,
// this is where I'm setting the html for content from a nearby hidden div with id="html-"+clicked_div_id
content: function() { return $('#html-'+$(this).attr('id')).html(); },
trigger: 'manual'
}).click(function(e) {
$(this).popover('toggle');
e.stopPropagation();
});
});
Ответ 22
Я придумал это:
Мой сценарий включал в себя больше popovers на той же странице, и скрытие их просто делало их невидимыми, и из-за этого щелчок по элементам за popover не был возможен.
Идея состоит в том, чтобы отметить конкретную popover-ссылку как "активную", а затем вы можете просто "переключить" активный popover. Это позволит полностью закрыть всплывающее окно.
$('.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"
Ответ 23
Я пытался сделать простое решение для простой проблемы. Над сообщениями хорошие, но сложные для простой проблемы. Поэтому я сделал простую вещь. Просто добавлена кнопка закрытия. Это идеально для меня.
$(".popover-link").click(function(){
$(".mypopover").hide();
$(this).parent().find(".mypopover").show();
})
$('.close').click(function(){
$(this).parents('.mypopover').css('display','none');
});
<div class="popover-content">
<i class="fa fa-times close"></i>
<h3 class="popover-title">Title here</h3>
your other content here
</div>
.popover-content {
position:relative;
}
.close {
position:absolute;
color:#CCC;
right:5px;
top:5px;
cursor:pointer;
}
Ответ 24
Мне нравится это, просто, но эффективно..
var openPopup;
$('[data-toggle="popover"]').on('click',function(){
if(openPopup){
$(openPopup).popover('hide');
}
openPopup=this;
});
Ответ 25
Добавьте btn-popover
класс в свою кнопку/ссылку для всплывающих окон, которая открывает popover. Этот код закрывает popovers при нажатии на него.
$('body').on('click', function(event) {
if (!$(event.target).closest('.btn-popover, .popover').length) {
$('.popover').popover('hide');
}
});
Ответ 26
Еще проще, просто перебирайте все popovers и скрывайте, если не this
.
$(document).on('click', '.popup-marker', function() {
$(this).popover('toggle')
})
$(document).bind('click touchstart', function(e) {
var target = $(e.target)[0];
$('.popup-marker').each(function () {
// hide any open popovers except for the one we've clicked
if (!$(this).is(target)) {
$(this).popover('hide');
}
});
});
Ответ 27
Попробуйте data-trigger="focus"
вместо "click"
.
Это решило проблему для меня.
Ответ 28
jQuery(':not(.popup-marker)').once().click(function(){
jQuery('.popup-marker').hide();
});