我怎样才能在悬停的时候让 Bootstrap 泡芙保持活力呢?

我正在使用一个 Bootstrap 弹出窗口来创建一个显示用户信息的悬停卡,我在鼠标悬停按钮上触发它。我想让这个弹出窗口保持活动,而弹出窗口本身正在悬停,但它消失后,用户停止悬停在按钮。我怎么能这么做?

$('#example').popover({
html : true,
trigger : 'manual',
content : function() {
return '<div class="box">Popover</div>';
}
});


$(document).on('mouseover', '#example', function(){
$('#example').popover('show');
});


$(document).on('mouseleave', '#example', function(){
$('#example').popover('hide');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.js"></script>
<script src="https://unpkg.com/@popperjs/core@2"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"/>


<a href="#" id="example" class="btn btn-danger" rel="popover" >hover for popover</a>

114771 次浏览

我将触发器集设置为 hover,并将容器集设置为 #element,最后将 box的位置添加到 right

这应该是你的设置:

$('#example').popover({
html: true,
trigger: 'hover',
container: '#example',
placement: 'right',
content: function () {
return '<div class="box"></div>';
}
});

#example css 需要 position:relative;检查下面的 jsfiddle:

Https://jsfiddle.net/9qn6pw4p/1/

编辑

这个小提琴有两个链接,工作没有问题 Http://jsfiddle.net/davidchase03/fqe57/4/

我已经找到了另一个解决方案... 这是密码

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

以下是我的观点: http://jsfiddle.net/WojtekKruszewski/Zf3m7/22/

有时,当鼠标从弹出触发器移动到实际的弹出内容 对角线时,您将鼠标悬停在下面的元素上。我想处理这样的情况-只要你达到弹出窗口内容之前的超时火,你是安全的(弹出窗口不会消失)。它需要 delay选项。

这种方法基本上覆盖了 Popover leave函数,但是调用了原始函数(它启动计时器来隐藏 Popover)。然后,它将一个一次性侦听器附加到 mouseenter popover 内容元素的。

如果鼠标进入弹出窗口,计时器将被清除。然后它在 popover 上监听 mouseleave,如果它被触发,它就调用原来的 leave 函数,这样它就可以启动 hide timer。

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

这就是我如何做引导弹出在网络周围的其他位的帮助。动态获取标题和内容从模具各种产品显示在网站上。每个产品或泡芙都有唯一的 ID。Popover 将在退出产品时消失($this。或者酥饼。使用超时时,将显示弹出窗口,直到通过产品退出,而不是弹出窗口。

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

使用下面的代码片段进行测试:

小修改(来自 vikas 提供的解决方案)以适应我的用例。

  1. 打开弹出窗口悬停事件的弹出窗口按钮
  2. 当悬停在泡芙盒上方时,保持泡芙打开
  3. 在鼠标离开时关闭弹出窗口按钮或弹出窗口框。

$(".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);
});
<!DOCTYPE html>
<html>


<head>
<link data-require="bootstrap-css@*" data-semver="3.2.0" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" />
<script data-require="jquery@*" data-semver="2.1.1" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script data-require="bootstrap@*" data-semver="3.2.0" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.js"></script>


<link rel="stylesheet" href="style.css" />


</head>


<body>
<h2 class='text-primary'>Another Great "KISS" Bootstrap Popover example!</h2>
<p class='text-muted'>KISS = Keep It Simple S....</p>


<p class='text-primary'>Goal:</p>
<ul>
<li>Open popover on hover event for the popover button</li>
<li>Keep popover open when hovering over the popover box</li>
<li>Close popover on mouseleave for either the popover button, or the popover box.</li>
</ul>


<button type="button" class="btn btn-danger pop" data-container="body" data-toggle="popover" data-placement="right" data-content="Optional parameter: Skip if this was not requested<br>                                    A placement group is a logical grouping of instances within a single Availability                                     Zone. Using placement groups enables applications to get the full-bisection bandwidth                                     and low-latency network performance required for tightly coupled, node-to-node                                     communication typical of HPC applications.<br>                                    This only applies to cluster compute instances: cc2.8xlarge, cg1.4xlarge, cr1.8xlarge, hi1.4xlarge and hs1.8xlarge.<br>                                    More info: <a href=&quot;http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/placement-groups.html&quot; target=&quot;_blank&quot;>Click here...</a>"
data-original-title="" title="">
HOVER OVER ME
</button>
<br><br>
<button type="button" class="btn btn-info pop" data-container="body" data-toggle="popover" data-placement="right" data-content="Optional parameter: Skip if this was not requested<br>                                    A placement group is a logical grouping of instances within a single Availability                                     Zone. Using placement groups enables applications to get the full-bisection bandwidth                                     and low-latency network performance required for tightly coupled, node-to-node                                     communication typical of HPC applications.<br>                                    This only applies to cluster compute instances: cc2.8xlarge, cg1.4xlarge, cr1.8xlarge, hi1.4xlarge and hs1.8xlarge.<br>                                    More info: <a href=&quot;http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/placement-groups.html&quot; target=&quot;_blank&quot;>Click here...</a>"
data-original-title="" title="">
HOVER OVER ME... Again!
</button><br><br>
<button type="button" class="btn btn-success pop" data-container="body" data-toggle="popover" data-placement="right" data-content="Optional parameter: Skip if this was not requested<br>                                    A placement group is a logical grouping of instances within a single Availability                                     Zone. Using placement groups enables applications to get the full-bisection bandwidth                                     and low-latency network performance required for tightly coupled, node-to-node                                     communication typical of HPC applications.<br>                                    This only applies to cluster compute instances: cc2.8xlarge, cg1.4xlarge, cr1.8xlarge, hi1.4xlarge and hs1.8xlarge.<br>                                    More info: <a href=&quot;http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/placement-groups.html&quot; target=&quot;_blank&quot;>Click here...</a>"
data-original-title="" title="">
Okay one more time... !
</button>
<br><br>
<p class='text-info'>Hope that helps you... Drove me crazy for a while</p>
<script src="script.js"></script>
</body>


</html>

工具提示也是一样:

对我来说,下面的解决方案是有效的,因为它不会在每个“ mouseenter”上添加事件侦听器,而且可以将鼠标悬停在使工具提示保持活动的工具提示元素上。

$ ->


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

Vikas 的回答对我来说是完美的,在这里我也加入了对延迟的支持(显示/隐藏)。

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

还请注意我的改动:

if (!$(".popover:hover").length) {

与:

if (popover.siblings(".popover").length && !popover.siblings(".popover").is(":hover")) {

所以它只引用那个打开的弹出窗口,而不引用其他窗口(因为现在,通过延迟,可以同时打开多于1个窗口)

这个解决办法对我来说效果很好: (现在它是防弹的) ; -)

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

我想一个简单的方法是这样的:

$('.popover').each(function () {
var $this = $(this);
$this.popover({
trigger: 'hover',
content: 'Content Here',
container: $this
})
});

这样,将在目标元素本身内部创建 popover。所以当你将鼠标移动到泡芙上时,它仍然在元素上方。Bootstrap 3.3.2可以很好地处理这个问题。旧版本的动画可能有一些问题,所以你可能要禁用“动画: 假”

选择的答案是 工程,但是如果弹出窗口以 body作为容器初始化,则会失败。

$('a').popover({ container: 'body' });

基于所选答案的解决方案是在使用 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);
});
})
}
};

