如果与Prototype JS一起使用,Popover会隐藏父元素

时间:2013-02-26 10:48:26

标签: jquery twitter-bootstrap prototypejs popover

更新到bootstrap 2.3.0后,我注意到了popover工具提示的奇怪行为。

如果您进入该字段并尝试离开,工具提示将消失并隐藏输入字段。此问题仅在最新版本的bootstrap中出现,不确定究竟是什么更改,但2.2.2适用于Prototype。

jQuery.noConflict();
jQuery('input[data-content]').popover({
    trigger: 'focus'
});

以下是工作示例:http://jsfiddle.net/U6EDs/4/

8 个答案:

答案 0 :(得分:22)

这个github问题https://github.com/twitter/bootstrap/issues/6921描述了你所看到的。我正在复制问题中的信息。

bootstrap-tooltip.js中的这些行导致了问题:

  , hide: function () {
  var that = this
    , $tip = this.tip()
    , e = $.Event('hide')   ///this line

  this.$element.trigger(e)  /// this line
  if (e.isDefaultPrevented()) return //and this line 

PrototypeJS向Element原型添加方法,所以当jQuery尝试触发元素上的hide()方法时,它实际上触发了PrototypeJS hide()方法,这相当于jQuery hide()方法并将元素的样式设置为display:none;

您有几个选择

  1. 删除js文件中上面标记的行
  2. 将事件重命名为其他内容(不隐藏)
  3. 使用BootStrap的PrototypeJS分支(目前适用于2.3.2)
  4. http://github.com/jwestbrook/bootstrap-prototype

    ***** ***声明

    我是开发人员,目前正在将BootStrap JS组件移植到PrototypeJS

答案 1 :(得分:5)

我知道这是一个老问题,但我刚刚遇到这个(再次),上面的答案对我不起作用。我最终找到了一个没有入侵任何库的解决方案。想法是在隐藏元素后显示元素。没有闪烁,效果很好。

jQuery(function () {
    jQuery.noConflict();
        jQuery('input[data-content]').popover({
            trigger: 'focus'
        }).on('hidden.bs.popover', function(){
            jQuery(this).show();
        });
});

您可以对工具提示使用相同的技巧,只需使用on('hidden.bs.tooltip'), ...

即可

注意,我在大多数个人测试中都使用Bootstrap 3.0.0。这是使用BS 2.3的问题的更新小提琴: http://jsfiddle.net/calypsonian/U6EDs/13/

答案 2 :(得分:5)

我花了一些时间研究这个。

这就是它发生的原因。

Prototype的策略是扩展 DOM元素类的新行为,例如' hide'。相当于:

HTMLElement.prototype.hide = function(...) {...};

jQuery假设如果一个元素具有与事件同名的函数,那么当该事件被触发时,它被认为是该元素的默认行为。例如,这对于事件'焦点'模糊'等是有用的,其中存在由该名称引起的事件'焦点'以及元素.focus()上的匹配函数。当您致电jQuery' event.preventDefault()时,它实际上并非阻止默认行为。相反,它是相反的 - 如果你调用event.preventDefault(),那么jQuery会查找与事件同名的函数,然后调用它。存在。

这里是jQuery src手动调用"默认行为"功能: https://github.com/jquery/jquery/blob/d837f119c3729565103005d5d7fa89e1dd8110cb/src/event.js#L338

因此,我们遇到了问题。 Prototype使用新功能扩展了基础HTMLElement原型(即' hide')。当触发同名事件时,jQuery认为这些函数是默认行为。 Bootstrap的JS会触发一个同名的事件(' hide'),这会错误地导致jQuery调用Prototype的Element.hide()函数。

我将根据这些信息研究解决方案。可能有以下几点:

jQuery(window).load(function() {
    // Defer this code until after the window 'load' event finishes firing
    setTimeout(function() {
        window.HTMLElement &&
        window.HTMLElement.prototype.hide &&
        delete window.HTMLElement.prototype.hide;
    }, 0);
});

答案 3 :(得分:2)

对我来说,更好(不改变Bootstrap源代码)是为了防止事件并手动删除隐藏工具提示的“in”类:

jQuery("input").on('hide.bs.tooltip', function(e) {
    e.preventDefault();
    $("div.tooltip.in").removeClass('in');

});

唯一的问题是它阻止了“hidden.bs.tooltip”事件的触发。但如果您不介意,我建议使用此解决方案,因为它不会导致闪烁

答案 4 :(得分:2)

您可以在mouseleave事件上再次显示,例如

jQuery(function(){  
    jQuery('[data-toggle="popover"]').popover().on('mouseleave',function(){
       $(this).show(0); // show it again when mouse leave event fires
    });
});

<强> Live Demo

答案 5 :(得分:1)

我添加了一个重要的CSS样式来覆盖原型添加的元素样式。这对我有用,因为没有任何东西可以隐藏元素。

#elemId{
  display: block!important; /* or whatever the original display was */
}

答案 6 :(得分:0)

通过以这种方式编辑Bootstrap JS来“修复”错误:
(注释掉this.$element.trigger(e)行)

, hide: function () {
  var that = this
    , $tip = this.tip()
    , e = $.Event('hide')

  this.$tip.trigger(e)
//this.$element.trigger(e)
  if (e.isDefaultPrevented()) return

答案 7 :(得分:0)

一种可能的解决方案是始终通过CSS显示元素。

[data-toggle=tooltip] {
    display: block!important;
}