【问题标题】:How can I hold Twitter Bootstrap Popover open until my mouse moves into it?如何在鼠标移入之前保持 Twitter Bootstrap Popover 打开?
【发布时间】:2011-12-03 23:16:26
【问题描述】:

我有一个使用Twitter Bootstrap Popover version 1.3.0 显示一些信息的链接。此信息包含一个链接,但每次我将鼠标从链接移到弹出框时,弹出框就会消失。

我怎样才能使弹出框保持打开足够长的时间以使鼠标能够移动到其中?那么当鼠标移出链接和popover时,隐藏它呢?

或者有没有其他插件可以做到这一点?

【问题讨论】:

  • 我知道您已经解决了您的问题,但为了对未来的读者有所帮助,请发布一些相关代码以便有意义。
  • 有您的问题吗?我在问题中没有看到任何代码。
  • 我不是在谈论您答案中的代码...我是在谈论在您上面的问题中添加一些更有意义的东西。本网站是为了未来的读者和您自己的利益。您的问题应该以合理的方式进行格式化,以便有人知道您的意思并可能弄明白。
  • 我为您的问题添加了一个链接,因此至少读者知道您在说什么插件。

标签: javascript jquery twitter-bootstrap twitter-bootstrap-3 popover


【解决方案1】:

使用引导程序(使用版本 2 测试)我想出了以下代码:

$("a[rel=popover]")
            .popover({
                offset: 10,
                trigger: 'manual',
                animate: false,
                html: true,
                placement: 'left',
                template: '<div class="popover" onmouseover="$(this).mouseleave(function() {$(this).hide(); });"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'

            }).click(function(e) {
                e.preventDefault() ;
            }).mouseenter(function(e) {
                $(this).popover('show');
            });

重点是用 mouseleave() 启用程序覆盖模板。我希望这会有所帮助。

【讨论】:

  • 这对我有用。我希望这个功能内置得更好,这样你就不必传递这个冗长的“模板”选项。 twitter.github.com/bootstrap/javascript.html#popovers 甚至没有记录“模板”选项。
  • 有效,但如果您离开触发弹出框的容器,它会一直留在那里,直到您将鼠标悬停在弹出框本身为止。
  • 可能被最新版本的引导程序破坏了
  • 无法在 Bootstrap 3.0.0 及更高版本中正常工作。我发布的解决方案适用于 Bootstrap 3.0.0 及更高版本,并且非常易于设置。看看HERE
  • 我在谷歌上搜索弹出框闪烁,我唯一错过的是offset: 10。谢谢。
【解决方案2】:

Bootstrap 3 及以上

简单,只需使用container 选项并将其作为调用弹出框的元素。这样,弹出框是调用它的元素的子元素。因此,从技术上讲,您仍然将鼠标悬停在父级上,因为子弹出框属于它。

例如:

HTML:

<div class="pop" data-content="Testing 12345">This has a popover</div>
<div class="pop" data-content="Testing 12345">This has a popover</div>
<div class="pop" data-content="Testing 12345">This has a popover</div>

jQuery:

在我希望将弹出框绑定到其父级的每个元素上运行$.each() 循环。在这种情况下,每个元素都有pop 的类。

$('.pop').each(function () {
    var $elem = $(this);
    $elem.popover({
        placement: 'top',
        trigger: 'hover',
        html: true,
        container: $elem
    });
});

CSS:

这部分是可选的,但推荐。它将弹出框向下移动 7 个像素以便于访问。

.pop .popover {
    margin-top:7px;
}

WORKING DEMO

【讨论】:

  • 迄今为止最简单的解决方案。谢谢!
  • 通过将其绑定到元素,弹出框将被元素的父级溢出规则绑定。这意味着如果它超出界限并且溢出不是“可见”,那么用户将需要滚动才能查看弹出框,这非常令人不快。只要您的弹出框不大或父元素不限制其溢出,此方法就可以。
  • @casey - 你是绝对正确的。在这种情况下,他们将需要使用手动触发器。虽然,看不到这种情况经常发生。使用这个解决方案已经有一段时间了,从来不需要使用手动触发器。
  • 非常优雅。非常有效。很好的答案。
  • 谢谢@RobinvanBaalen :)
【解决方案3】:

添加到 Marchello 的示例中,如果您希望在用户将鼠标从弹出框 and 源链接上移开时弹出框消失,请尝试一下。

