jquery - content - ¿Cómo puedo mantener el popover bootstrap vivo mientras el popover está siendo suspendido?
popover jquery (15)
Estoy usando el popover de twitter boostrap para crear una tarjeta flotante para mostrar la información del usuario, y estoy activando el popover en el mouseover check jsfiddle aquí . Quiero mantener este popover vivo mientras está suspendido.
<a href="#" id="example" class="btn btn-danger" rel="popover" >hover for popover</a>
$(''#example'').popover({
html : true,
trigger : ''manual'',
content : function() {
return ''<div class="box"></div>'';
}
});
$(document).on(''mouseover'', ''#example'', function(){
$(''#example'').popover(''show'');
});
$(document).on(''mouseleave'', ''#example'', function(){
$(''#example'').popover(''hide'');
});
Puedes pensar en trabajar con facebook hover card. Quiero hacerlo de la misma manera. ¿Cómo puedo hacer esto?
Pequeña modificación (de la solución proporcionada por vikas) para adaptarse a mi caso de uso.
1. Abrir popover en el evento hover para el botón popover
2. Mantenga el popover abierto cuando se cierne sobre la caja de popover
3. Cierre popover en mouseleave para el botón popover, o el cuadro popover.
$(".pop").popover({ trigger: "manual" , html: true, animation:false})
.on("mouseenter", function () {
var _this = this;
$(this).popover("show");
$(".popover").on("mouseleave", function () {
$(_this).popover(''hide'');
});
}).on("mouseleave", function () {
var _this = this;
setTimeout(function () {
if (!$(".popover:hover").length) {
$(_this).popover("hide");
}
}, 300);
});
Aquí está mi opinión: http://jsfiddle.net/WojtekKruszewski/Zf3m7/22/
En ocasiones, al mover el mouse desde el disparador de popover al contenido de popover real en diagonal , pasas el cursor sobre los elementos a continuación. Quería manejar esas situaciones: siempre que llegue al contenido de popover antes de que se agote el tiempo de espera, estará a salvo (el popover no desaparecerá). Requiere una opción de delay
.
Este hack básicamente anula la función de leave
Popover, pero llama al original (que inicia el temporizador para ocultar el popover). A continuación, agrega un elemento de contenido de popover de oyente a mouseenter
oyente mouseenter
.
Si el mouse entra en el popover, el temporizador se borrará. Luego, se activa para mouseleave
el mouseleave
de mouseleave
sobre popover y, si se activa, llama a la función original leave para que pueda comenzar a ocultar el temporizador.
var originalLeave = $.fn.popover.Constructor.prototype.leave;
$.fn.popover.Constructor.prototype.leave = function(obj){
var self = obj instanceof this.constructor ?
obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data(''bs.'' + this.type)
var container, timeout;
originalLeave.call(this, obj);
if(obj.currentTarget) {
container = $(obj.currentTarget).siblings(''.popover'')
timeout = self.timeout;
container.one(''mouseenter'', function(){
//We entered the actual popover – call off the dogs
clearTimeout(timeout);
//Let''s monitor popover content instead
container.one(''mouseleave'', function(){
$.fn.popover.Constructor.prototype.leave.call(self, self);
});
})
}
};
Así es como lo hice con bootspop popover con ayuda de otros bits en la red. Obtiene dinámicamente el título y el contenido de diferentes productos que se muestran en el sitio. Cada producto o popover obtiene una identificación única. Popover desaparecerá al salir del producto ($ this .pop) o el popover. Se usa Timeout donde se mostrará el popover hasta salir por producto en lugar de popover.
$(".pop").each(function () {
var $pElem = $(this);
$pElem.popover(
{
html: true,
trigger: "manual",
title: getPopoverTitle($pElem.attr("id")),
content: getPopoverContent($pElem.attr("id")),
container: ''body'',
animation:false
}
);
}).on("mouseenter", function () {
var _this = this;
$(this).popover("show");
console.log("mouse entered");
$(".popover").on("mouseleave", function () {
$(_this).popover(''hide'');
});
}).on("mouseleave", function () {
var _this = this;
setTimeout(function () {
if (!$(".popover:hover").length) {
$(_this).popover("hide");
}
}, 100);
});
function getPopoverTitle(target) {
return $("#" + target + "_content > h3.popover-title").html();
};
function getPopoverContent(target) {
return $("#" + target + "_content > div.popover-content").html();
};
Creo que una manera fácil sería esta:
$(''.popover'').each(function () {
var $this = $(this);
$this.popover({
trigger: ''hover'',
content: ''Content Here'',
container: $this
})
});
De esta forma, el popover se crea dentro del elemento objetivo en sí mismo. así que cuando mueves el mouse sobre el popover, todavía está sobre el elemento. Bootstrap 3.3.2 funciona bien con esto. La versión anterior puede tener algunos problemas con la animación, por lo que es posible que desee deshabilitar "animación: falso"
Descubrí que el mouseleave
no se mouseleave
cuando sucedan cosas extrañas, como que el foco de la ventana cambia repentinamente, luego el usuario regresa al navegador. En casos como este, mouseleave
nunca se disparará hasta que el cursor pase y deje el elemento nuevamente.
Esta solución que se me ocurrió depende del mouseenter
en el objeto de la window
, por lo que desaparece cuando el mouse se mueve a otro lugar en la página.
Esto fue diseñado para funcionar con múltiples elementos en la página que lo desencadenarán (como en una tabla).
var allMenus = $(".menus");
allMenus.popover({
html: true,
trigger: "manual",
placement: "bottom",
content: $("#menuContent")[0].outerHTML
}).on("mouseenter", (e) => {
allMenus.not(e.target).popover("hide");
$(e.target).popover("show");
e.stopPropagation();
}).on("shown.bs.popover", () => {
$(window).on("mouseenter.hidepopover", (e) => {
if ($(e.target).parents(".popover").length === 0) {
allMenus.popover("hide");
$(window).off("mouseenter.hidepopover");
}
});
});
Esta es una solución que ideé y que parece funcionar bien al mismo tiempo que le permite usar la implementación Bootstrap normal para activar todos los popovers.
Violín original: https://jsfiddle.net/eXpressive/hfear592/
Portado a esta pregunta:
<a href="#" id="example" class="btn btn-danger" rel="popover" >hover for popover</a>
$(''#example'').popover({
html : true,
trigger : ''hover'',
content : function() {
return ''<div class="box"></div>'';
}
}).on(''hide.bs.popover'', function () {
if ($(".popover:hover").length) {
return false;
}
});
$(''body'').on(''mouseleave'', ''.popover'', function(){
$(''.popover'').popover(''hide'');
});
Esta solución funcionó bien para mí: (ahora es a prueba de balas) ;-)
function enableThumbPopover() {
var counter;
$(''.thumbcontainer'').popover({
trigger: ''manual'',
animation: false,
html: true,
title: function () {
return $(this).parent().find(''.thumbPopover > .title'').html();
},
content: function () {
return $(this).parent().find(''.thumbPopover > .body'').html();
},
container: ''body'',
placement: ''auto''
}).on("mouseenter",function () {
var _this = this; // thumbcontainer
console.log(''thumbcontainer mouseenter'')
// clear the counter
clearTimeout(counter);
// Close all other Popovers
$(''.thumbcontainer'').not(_this).popover(''hide'');
// start new timeout to show popover
counter = setTimeout(function(){
if($(_this).is('':hover''))
{
$(_this).popover("show");
}
$(".popover").on("mouseleave", function () {
$(''.thumbcontainer'').popover(''hide'');
});
}, 400);
}).on("mouseleave", function () {
var _this = this;
setTimeout(function () {
if (!$(".popover:hover").length) {
if(!$(this).is('':hover''))
{
$(_this).popover(''hide'');
}
}
}, 200);
});
}
Estoy de acuerdo en que la mejor manera es usar la que ofrecen: David Chase , Cu Ly y otros, que la forma más sencilla de hacerlo es usar el container: $(this)
property de la siguiente manera:
$(selectorString).each(
var $this = $(this);
$this.popover({
html: true,
placement: "top",
container: $this,
trigger: "hover",
title: "Popover",
content: "Hey, you hovered on element"
});
);
Quiero señalar aquí que el popover en este caso heredará todas las propiedades del elemento actual . Entonces, por ejemplo, si haces esto para un elemento .btn
(bootstrap), no podrás seleccionar texto dentro del popover . Solo quería grabar eso ya que pasé bastante tiempo golpeando mi cabeza en esto.
He venido después de otra solución a esto ... aquí está el código
$(''.selector'').popover({
html: true,
trigger: ''manual'',
container: $(this).attr(''id''),
placement: ''top'',
content: function () {
$return = ''<div class="hover-hovercard"></div>'';
}
}).on("mouseenter", function () {
var _this = this;
$(this).popover("show");
$(this).siblings(".popover").on("mouseleave", function () {
$(_this).popover(''hide'');
});
}).on("mouseleave", function () {
var _this = this;
setTimeout(function () {
if (!$(".popover:hover").length) {
$(_this).popover("hide")
}
}, 100);
});
La respuesta de Vikas funciona perfectamente para mí, aquí también agrego soporte para la demora (mostrar / ocultar).
var popover = $(''#example'');
var options = {
animation : true,
html: true,
trigger: ''manual'',
placement: ''right'',
delay: {show: 500, hide: 100}
};
popover
.popover(options)
.on("mouseenter", function () {
var t = this;
var popover = $(this);
setTimeout(function () {
if (popover.is(":hover")) {
popover.popover("show");
popover.siblings(".popover").on("mouseleave", function () {
$(t).popover(''hide'');
});
}
}, options.delay.show);
})
.on("mouseleave", function () {
var t = this;
var popover = $(this);
setTimeout(function () {
if (popover.siblings(".popover").length && !popover.siblings(".popover").is(":hover")) {
$(t).popover("hide")
}
}, options.delay.hide);
});
También por favor, presten atención, cambié:
if (!$(".popover:hover").length) {
con:
if (popover.siblings(".popover").length && !popover.siblings(".popover").is(":hover")) {
para que haga referencia exactamente a ese popover abierto, y no a ningún otro (ya que ahora, a través de la demora, más de 1 podría estar abierto al mismo tiempo)
La respuesta elegida funciona pero fallará si el popover se inicializa con el body
como contenedor.
$(''a'').popover({ container: ''body'' });
Una solución basada en la respuesta elegida es el siguiente código que debe colocarse antes de usar el popover.
var originalLeave = $.fn.popover.Constructor.prototype.leave;
$.fn.popover.Constructor.prototype.leave = function(obj) {
var self = obj instanceof this.constructor ? obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data(''bs.'' + this.type);
originalLeave.call(this, obj);
if (obj.currentTarget) {
self.$tip.one(''mouseenter'', function() {
clearTimeout(self.timeout);
self.$tip.one(''mouseleave'', function() {
$.fn.popover.Constructor.prototype.leave.call(self, self);
});
})
}
};
El cambio es mínimo usando self.$tip
lugar de atravesar el DOM esperando que el popover sea siempre un hermano del elemento.
Lo mismo para la información sobre herramientas:
Para mí, la solución siguiente funciona porque no agrega detectores de eventos en cada "mouseenter" y es posible desplazarse hacia atrás en el elemento de información sobre herramientas que mantiene activa la información sobre herramientas.
$ ->
$(''.element'').tooltip({
html: true,
trigger: ''manual''
}).
on ''mouseenter'', ->
clearTimeout window.tooltipTimeout
$(this).tooltip(''show'') unless $(''.tooltip:visible'').length > 0
.
on ''mouseleave'', ->
_this = this
window.tooltipTimeout = setTimeout ->
$(_this).tooltip(''hide'')
, 100
$(document).on ''mouseenter'', ''.tooltip'', ->
clearTimeout window.tooltipTimeout
$(document).on ''mouseleave'', ''.tooltip'', ->
trigger = $($(this).siblings(''.element'')[0])
window.tooltipTimeout = setTimeout ->
trigger.tooltip(''hide'')
, 100
Será más flexible con hover()
:
$(".my-popover").hover(
function() { // mouse in event
$this = $(this);
$this.popover({
html: true,
content: "Your content",
trigger: "manual",
animation: false
});
$this.popover("show");
$(".popover").on("mouseleave", function() {
$this.popover("hide");
});
},
function() { // mouse out event
setTimeout(function() {
if (!$(".popover:hover").length) {
$this.popover("hide");
}
}, 100);
}
)
Utilicé el conjunto de disparadores para colocar el contenedor y le di al conjunto de contenedores el elemento #element
y finalmente #element
una ubicación del box
a la right
.
Esta debería ser tu configuración:
$(''#example'').popover({
html: true,
trigger: ''hover'',
container: ''#example'',
placement: ''right'',
content: function () {
return ''<div class="box"></div>'';
}
});
y #example
css needs position:relative;
revisa el jsfiddle a continuación:
https://jsfiddle.net/9qn6pw4p/1/
Editado
Este violín tiene ambos enlaces que funcionan sin problemas http://jsfiddle.net/davidchase03/FQE57/4/
$(function() {
$("[data-toggle = ''popover'']").popover({
placement: ''left'',
html: true,
trigger: " focus",
}).on("mouseenter", function() {
var _this = this;
$(this).popover("show");
$(this).siblings(".popover").on("mouseleave", function() {
$(_this).popover(''hide'');
});
}).on("mouseleave", function() {
var _this = this;
setTimeout(function() {
if (!$(".popover:hover").length) {
$(_this).popover("hide")
}
}, 100);
});
});