outside close bootstrap autoclose javascript jquery twitter-bootstrap

javascript - close - ¿Cómo puedo cerrar un popover Twitter Bootstrap con un clic desde cualquier lugar(más) en la página?



popover css (29)

Actualmente estoy usando popovers con Twitter Bootstrap, iniciado así:

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

Como puede ver, se activan manualmente y al hacer clic en .popup-marker (que es un div con una imagen de fondo) se alterna un popover. Esto funciona muy bien, pero también me gustaría poder cerrar el popover con un clic en cualquier otro lugar de la página (¡pero no en el popover mismo!).

Probé algunas cosas diferentes, entre ellas las siguientes, pero sin resultados para mostrar:

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

¿Cómo puedo cerrar el popover haciendo clic en cualquier otro lugar de la página, pero sin hacer clic en el popover?


@RayOnAir, tengo el mismo problema con las soluciones anteriores. También me acerco a la solución @RayOnAir. Una cosa que mejoró es el popover cerrado cuando se hace clic en otro marcador de popover. Entonces mi código es:

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


A pesar de que hay muchas soluciones aquí, me gustaría proponer la mía también, no sé si hay alguna solución que lo resuelva todo, pero probé 3 y tuvieron problemas, como hacer clic en el popover lo hace esconderse, otros que si tuviera otro popover abotonaran ambos botones / aparecerían múltiples popovers (como en la solución seleccionada), sin embargo, este lo arregló todo

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


Agregue la clase btn-popover a su botón / enlace de popover que abre el popover. Este código cerrará los popovers al hacer clic fuera de él.

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


Aquí está la solución que funcionó muy bien para mí, si puede ayudar:

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


Aquí está mi solución, por lo 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"); } }); });


Encontré que se trataba de una solución modificada de la sugerencia de pbaron anterior, porque su solución activaba el popover (''hide'') en todos los elementos con la clase ''popup-marker''. Sin embargo, cuando usa popover () para contenido html en lugar del contenido de datos, como hago abajo, cualquier clic dentro de esa ventana emergente html activa realmente el popover (''hide''), que cierra la ventana rápidamente. Este método a continuación itera a través de cada elemento .popup-marker y descubre primero si el padre está relacionado con el id del marcador .popup que se hizo clic, y si es así, no lo oculta. Todos los demás divs están ocultos ...

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


Esta pregunta también se hizo aquí y mi respuesta proporciona no solo una forma de entender los métodos de cruce de jQuery DOM, sino también dos opciones para manejar el cierre de popovers haciendo clic afuera.

Abre múltiples popovers a la vez o un popover a la vez.

Además, estos pequeños fragmentos de código pueden manejar el cierre de los botones que contienen íconos.

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


Este funciona como un amuleto y lo uso.

Se abrirá el popover cuando haga clic y si vuelve a hacer clic se cerrará, también si hace clic fuera del popover se cerrará el popover.

Esto también funciona con más de 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(); });


Esto es aún más 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(); });


Intentaba hacer una solución simple para un problema simple. Los mensajes anteriores son buenos pero muy complicados para un problema simple. Así que hice una cosa simple. Acabo de agregar un botón de cerrar. Es perfecto para mi

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


La solución aceptada me dio algunos problemas (al hacer clic en el elemento ''.popup-marker'' del popover abierto, los popovers no funcionaron después). Se me ocurrió esta otra solución que funciona perfectamente para mí y es bastante simple (estoy usando 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''); } });

ACTUALIZACIÓN: ¡Este código también funciona con Bootstrap 3!


Le doy a todos mis popovers anclas la clase activate_popover . Los activo todos a la vez onload

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

para obtener la funcionalidad de clic que uso y uso (en script de café):

