bootstrap twitter-bootstrap popover

¿Cómo descartar una ventana emergente de Twitter Bootstrap haciendo clic afuera?



tooltip bootstrap css (30)

¿Podemos hacer que los popovers sean descartables de la misma manera que los modales, es decir? ¿Hacer que se cierren cuando el usuario hace clic en algún lugar fuera de ellos?

Desafortunadamente, no puedo usar modal real en lugar de popover, porque modal significa posición: fija y eso ya no sería popover. :(


Acabo de eliminar otras ventanas emergentes activas antes de que se muestre la nueva ventana emergente (bootstrap 3):

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


Básicamente, esto no es muy complejo, pero hay que hacer algunas comprobaciones para evitar fallos.

Demo (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 http://getbootstrap.com/javascript/#popovers :

JS Bin Demo

Marcado específico requerido para descartar al siguiente clic

Para un correcto comportamiento entre navegadores y plataformas, debe usar la etiqueta <a> , no la etiqueta <button> , y también debe incluir los atributos role="button" y tabindex .


Con bootstrap 2.3.2 puede configurar el disparador para ''enfocar'' y simplemente funciona:

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


De acuerdo con http://getbootstrap.com/javascript/#popovers ,

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

Utilice el disparador de enfoque para descartar las ventanas emergentes en el siguiente clic que haga el usuario.

$(''.popover-dismiss'').popover({ trigger: ''focus'' })


Descubrimos que tuvimos un problema con la solución de @mattdlockyer (¡Gracias por la solución!). Cuando se utiliza la propiedad selector para el constructor de popover como este ...

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

... la solución propuesta para BS3 no funcionará. En su lugar, crea una segunda instancia de popover local a su $(this) . Aquí está nuestra solución para evitar que:

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

Como se mencionó, $(this).popover(''hide''); creará una segunda instancia debido a la escucha delegada. La solución provista solo oculta los popovers que ya están instanciados.

Espero poderles ahorrarles un poco de tiempo.


Estaba teniendo problemas con la solución de mattdlockyer porque estaba configurando enlaces de popover dinámicamente usando un código como este:

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

Así que tuve que modificarlo así. Me solucionó muchos problemas:

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

Recuerde que destroy se deshace del elemento, por lo que la parte del selector es importante al inicializar los elementos emergentes.


Este enfoque garantiza que puede cerrar una ventana emergente haciendo clic en cualquier lugar de la página. Si hace clic en otra entidad en la que se puede hacer clic, se ocultan todos los demás elementos emergentes. La animación: falso es necesario, de lo contrario obtendrá un error de eliminación de jquery en su consola.

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


Esto es tarde para la fiesta ... pero pensé que lo compartiría. Me encanta el popover pero tiene muy poca funcionalidad incorporada. Escribí una extensión bootstrap .bubble () que es todo lo que me gustaría que fuera popover. Cuatro formas de despedir. Haz clic en el exterior, activa el enlace, haz clic en la X y pulsa escapar.

Se posiciona automáticamente para que nunca salga de la página.

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

Esta no es una promoción gratuita ... He agarrado el código de otras personas tantas veces en mi vida que quería ofrecer mis propios esfuerzos. Dale un giro y ve si funciona para ti.


Esto ha sido preguntado antes here . La misma respuesta que di entonces sigue siendo válida:

Tenía una necesidad similar, y encontré esta pequeña gran extensión de Twitter Bootstrap Popover de Lee Carmichael, llamada BootstrapX - clickover . También tiene algunos ejemplos de uso here . Básicamente, cambiará la ventana emergente a un componente interactivo que se cerrará cuando haga clic en otra parte de la página, o en un botón de cierre dentro de la ventana emergente. Esto también permitirá que múltiples ventanas emergentes se abran a la vez y un montón de otras características interesantes.


He intentado muchas de las respuestas anteriores, realmente nada me funciona, pero esta solución lo hizo:

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

Recomiendan usar la etiqueta de anclaje no el botón y cuidar los roles role = "button" + data-trigger = "focus" + tabindex = "0".

Ex:

<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>


Hice un jsfiddle para mostrarte cómo hacerlo:

http://jsfiddle.net/3yHTH/

La idea es mostrar la ventana emergente cuando hace clic en el botón y ocultar la ventana emergente cuando hace clic fuera del botón.

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


Intenta esto, esto se esconderá haciendo clic afuera.

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


La respuesta de @guya funciona, a menos que tenga algo como un selector de fecha o un selector de tiempo en la ventana emergente. Para arreglar eso, esto es lo que he hecho.

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


Ninguna de las supuestas soluciones altamente votadas me funcionó correctamente. Cada uno de ellos genera un error cuando, después de abrir y cerrar (haciendo clic en otros elementos) la ventana emergente por primera vez, no se abre de nuevo, hasta que haga dos clics en el enlace de activación en lugar de uno.

Así que lo modifiqué ligeramente:

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


Ok, este es mi primer intento de responder realmente algo en , así que aquí va nada: P

Parece que no está del todo claro si esta funcionalidad realmente funciona de manera inmediata en la última versión (bueno, si está dispuesto a comprometer donde el usuario puede hacer clic. No estoy seguro si tiene que poner ''clic'' hover ''per-se pero en un iPad, haga clic en funciona como un conmutador.

El resultado final es que, en un escritorio, puede desplazarse o hacer clic (la mayoría de los usuarios lo harán). En un dispositivo táctil, al tocar el elemento lo subirá, y al tocarlo de nuevo lo bajará. Por supuesto, esto es un pequeño compromiso con su requisito original, pero al menos su código ahora está más limpio :)

$ (". my-popover"). popover ({trigger: ''click hover''});


Parece que el método ''ocultar'' no funciona si creas la ventana emergente con el selector, en lugar de eso, se debe usar ''destruir''.

Lo hice funcionar así:

$(document.body'').popover({selector: ''[data-toggle=popover]''});

JSpiddle aquí


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 lo tanto, no era posible hacer clic en los elementos detrás del popover. La idea es marcar el popover-link específico como ''activo'' y luego simplemente puede ''conmutar'' el popover activo. Si lo hace, se cerrará la ventana emergente completamente $ (''. 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"


Solución aceptada modificada. Lo que he experimentado es que después de que algunos popovers estuvieran ocultos, tendrían que hacer clic dos veces para aparecer de nuevo. Esto es lo que hice para garantizar que no se invocara a popover (''hide'') en popovers ya ocultos.

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


También puede usar la propagación de eventos para eliminar la ventana emergente del DOM. Está un poco sucio, pero funciona bien.

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

En su HTML, agregue la clase .popover-close al contenido dentro de la ventana emergente que debe cerrar la ventana emergente.


Tomando el código de Matt Lockyer, he hecho un simple reinicio para que el elemento no quede cubierto por el elemento en hide.

Código de Matt: http://mattlockyer.com/2013/04/08/close-a-twitter-bootstrap-popover-when-clicking-outside/

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


demostración: 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; });

}