var timeoutObj;
$('.nav_item a').popover({
    offset: 10,
    trigger: 'manual',
    html: true,
    placement: 'right',
    template: '<div class="popover" onmouseover="clearTimeout(timeoutObj);$(this).mouseleave(function() {$(this).hide();});"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'
}).mouseenter(function(e) {
    $(this).popover('show');
}).mouseleave(function(e) {
    var ref = $(this);
    timeoutObj = setTimeout(function(){
        ref.popover('hide');
    }, 50);
});

【讨论】:

  • 这非常有效。您可以直接在data 属性的 html 中添加偏移量、触发器、html 和位置,而不是在 javascript 中为每个弹出窗口设置选项。
  • 为什么在进入弹出框时出现错误提示“未定义 timeoutObj”
  • 您使用的是什么版本的 bootstrap/jquery?您是否逐字复制代码?如果没有,请粘贴您的代码,我可以尝试提供帮助。
  • 谢谢!在​​ v2.3.2 上为我工作。
  • 对我来说在 2.3.2 上也很好用。谢谢。
【解决方案4】:

这有点 hacky,但是基于 Marchello 的示例,我做了这个(不需要模板):

$(".trigger-link").popover({
  trigger: "manual",
}).on("click", function(e) {
  e.preventDefault();
}).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);
});

setTimeout 有助于确保有时间从触发链接移动到弹出框。

【讨论】:

  • 谢谢。我尝试了此页面上的所有答案,而您的答案是唯一有效的。你太棒了。
  • 真的很喜欢你的解决方案!我使用的是$this.data('popover').tip() 而不是$(this).siblings(".popover"),但感觉和你的方法一样笨拙:)。带有悬停选择器的 setTimeout 函数非常智能!
  • 最好用$(_this).popover('hide');替换$(this).hide();
  • 在无休止的谷歌搜索之后,这让我很开心。谢谢@clem
  • @lacco 我如何使用 $this.data('popover').tip() ?
【解决方案5】:

This issue on the bootstrap github repo 处理这个问题。 fat 指出了实验性的“上/下/左/右”位置。它工作得很好,但你必须确保弹出框触发器不是用 css 静态定位的。否则弹出框不会出现在您想要的位置。

HTML:

&lt;span class="myClass" data-content="lorem ipsum content" data-original-title="pop-title"&gt;Hover me to show a popover.&lt;/span&gt;

CSS:

/*CSS */
.myClass{ position: relative;}

JS:

$(function(){
  $('.myClass').popover({placement: 'in top'});
});  

【讨论】:

  • 为我工作!在 Chrome 和 Firefox 上测试。但是,我对弹出框内容的显示方式有些不一致,因为胖子在问题的评论之一中发出警告
  • 太棒了,这对我有用,谢谢 - 这几乎和内置一样整洁:)
  • 如果您正在寻找包含更多自定义功能的 bootstrap 弹出框替代方案,请查看stevenbenner.github.com/jquery-powertip
【解决方案6】:

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

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

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

如果鼠标进入弹出框,计时器将被清除。然后它会在弹出框上监听mouseleave,如果它被触发,它会调用原始的离开函数,以便它可以开始隐藏计时器。

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

【讨论】:

  • 请注意,此解决方案至少需要 Bootstrap 版本 3。
  • 如果您使用container 选项,这将不起作用。我已经在我的 fork 中解决了这个问题:jsfiddle.net/5p7g4j22/1
  • 我喜欢这个解决方案,但是这条线做了什么: var self = obj instanceof this.constructor ? obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
【解决方案7】:

解决方案适用于 Bootstrap 3。

var timeoutObj;
$('.list-group a').popover({
    offset: 10,
    trigger: 'manual',
    html: true,
    placement: 'right',
    template: '<div class="popover" onmouseover="$(this).mouseleave(function() {$(this).hide();});"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'
}).mouseenter(function(e) {
    $(this).popover('show');
}).mouseleave(function(e) {
    var _this = this;
    setTimeout(function() {
        if (!$(".popover:hover").length) {
            $(_this).popover("hide");
        }
    }, 100);
}); 

【讨论】:

  • 效果很好。虽然,当您的鼠标离开弹出框时,它不会消失。当您的鼠标离开触发器时,它会逐渐消失。只是一个小错误。
【解决方案8】:

