Como posso fechar um popover Twitter Bootstrap com um clique de qualquer lugar (outra pessoa) na página?

Atualmente estou usando popovers com o Twitter Bootstrap, iniciado assim:

$('.popup-marker').popover({ html: true, trigger: 'manual' }).click(function(e) { $(this).popover('toggle'); e.preventDefault(); }); 

Como você pode ver, eles são acionados manualmente e clicar em. Pop-marcador (que é um div com uma imagem de fundo) alterna um popover. Isso funciona muito bem, mas eu também gostaria de poder fechar o popover com um clique em qualquer outro lugar na página (mas não no próprio popover!).

Eu tentei algumas coisas diferentes, incluindo as seguintes, mas sem resultados para mostrar:

 $('body').click(function(e) { $('.popup-marker').popover('hide'); }); 

Como posso fechar o popover com um clique em qualquer outro lugar da página, mas não com um clique no próprio popover?

Presumindo que somente um popover possa ser visível a qualquer momento, você pode usar um conjunto de sinalizadores para marcar quando há um popover visível e somente depois ocultá-los.

Se você definir o ouvinte de evento no corpo do documento, ele será acionado quando você clicar no elemento marcado com ‘popup-marker’. Então você terá que chamar stopPropagation() no object de evento. E aplique o mesmo truque ao clicar no próprio popover.

Abaixo está um código JavaScript de trabalho que faz isso. Ele usa 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/

A única ressalva é que você não poderá abrir 2 popovers ao mesmo tempo. Mas eu acho que seria confuso para o usuário, de qualquer maneira 🙂

Isso é ainda mais fácil:

 $('html').click(function(e) { $('.popup-marker').popover('hide'); }); $('.popup-marker').popover({ html: true, trigger: 'manual' }).click(function(e) { $(this).popover('toggle'); e.stopPropagation(); }); 

Eu tive uma necessidade semelhante, e encontrei essa grande extensão do Twitter Bootstrap Popover de Lee Carmichael, chamada BootstrapX – clickover . Ele também tem alguns exemplos de uso aqui . Basicamente, ele mudará o popover para um componente interativo que será fechado quando você clicar em outro lugar na página ou em um botão de fechamento dentro do popover. Isso também permitirá que vários popovers sejam abertos de uma só vez e um monte de outros resources interessantes.

Plugin pode ser encontrado aqui .

Exemplo de uso

 

javascript:

 // load click overs using 'rel' attribute $('[rel="clickover"]').clickover(); 

A solução aceita me deu alguns problemas (clicar no elemento ‘.popup-marker’ do popover aberto fez com que os popovers não funcionassem depois). Eu criei essa outra solução que funciona perfeitamente para mim e é bem simples (estou usando o 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'); } }); 

ATUALIZAÇÃO: Este código também funciona com o Bootstrap 3!

leia “Ignorar no próximo clique” aqui http://getbootstrap.com/javascript/#popovers

Você pode usar o gatilho de foco para descartar popovers no próximo clique, mas você deve usar a tag , não a tag , e também deve include um atributo tabindex

Exemplo:

  Dismissible popover  

Todas as respostas existentes são bastante fracas, pois elas dependem da captura de todos os events do documento, da localização de popovers ativos ou da modificação da chamada para .popover() .

Uma abordagem muito melhor é ouvir events show.bs.popover no corpo do documento e reagir de acordo. Abaixo está o código que fechará popovers quando o documento for clicado ou esc for pressionado, apenas ligando ouvintes de evento quando popovers forem mostrados:

 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); } 

https://github.com/lecar-red/bootstrapx-clickover

É uma extensão do popover bootstrap do twitter e vai resolver o problema de forma muito simples.

Por alguma razão, nenhuma das outras soluções aqui funcionou para mim. No entanto, depois de muita resolução de problemas, finalmente cheguei a este método que funciona perfeitamente (pelo menos para mim).

 $('html').click(function(e) { if( !$(e.target).parents().hasClass('popover') ) { $('#popover_parent').popover('destroy'); } }); 

No meu caso eu estava adicionando um popover a uma mesa e posicionando-o absolutamente acima / abaixo do td que foi clicado. A seleção da tabela foi tratada pelo jQuery-UI Selectable, então não tenho certeza se isso estava interferindo. No entanto, sempre que eu clicava dentro do popover, meu manipulador de cliques que segmentava $('.popover') nunca funcionava e a manipulação de events sempre era delegada ao manipulador de cliques $(html) . Eu sou relativamente novo no JS, então talvez eu esteja perdendo alguma coisa?

De qualquer forma, espero que isso ajude alguém!

Eu dou a todos os meus popovers anchors a class activate_popover . Eu ativo todos de uma vez onload

$('body').popover({selector: '.activate-popover', html : true, container: 'body'})

