当popover徘徊时,我怎样才能保持bootstrap popover活着?

时间:2013-04-13 15:42:25

标签: jquery twitter-bootstrap popover onhover

我正在使用twitter boostrap的popover来创建一个用于显示用户信息的悬停卡,并且我在鼠标悬停检查时触发了popover jsfiddle here 。我希望在它被徘徊时保持这个popover活着。

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

你可以想到facebook悬停卡的工作。我想以同样的方式。我怎么能这样做?

20 个答案:

答案 0 :(得分:148)

  

View this working code in Plunker

小修改(来自vikas提供的解决方案)以适应我的用例。
1.在弹出按钮的悬停事件上打开弹出窗口 2.将鼠标悬停在弹出框上时保持弹出打开 3.关闭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);
});

Play with it in Plunker

答案 1 :(得分:78)

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

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

答案 2 :(得分:28)

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

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

这个hack基本上覆盖了Popover leave函数,但调用了原始函数(启动计时器来隐藏弹出窗口)。然后它将一次性监听器附加到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);
      });
    })
  }
};

答案 3 :(得分:12)

我使用了设置为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/

答案 4 :(得分:9)

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

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

这样,popover就会在target元素本身内创建。所以当你将鼠标移到弹出窗口上时,它仍然在元素上方。 Bootstrap 3.3.2适用于此。旧版本可能在动画方面存在一些问题,因此您可能需要禁用“animation:false”

答案 5 :(得分:7)

这就是我在网络上的其他位的帮助下使用bootstrap popover的方式。动态获取网站上显示的各种产品的标题和内容。每个产品或popover都有唯一的ID。当退出产品($ this .pop)或popover时,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();
    };

答案 6 :(得分:4)

这是我设计的解决方案似乎运行良好,同时还允许您使用正常的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');
});

答案 7 :(得分:1)

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")) {

这样它就可以准确地引用那个打开的popover,而不是任何其他的(从现在开始,通过延迟,可以同时打开多于1个)

答案 8 :(得分:1)

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

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

基于所选答案的解决方案是在使用弹出窗口之前需要放置的以下代码。

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,期望popover始终是元素的兄弟。

答案 9 :(得分:1)

我同意最好的方法是使用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"
  });
);

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

答案 10 :(得分:1)

简单:)

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

答案 11 :(得分:0)

我知道我参加聚会有点晚了,但是我正在寻找解决方案,所以我碰到了这个职位。这是我的看法,也许会对您有所帮助。

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

答案 12 :(得分:0)

我发现公认的答案和与之相似的答案都有一些缺陷。主要是它反复将mouseleave侦听器添加到元素中。

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

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

哪个提供了很好的“悬浮意图”之类的解决方案,以使其不会闪烁进出。

答案 13 :(得分:0)

我最近需要与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);
});

答案 14 :(得分:0)

这是我的用于显示动态工具提示的代码,该提示具有延迟并由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>");
            }
        });
    }
}

答案 15 :(得分:0)

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

答案 16 :(得分:0)

我发现mouseleave在发生奇怪的事情时不会触发,就像窗口焦点突然改变一样,然后用户回到浏览器。在这种情况下,mouseleave将永远不会触发,直到光标结束并再次离开该元素。

我提出的这个解决方案依赖于mouseenter对象上的window,因此当鼠标移动到页面上其他地方时,它就会消失。

这是为了在页面上有多个元素来触发它(就像在表格中一样)。

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

答案 17 :(得分:0)

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

答案 18 :(得分:0)

这个解决方案对我很好:(现在它的防弹); - )

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

答案 19 :(得分:0)

工具提示相同:

对于我来说,以下解决方案是有效的,因为它不会在每个'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