最后我解决了这个问题。 Popover消失是因为Popover不是link的子节点,是body的子节点。

所以修复它很容易,更改bootstrap-twipsy.js内容:

.prependTo(document.body) 更改为.prependTo(this.$element)

并修复因变化引起的位置问题。

还有一些使用link的tiger popover也会导致popover with link,所以添加一个span contains link,问题就解决了。

【讨论】:

  • 这可行,尽管存在一些问题:1 样式是从目标继承的 2. 定位是顶栏中的错误元素(我怀疑它与浮动有关)
  • 所以我说“由变化引起的定位问题。”。
  • 如何解决位置问题?它在 Chrome/Safari 中似乎可以正常工作,但在 Firefox 中却不行(即弹出框的位置在 Firefox 中不好)。
  • 如果您使用的是一个简单的站点,这个解决方案非常棒。如果您在页面上使用 z-index 有一个复杂的布局和其他元素,那么如果您将工具提示附加到元素并且页面上有另一个元素破坏了 z-index,那么您很快就会遇到一些大的 z-index 问题堆叠。
  • 请注意:从 Bootstrap 2.3.0 版开始,您可以定义 Popover 附加到的容器 (twitter.github.com/bootstrap/javascript.html#popovers)。因此,Tinyfool 建议的代码不再需要了。但是,在将其附加到 Anchor 元素本身的情况下,整个 Popover 及其内容变成了超链接。
【解决方案9】:

这是 Wojtek Kruszewski 解决方案的一个版本。此版本在鼠标返回触发时处理弹出框闪烁。 http://jsfiddle.net/danielgatis/QtcpD/

(function($) {
      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) {
          var current = $(obj.currentTarget);
          var container = current.siblings(".popover");
          container.on("mouseenter", function() {
            clearTimeout(self.timeout);
          });
          container.on("mouseleave", function() {
            originalLeave.call(self, self);
          });
        }
      };

      var originalEnter = $.fn.popover.Constructor.prototype.enter;
      $.fn.popover.Constructor.prototype.enter = function(obj) {
        var self = (obj instanceof this.constructor ? obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data("bs." + this.type));
        clearTimeout(self.timeout);
        if (!$(obj.currentTarget).siblings(".popover:visible").length) {
          originalEnter.call(this, obj);
        }
      };
    })(jQuery);

【讨论】:

  • 请注意,此解决方案至少需要 Bootstrap 版本 3。
【解决方案10】:

我尝试了@Wotjek Kruszewski 和@danielgatis 的解决方案,但都没有为我工作。警告:我使用的是 Bootstrap v2.1.0,而不是 v3。这个解决方案在coffeescript中(为什么人们还在使用纯javascript?=))。

(($) ->
  originalLeave = $.fn.popover.Constructor::leave
  $.fn.popover.Constructor::leave = (e) ->
    self = $(e.currentTarget)[@type](@_options).data(@type)
    originalLeave.call @, e

    if e.currentTarget
      container = $(".popover")
      container.one "mouseenter", ->
        clearTimeout self.timeout

        container.one "mouseleave", ->
          originalLeave.call self, e
) jQuery

【讨论】:

  • 在 2.3.2 中也可以完美运行,尽管我添加了 off('mouseenter') 以避免在显示和隐藏弹出框而不在其中移动鼠标时使用多个处理程序。
【解决方案11】:

这是我所做的:

e = $("a[rel=popover]")
e.popover({
    content: d, 
    html:true, 
    trigger:'hover',
    delay: {hide: 500},
    placement: 'bottom',
    container: e, 
})

对于这个问题,这是一个非常简单且很棒的解决方案,我通过查看引导工具提示代码发现了这一点。在 Bootstrap v3.0.3 中,这是我注意到的代码行:

this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)

这表示如果定义了 popover 的 container 属性,则 popover 将获取 appendTo() 元素而不是 insertAfter() 原始元素,您只需将元素作为容器属性传递即可。由于 appendTo(),弹出框成为绑定悬停事件的链接的一部分,因此当鼠标移动时,弹出框保持打开状态。

【讨论】:

  • 完美的解决方法,并且没有任何错误的黑客攻击。干得好,+1。
【解决方案12】:

这适用于 BootStrap 3