使用 self.$tip而不是遍历 DOM 期望弹出窗口始终是元素的兄弟元素,这种变化是最小的。

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

我同意最好的方法是使用: David Chase、 Cu Ly 和其他人给出的方法,最简单的方法是使用 container: $(this)属性,如下所示:

$(selectorString).each(function () {
var $this = $(this);
$this.popover({
html: true,
placement: "top",
container: $this,
trigger: "hover",
title: "Popover",
content: "Hey, you hovered on element"
});
});

我想在这里指出,在这种情况下,popover 将继承当前元素 的所有属性。因此,例如,如果对 .btn元素(引导程序)执行此操作,则 您将无法选择弹出窗口内的文本。我只是想把这个录下来因为我花了很长时间研究这个。

下面是我设计的一个解决方案,它似乎工作得很好,同时还允许您使用普通的 Bootstrap 实现来打开所有弹出窗口。

原版小提琴: https://jsfiddle.net/eXpressive/hfear592/

移植到这个问题:

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

我发现 mouseleave不会在奇怪的事情发生时触发,比如窗口焦点突然变化,然后用户再回到浏览器。在这种情况下,mouseleave将永远不会触发,直到光标过去并再次离开元素。

我想到的这个解决方案依赖于 window对象上的 mouseenter,所以当鼠标在页面上移动 其他任何地方时它就会消失。