$(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 perfectamente bien con bootstrap 2.3.1


Lo hago como abajo

$("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 esto ayude!


Me gusta esto, simple pero efectivo ...

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


Pondría el foco en el pop-over recién creado y lo eliminaría en blur. De esta forma, no es necesario verificar en qué elemento del DOM se ha hecho clic y se puede hacer clic en el elemento emergente y seleccionarlo también: no perderá su foco y no desaparecerá.

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


Por alguna razón, ninguna de las otras soluciones aquí funcionó para mí. Sin embargo, después de mucha resolución de problemas, finalmente llegué a este método que funciona perfectamente (al menos para mí).

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

En mi caso, estaba agregando un popover a una mesa y colocándolo por encima / debajo del td que se hizo clic. JQuery-UI manejaba la selección de la tabla, por lo que no estoy seguro de si eso interfería. Sin embargo, cada vez que hacía clic dentro del popover, mi manejador de clics que apuntaba a $(''.popover'') nunca funcionó y el manejo del evento siempre fue delegado al manejador de clics $(html) . Soy bastante nuevo para JS así que tal vez me estoy perdiendo algo?

De todos modos espero que esto ayude a alguien!


Pruebe con data-trigger="focus" lugar de "click" .

Esto resolvió mi problema.


Se me ocurrió esto:

Mi escenario incluía más popovers en la misma página, y ocultarlos solo los hacía invisibles y, por eso, no era posible hacer clic en elementos detrás del popover. La idea es marcar el enlace popover específico como ''activo'' y luego simplemente ''alternar'' el popover activo. Al hacerlo, se cerrará por completo el 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"


Si estás tratando de usar Twitter bootstrap popover con pjax, esto funcionó para mí:

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


Suponiendo que solo un popover puede ser visible en cualquier momento, puede usar un conjunto de indicadores para marcar cuando hay un popover visible, y solo luego ocultarlos.

Si configura el detector de eventos en el cuerpo del documento, se activará cuando haga clic en el elemento marcado con ''marcador emergente''. Entonces tendrá que llamar a stopPropagation() en el objeto del evento. Y aplique el mismo truco al hacer clic en el popover.

A continuación se muestra un código JavaScript que funciona y que hace esto. Utiliza 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/

La única advertencia es que no podrás abrir 2 popovers al mismo tiempo. Pero creo que eso sería confuso para el usuario, de todos modos :-)


Tenía una necesidad similar, y encontré esta gran pequeña extensión de Twitter Bootstrap Popover de Lee Carmichael, llamada BootstrapX - clickover . Él también tiene algunos ejemplos de uso here . Básicamente cambiará el popover en un componente interactivo que se cerrará cuando haga clic en otro lugar de la página, o en un botón de cerrar dentro del popover. Esto también permitirá la apertura de varios popovers a la vez y muchas otras funciones agradables.

El complemento se puede encontrar aquí .

Ejemplo de uso

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


Todas las respuestas existentes son bastante débiles, ya que dependen de la captura de todos los eventos del documento, la búsqueda de popovers activos o la modificación de .popover() .

Un enfoque mucho mejor es escuchar los eventos show.bs.popover en el cuerpo del documento y luego reaccionar en consecuencia. A continuación se muestra un código que cerrará popovers cuando se haga clic en el documento o se presione esc , solo vinculando eventos oyentes cuando se muestren 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); }


Tuve un problema para hacerlo funcionar en bootstrap 2.3.2. Pero lo aplasté de esta manera:

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


Una solución aún más fácil, simplemente iterar a través de todos los popovers y ocultar si no 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''); } }); });


lea "Descartar en el siguiente clic" aquí http://getbootstrap.com/javascript/#popovers

Puede utilizar el desencadenador de enfoque para descartar los popovers en el siguiente clic, pero debe utilizar la etiqueta <a> , no la etiqueta <button> , y también debe incluir un atributo tabindex ...

Ejemplo:

<a href="#" tabindex="0" class="btn btn-lg btn-danger" data-toggle="popover" data-trigger="focus" title="Dismissible popover" data-content="And here''s some amazing content. It''s very engaging. Right?"> Dismissible popover </a>


retocado @David Wolever solución levemente:

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



$(''.popForm'').popover(); $(''.conteneurPopForm'').on("click",".fermePopover",function(){ $(".popForm").trigger("click"); });

Para ser claro, solo activa el popover


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