para obter o clique de funcionalidade que eu uso (em coffee 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') ) 

Que funciona perfeitamente bem com o bootstrap 2.3.1

Mesmo que haja muitas soluções aqui, eu gostaria de propor o meu também, não sei se há alguma solução lá em cima que resolva tudo, mas eu tentei 3 delas e elas tiveram problemas, como clicar no popover ele mesmo faz isso se esconder, outros que se eu tivesse outro botão popover clicado ambos / múltiplos popovers ainda aparecessem (como na solução selecionada), como sempre, esse fixou tudo

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

Aqui está a solução que funcionou muito bem para mim, se puder ajudar:

 /** * 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; } }); }); 

Aqui está a minha solução, pelo que vale:

 // 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's 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"); } }); }); 

Eu tive algum problema para fazê-lo funcionar no bootstrap 2.3.2. Mas eu adorei assim:

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

tweaked @ David solução Wolever ligeiramente:

 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); } 

Esta pergunta também foi feita aqui e minha resposta fornece não apenas uma maneira de entender os methods de travessia do jQuery DOM, mas também duas opções para manipular o fechamento de popovers clicando em fora.

Abra vários popovers de uma só vez ou um popover de cada vez.

Além disso, esses pequenos trechos de código podem lidar com o fechamento de botões contendo icons!

https://stackoverflow.com/a/14857326/1060487

Este funciona como um encanto e eu uso.

Ele abrirá o popover quando você clicar e se você clicar novamente ele fechará, também se você clicar fora do popover o popover será fechado.

Isso também funciona com mais de um 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(); }); 

Gostaria de definir o foco para o pop-over recém-criado e removê-lo no desfoque. Dessa forma, não é necessário verificar qual elemento do DOM foi clicado e o pop-over pode ser clicado e selecionado também: ele não perderá o foco e não desaparecerá.

O código:

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

Eu faço como abaixo

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

Espero que isto ajude!

Se você está tentando usar popover bootstrap no twitter com o pjax, isso funcionou para mim:

 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); }); 

@RayOnAir, tenho o mesmo problema com as soluções anteriores. Cheguei perto da solução @RayOnAir também. Uma coisa que melhorou está perto já abriu popover quando clica em outro marcador popover. Então meu código é:

 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; } }); 

Eu achei esta uma solução modificada da sugestão de pbaron acima, porque sua solução ativou o popover (‘hide’) em todos os elementos com class ‘popup-marker’. No entanto, quando você está usando popover () para conteúdo html em vez do conteúdo de dados, como eu estou fazendo abaixo, qualquer clique dentro desse popup de html ativa o popover (‘hide’), que prontamente fecha a janela. Esse método abaixo percorre cada elemento .popup-marker e descobre primeiro se o pai estiver relacionado ao id do marcador .popup que foi clicado e, em caso afirmativo, não o ocultará. Todos os outros divs estão escondidos …

  $(function(){ $('html').click(function(e) { // this is my departure from pbaron's 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(); }); }); 

Eu inventei isso:

Meu cenário incluía mais popovers na mesma página, e ocultá-los apenas os tornava invisíveis e, por causa disso, clicar em itens por trás do popover não era possível. A idéia é marcar o popover-link específico como ‘ativo’ e então você pode simplesmente ‘alternar’ o popover ativo. Se o fizer, fechará completamente o 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" 

Eu estava tentando fazer uma solução simples para um problema simples. Postagens acima são boas, mas muito complicadas para um problema simples. Então eu fiz uma coisa simples. Acabei de adicionar um botão de fechar. É perfeito para mim.

  $(".popover-link").click(function(){ $(".mypopover").hide(); $(this).parent().find(".mypopover").show(); }) $('.close').click(function(){ $(this).parents('.mypopover').css('display','none'); }); 

Title here

your other content here
.popover-content { position:relative; } .close { position:absolute; color:#CCC; right:5px; top:5px; cursor:pointer; }

Eu gosto disso, simples mas eficaz ..

 var openPopup; $('[data-toggle="popover"]').on('click',function(){ if(openPopup){ $(openPopup).popover('hide'); } openPopup=this; }); 

Adicione btn-popover class btn-popover ao seu botão popover / link que abre o popover. Esse código fechará os popovers quando clicar fora dele.

 $('body').on('click', function(event) { if (!$(event.target).closest('.btn-popover, .popover').length) { $('.popover').popover('hide'); } }); 

Uma solução ainda mais fácil, basta percorrer todos os popovers e ocultar, se não 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'); } }); }); 
 $('.popForm').popover(); $('.conteneurPopForm').on("click",".fermePopover",function(){ $(".popForm").trigger("click"); }); 

Para ser claro, basta acionar o popover

Outra solução, cobria o problema que eu tinha com clicando em descendentes do popover:

 $(document).mouseup(function (e) { // The target is not popover or popover descendants if (!$(".popover").is(e.target) && 0 === $(".popover").has(e.target).length) { $("[data-toggle=popover]").popover('hide'); } }); 

Tente data-trigger="focus" vez de "click" .

Isso resolveu o problema para mim.

 jQuery(':not(.popup-marker)').once().click(function(){ jQuery('.popup-marker').hide(); });