el.popover({
  delay: {hide: 100}
}).on("shown.bs.popover", function(){
  el.data("bs.popover").tip().off("mouseleave").on("mouseleave", function(){
    setTimeout(function(){
      el.popover("hide");
    }, 100);
  });
}).on("hide.bs.popover", function(ev){
  if(el.data("bs.popover").tip().is(":hover"))
    ev.preventDefault();
});

【讨论】:

    【解决方案13】:

    @stevendaniels 链接的对话末尾是一个指向 Twitter Bootstrap 扩展程序的链接,名为 BootstrapX - clickover Lee Carmichael。这会将弹出框从过大的工具提示更改为交互式控件,可以通过单击表单上的其他位置、关闭按钮或超时后关闭。它易于使用,并且非常适合我需要的项目。可以在here 找到一些使用示例。

    【讨论】:

      【解决方案14】:

      我不喜欢我找到的任何答案,所以我结合了一些接近的答案来制作以下代码。它允许您每次想要制作“可固定”弹出框时只需输入$(selector).pinnablepopover(options);

      让事情变得简单的代码:

      $.fn.popoverHoverShow = function ()
      {
          if(this.data('state') !== 'pinned')
          {
              if(!this.data('bs.popover').$tip || (this.data('bs.popover').$tip && this.data('bs.popover').$tip.is(':hidden')))
              {
                  this.popover('show');
              }
          }
      };
      $.fn.popoverHoverHide = function ()
      {
          if (this.data('state') !== 'pinned')
          {
              var ref = this;
              this.data('bs.popover').$tip.data('timeout', setTimeout(function(){ ref.popover('hide') }, 100))
              .on('mouseenter', function(){ clearTimeout($(this).data('timeout')) })
              .on('mouseleave', function(){ $(this).data('timeout', setTimeout(function(){ ref.popover('hide') }, 100)) });
              this.on('mouseenter', function(){ clearTimeout($(this).data('timeout')) });
          }
      };
      $.fn.popoverClickToggle = function ()
      {
          if (this.data('state') !== 'pinned')
          {
              this.data('state', 'pinned');
          }
          else
          {
              this.data('state', 'hover')
          }
      };
      $.fn.pinnablepopover = function (options)
      {
          options.trigger = manual;
          this.popover(options)
          .on('mouseenter', function(){ $(this).popoverHoverShow() })
          .on('mouseleave', function(){ $(this).popoverHoverHide() })
          .on('click', function(){ $(this).popoverClickToggle() });
      };
      

      示例用法:

      $('[data-toggle=popover]').pinnablepopover({html: true, container: 'body'});
      

      【讨论】:

        【解决方案15】:

        看到我所做的所有答案后,我认为这会有所帮助。您可以管理所需的一切。 许多答案不会使我使用它的显示延迟。它在我的项目中工作得非常好
        /****** /************************************************* ************/

        <div class='thumbnail' data-original-title=''  style='width:50%'>    
         <div id='item_details' class='popper-content hide'>
            <div>
                <div style='height:10px'> </div>
                <div class='title'>Bad blood </div>
                <div class='catagory'>Music </div>
            </div>
        
          </div>
          HELLO POPOVER
        </div>"
        

        /****************脚本代码 ****************** 请从听到使用 ****** /

        $(".thumbnail").popover({
        trigger: "manual" ,
        html: true,
        animation:true,
        container: 'body',
        placement: 'auto right',
        content: function () {
            return $(this).children('.popper-content').html();
        }}) .on("mouseenter", function () {
        var _this = this;
        
        $('.thumbnail').each(function () {
            $(this).popover('hide');
        });
        setTimeout(function(){
            if ($(_this).is(':hover')) {
                $(_this).popover("show");
            }
        },1000);
        $(".popover").on("mouseleave", function () {
            $('.thumbnail').each(function () {
                $(this).popover('hide');
            });
            $(_this).popover('hide');
         }); }).on("mouseleave", function () {
            var _this = this;
            setTimeout(function () {
                if (!$(".popover:hover").length) {
                    $(_this).popover("hide");
                }
            }, 100); });
        

        【讨论】:

          【解决方案16】:

          现在我只是切换到 webuiPopover,它就可以工作了。

          【讨论】:

          • 对不起,但即使那是您最终决定的方式也不是您提出的问题的解决方案,并且在甚至没有使用引导程序来解决问题时将您自己的答案标记为正确的答案,至少有这篇文章中的 3 个解决方案真正解决了问题......
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-09-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多