这是为了在页面上具有多个元素来触发它(比如在表中)而设计的。

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

这将是更多的 灵活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);
}
)

简单:)

$('[data-toggle="popover"]').popover( { "container":"body", "trigger":"focus", "html":true });
$('[data-toggle="popover"]').mouseenter(function(){
$(this).trigger('focus');
});

这是我的代码,用于显示带有延迟和由 ajax 加载的动态工具提示。

$(window).on('load', function () {
generatePopovers();
    

$.fn.dataTable.tables({ visible: true, api: true }).on('draw.dt', function () {
generatePopovers();
});
});


$(document).ajaxStop(function () {
generatePopovers();
});

function generatePopovers() {
var popover = $('a[href*="../Something.aspx"]'); //locate the elements to popover


popover.each(function (index) {
var poplink = $(this);
if (poplink.attr("data-toggle") == null) {
console.log("RENDER POPOVER: " + poplink.attr('href'));
poplink.attr("data-toggle", "popover");
poplink.attr("data-html", "true");
poplink.attr("data-placement", "top");
poplink.attr("data-content", "Loading...");
poplink.popover({
animation: false,
html: true,
trigger: 'manual',
container: 'body',
placement: 'top'
}).on("mouseenter", function () {
var thispoplink = poplink;
setTimeout(function () {
if (thispoplink.is(":hover")) {
thispoplink.popover("show");
loadDynamicData(thispoplink); //load data by ajax if you want
$('body .popover').on("mouseleave", function () {
thispoplink.popover('hide');
});
}
}, 1000);
}).on("mouseleave", function () {
var thispoplink = poplink;
setTimeout(function () {
if (!$("body").find(".popover:hover").length) {
thispoplink.popover("hide");
}
}, 100);
});
}
});

function loadDynamicData(popover) {
var params = new Object();
params.somedata = popover.attr("href").split("somedata=")[1]; //obtain a parameter to send
params = JSON.stringify(params);
//check if the content is not seted
if (popover.attr("data-content") == "Loading...") {
$.ajax({
type: "POST",
url: "../Default.aspx/ObtainData",
data: params,
contentType: "application/json; charset=utf-8",
dataType: 'json',
success: function (data) {
console.log(JSON.parse(data.d));
var dato = JSON.parse(data.d);
if (dato != null) {
popover.attr("data-content",dato.something); // here you can set the data returned
if (popover.is(":hover")) {
popover.popover("show"); //use this for reload the view
}
}
},


failure: function (data) {
itShowError("- Error AJAX.<br>");
}
});
}
}

我最近需要得到这个工作与 KO 和上述解决方案不工作时,有一个延迟显示和隐藏很好。下面应该解决这个问题。基于引导工具提示的工作方式。希望这对谁有帮助。

var options = {
delay: { show: 1000, hide: 50 },
trigger: 'manual',
html: true
};
var $popover = $(element).popover(options);


$popover.on('mouseenter', function () { // This is entering the triggering element
var self = this;


clearTimeout(self.timeout);
self.hoverState = 'in';


self.timeout = setTimeout(function () {
if (self.hoverState == 'in') {
$(self).popover("show");


$(".popover, .popover *").on('mouseover', function () { // This is moving over the popover
clearTimeout(self.timeout);
});


$(".popover").on('mouseleave', function () { // This is leaving the popover
self.timeout = setTimeout(function () {
if (self.hoverState == 'out') {
$(self).popover('hide');
}
}, options.delay.hide);
});
}
}, options.delay.show);
}).on('mouseleave', function (event) { // This is leaving the triggering element
var self = this;


clearTimeout(self.timeout);
self.hoverState = 'out';


self.timeout = setTimeout(function () {
if (self.hoverState == 'out') {
$(self).popover('hide');
}


}, options.delay.hide);
});

我发现公认的答案和类似的答案都有一些缺陷。主要是它反复地向元素添加鼠标离开侦听器。

我已经将他们的解决方案与一些自定义代码结合起来,以实现有问题的功能,而不会出现内存泄漏或侦听器膨胀。

    var getPopoverTimeout = function ($el) {
return $el.data('timeout');
}
$element.popover({
trigger: "manual",
html: true,
content: ...,
title: ...,
container: $element
}).on("mouseenter", function () {
var $this = $(this);
if (!$this.find('.popover').length) {
$this.popover("show");
} else if (getPopoverTimeout($element)) {
clearTimeout(getPopoverTimeout($element));
}
}).on("mouseleave", function () {
var $this = $(this);
$element.data('timeout', setTimeout(function () {
if (!$(".popover:hover").length) {
$this.popover("hide")
}
}, 250));
});

它提供了一个不错的“悬停意图”之类的解决方案,这样它就不会闪进闪出。

我知道我有点迟到了,但我正在寻找一个解决办法。.然后我碰到了这个帖子。这是我对此的看法,也许它会对你们中的一些人有所帮助。

Html 部分:

<button type="button" class="btn btn-lg btn-danger" data-content="test" data-placement="right" data-toggle="popover" title="Popover title" >Hover to toggle popover</button><br>
// with custom html stored in a separate element, using "data-target"
<button type="button" class="btn btn-lg btn-danger" data-target="#custom-html" data-placement="right" data-toggle="popover" >Hover to toggle popover</button>


<div id="custom-html" style="display: none;">
<strong>Helloooo!!</strong>
</div>

Js 部分:

$(function () {
let popover = '[data-toggle="popover"]';


let popoverId = function(element) {
return $(element).popover().data('bs.popover').tip.id;
}


$(popover).popover({
trigger: 'manual',
html: true,
animation: false
})
.on('show.bs.popover', function() {
// hide all other popovers
$(popover).popover("hide");
})
.on("mouseenter", function() {
// add custom html from element
let target = $(this).data('target');
$(this).popover().data('bs.popover').config.content = $(target).html();


// show the popover
$(this).popover("show");
            

$('#' + popoverId(this)).on("mouseleave", () => {
$(this).popover("hide");
});


}).on("mouseleave", function() {
setTimeout(() => {
if (!$("#" + popoverId(this) + ":hover").length) {
$(this).popover("hide");
}
}, 100);
});
})

这是 Bootstrap 5的一个解决方案

let el = document.getElementById('poptest');
let popover = new bootstrap.Popover(el, { delay: { show: 0, hide: 500 }});


el.addEventListener('shown.bs.popover', function(ev) {
let oldHandler = popover.hide, pel = $(popover.tip);
pel.on('mouseenter', () => popover.hide = () => 1);
pel.on('mouseleave', () => {
popover.hide = oldHandler;
popover.hide();
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.10.2/dist/umd/popper.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/js/bootstrap.bundle.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/css/bootstrap.min.css" rel="stylesheet"/>


<button type="button" class="btn btn-secondary m-5" data-bs-trigger="hover" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="bottom" data-bs-content="Hover here and it won't close!" id="poptest">
Popover on top
</button>

这个概念是我们覆盖 mouseenter上的 hide函数,所以它不会自动关闭,然后在 mouseleave上恢复它。