Esta es mi solución para ello.


esta solución elimina el molesto segundo clic cuando se muestra la ventana emergente por segunda vez

probado con con Bootstrap v3.3.7

data-trigger="focus"


probado con 3.3.6 y segundo clic está bien

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


simplemente agrega este atributo con el elemento

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


Actualización: Una solución un poco más robusta: http://jsfiddle.net/mattdlockyer/C5GBU/72/

Para botones que contienen solo texto:

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

Para el uso de botones que contienen iconos (este código tiene un error en Bootstrap 3.3.6, vea la corrección a continuación en esta respuesta)

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

Para ventanas emergentes generadas por JS Use ''[data-original-title]'' en lugar de ''[data-toggle="popover"]''

Advertencia: la solución anterior permite abrir múltiples ventanas emergentes a la vez.

Un popover a la vez por favor:

Actualización: Bootstrap 3.0.x, vea el código o el violín 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''); } }); });

Esto maneja el cierre de ventanas emergentes ya abiertas y no se hace clic o sus enlaces no se han hecho clic.

Actualización: Bootstrap 3.3.6, ver violín

Corrige el problema donde, después del cierre, toma 2 clics para volver a abrir

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


La versión más simple, la más segura , funciona con cualquier versión bootstrap.

Demostración: http://jsfiddle.net/guya/24mmM/

Demo 2: no descartar al hacer clic dentro del contenido de la ventana emergente http://jsfiddle.net/guya/fjZja/

Demostración 3: varios popovers: http://jsfiddle.net/guya/6YCjW/

Simplemente llamando a esta línea se descartarán todos los popovers:

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

Descartar todos los popovers al hacer clic fuera con este código:

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

El fragmento de arriba adjunta un evento de clic en el cuerpo. Cuando el usuario haga clic en una ventana emergente, se comportará de forma normal. Cuando el usuario haga clic en algo que no sea una ventana emergente, cerrará todas las ventanas emergentes.

También funcionará con ventanas emergentes que se inician con Javascript, a diferencia de otros ejemplos que no funcionarán. (ver la demo)

Si no desea descartar al hacer clic dentro del contenido de la ventana emergente, use este código (vea el enlace a la segunda demostración):

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



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


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

Esto cierra todas las ventanas emergentes si hace clic en cualquier lugar excepto en una ventana emergente