jQuery 如何在悬停时保持 Bootstrap 弹出窗口的活动状态?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15989591/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 16:09:09  来源:igfitidea点击:

How can I keep Bootstrap popovers alive while being hovered?

jquerytwitter-bootstrappopper.js

提问by vikas devde

I am using a Bootstrap popover to create a hover card showing user info, and I am triggering it on mouseover of a button. I want to keep this popover alive while the popover itself is being hovered, but it disappears as soon as the user stops hovering over the button. How can I do this?

我正在使用 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>

采纳答案by vikas devde

I have came after another solution to this...here is the code

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

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

回答by OkezieE

View this working code in Plunker

在 Plunker 中查看此工作代码

Small modification (From the solution provided by vikas) to suit my use case.
1. Open popover on hover event for the popover button
2. Keep popover open when hovering over the popover box
3. Close popover on mouseleave for either the popover button, or the popover box.

小修改(来自 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);
});

Play with it in Plunker

在 Plunker 中使用它

回答by Wojtek Kruszewski

Here's my take: http://jsfiddle.net/WojtekKruszewski/Zf3m7/22/

这是我的看法:http: //jsfiddle.net/WojtekKruszewski/Zf3m7/22/

Sometimes while moving mouse from popover trigger to actual popover content diagonally, you hover over elements below. I wanted to handle such situations – as long as you reach popover content before the timeout fires, you're safe (the popover won't disappear). It requires delayoption.

有时,将鼠标从弹出框触发器斜向移动到实际弹出框内容时,您将鼠标悬停在下面的元素上。我想处理这种情况——只要你在超时触发之前到达弹出框内容,你就是安全的(弹出框不会消失)。它需要delay选项。

This hack basically overrides Popover leavefunction, but calls the original (which starts timer to hide the popover). Then it attaches a one-off listener to mouseenterpopover content element's.

这个 hack 基本上覆盖了 Popoverleave函数,但调用了原始函数(它启动计时器以隐藏 popover)。然后它将一次性侦听器附加到mouseenter弹出内容元素的。

If mouse enters the popover, the timer is cleared. Then it turns it listens to mouseleaveon popover and if it's triggered, it calls the original leave function so that it could start hide timer.

如果鼠标进入弹出窗口,则计时器被清除。然后它会mouseleave在 popover 上监听,如果它被触发,它会调用原始的 leave 函数,以便它可以启动隐藏计时器。

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

回答by David Chase

I used the trigger set to hoverand gave the container set to the #elementand finally adding a placement of the boxto right.

我使用触发器设置为hover并将容器设置为#element,最后添加了boxto的位置right

This should be your setup:

这应该是您的设置:

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

and #examplecss needs position:relative;check the jsfiddle below:

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

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

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

Edited

已编辑

This fiddle has both links that work with no problems http://jsfiddle.net/davidchase03/FQE57/4/

这个小提琴有两个链接都可以正常工作 http://jsfiddle.net/davidchase03/FQE57/4/

回答by Cu Ly

I think an easy way would be this:

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

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

This way the popover is created inside the target element itself. so when you move your mouse over the popover, it's still over the element. Bootstrap 3.3.2 works well with this. Older version may have some problems with animation, so you may want to disable "animation:false"

通过这种方式,在目标元素本身内部创建了弹出窗口。所以当你将鼠标移到 popover 上时,它仍然在元素上。Bootstrap 3.3.2 可以很好地处理这个问题。旧版本的动画可能存在一些问题,因此您可能需要禁用“animation:false”

回答by hoektoe

This is how I did with bootstrap popover with help of other bits around the net. Dynamically gets the title and content from die various products displayed on site. Each product or popover gets unique id. Popover will disappear when exiting the product( $this .pop) or the popover. Timeout is used where will display the popover until exit through product instead of popover.

这就是我在网络上其他位的帮助下使用 bootstrap popover 的方式。从网站上展示的各种产品中动态获取标题和内容。每个产品或弹出框都有唯一的 ID。退出产品( $this .pop )或弹出框时,弹出框会消失。超时用于显示弹出窗口,直到通过产品而不是弹出窗口退出。

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

回答by eXpressiveDesign

Here is a solution I devised that seems to work well while also allowing you to use the normal Bootstrap implementation for turning on all popovers.

这是我设计的一个解决方案,它似乎运行良好,同时还允许您使用正常的 Bootstrap 实现来打开所有弹出窗口。

Original fiddle: https://jsfiddle.net/eXpressive/hfear592/

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

Ported to this question:

移植到这个问题:

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

回答by forumulator

I agree that the best way is to use the one given by: David Chase, Cu Ly, and others that the simplest way to do this is to use the container: $(this)property as follows:

我同意最好的方法是使用由David Chase、Cu Ly 和其他人提供的方法,最简单的方法是使用以下container: $(this)属性:

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

I want to point out here that the popover in this case will inherit all properties of the current element. So, for example, if you do this for a .btnelement(bootstrap), you won't be able to select text inside the popover. Just wanted to record that since I spent quite some time banging my head on this.

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

回答by Rubens Mariuzzo

The chosen answer worksbut will fail if the popover is initialized with the bodyas the container.

所选择的答案有效,但如果弹出窗口使用body容器初始化,则会失败。

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

A solution based on the chosen answer is the following code that needs to be placed before using the 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);
            });
        })
    }
};

The change is minimal using self.$tipinstead of traversing the DOM expecting the popover to be always a siblings of the element.

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

回答by user1993198

Vikas answer works perfectly for me, here I also add support for the delay (show / hide).

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

Also please pay attention I changed:

另外请注意我改变了:

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

with:

和:

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

so that it references exactly at that opened popover, and not any other (since now, through the delay, more than 1 could be open at the same time)

以便它准确引用打开的弹出窗口,而不是其他任何弹出窗口(从现在开始,通过延迟,可以同时打开 1 个以上)