bootstrap tooltip \ popover - 解决左侧不一致的位置

时间:2014-07-15 14:08:02

标签: javascript jquery css twitter-bootstrap twitter-bootstrap-tooltip

我一直在研究一个项目,并且我注意到我想要解决的bootstrap行为的一些不一致。

当弹出窗口(或工具提示,无论如何,它们基本相同)接近屏幕边缘时 - 如果它是右侧的,当接近边缘时 - 它会收缩,所以不要离屏(它只能起作用,但通常就足够了)。

当展示位置在左侧时,不会发生这种情况。

即:

正确展示位置

正常宽度:

enter image description here

靠近边缘:

enter image description here

左侧展示位置:

正常宽度:

enter image description here

靠近边缘:

enter image description here

这些图片来自我写的一个小DEMO来说明问题。

我已经搞乱了源代码,到目前为止无济于事。我似乎无法首先指出究竟是什么导致了这种行为。

有什么想法吗?

P.S。

我使用的是Bootstrap 3.1.1。新的3.2确实解决了这个问题(我现在想避免升级)。


重大更新!

经过一番挖掘后,我发现这与bootstrap无关 - 它的简单css - 似乎当你绝对定位一个元素并将它推到两侧时它会尝试并保持屏幕状态

我从来不知道这种行为,它会自动发生 - 但仅限于你正在推动的方向 - 即从左侧推出的div将在到达屏幕的右边缘时收缩,反之亦然。

恰好,弹出窗口仅定位left分配 - 这就是为什么我们会看到不一致的行为 - 当它被推到右边时它会收缩而不是另一个方向。

所以解决方法是分配right - 听起来很简单? 没那么多。我拿了源代码并稍微操纵了它,adding these lines(jsfiddle中某处的第250行):

if (placement == 'left' && offset.left < 0) {
    var right = ( $(window).width() + 10 ) - ( offset.left + actualWidth ); 

    offset.left = 0;
    $tip.offset(offset);
    $tip.css({ 'right': right });
}

似乎合理,对吧?如果左边的偏移量小于0(即,它偏离屏幕),那么计算窗口宽度并从中移除左边距偏移和弹出窗口的宽度(actualWidth)本身,你得到的距离是右。

然后,确保重置左偏移并应用正确的定位。 但是 ......它只能起作用 - 也就是说它只能在第二次使用。

查看for yourself!将鼠标悬停一次,将其放错位置,将鼠标拉到一边再试一次,然后突然将其正确定位。怎么了?

修改

好的,这似乎出现了很多,所以我会说清楚:

我知道auto展示位置。我不想要它。 我想控制popover的位置,让它自动决定不是问题的解决方案,它只是避免它

3 个答案:

答案 0 :(得分:1)

好的,我已经离得更近了。

在css中分配right后,actualWidthactualHeight会发生变化,因此您需要更新这些变量。在你的jsfiddle的第253行附近:

if (placement == 'left' && offset.left < 0) {
    var right = (  $(window).width() + 10) - ( offset.left + actualWidth ); 

    offset.left = 0;
    $tip.offset(offset);
    $tip.css({ 'right': right });
    actualWidth  = $tip[0].offsetWidth;
    actualHeight = $tip[0].offsetHeight;
}

这是您第一次悬停时的效果,但每次在此之后,它会将top设置得太高,因此您无法读取工具提示的顶部。

更新: 似乎设置right值会使applyPlacement函数中的定位变得混乱。要解决此问题,请在设置初始actualWidth和actualHeight(225行左右)之前清除right值:

$tip.css({ 'right': '' });
// check to see if placing tip in new offset caused the tip to resize itself
var actualWidth  = $tip[0].offsetWidth
var actualHeight = $tip[0].offsetHeight

答案 1 :(得分:0)

我认为这与访问网页的浏览器/客户端有很大关系。例如,为了在适当的一侧显示尖端(没有聚集或从左侧或右侧难以辨认),确定offsetLeft&amp;使用javascript对象元素的offsetTop并相应地放置它。您可以为不同的分辨率使用不同的页面。

屏幕宽度为400-720像素的CSS示例:

@media screen and (min-width:400px) and (max-width:721px)

一些伪代码:

if (this.offsetLeft < 200)   //if there's not enough room to display the tip
tip.offsetLeft += 200;

答案 2 :(得分:-1)

我认为你基本上得到了它,它对我来说很好。

只需添加最小宽度检测,使其不会太小。

if (/bottom|top/.test(placement)) {
  var delta = 0

  if (offset.left < 0) {
    delta       = offset.left * -2
    offset.left = 0

    $tip.offset(offset)

    actualWidth  = $tip[0].offsetWidth
    actualHeight = $tip[0].offsetHeight
  } 

  this.replaceArrow(delta - width + actualWidth, actualWidth, 'left');

} else {
    if (placement == 'left' && offset.left < 0) {
        var right = (  $(window).width() + 10) - ( offset.left + actualWidth ); 

        offset.left = 0;
        $tip.offset(offset);
        $tip.css({ 'right': right });
    }

    this.replaceArrow(actualHeight - height, actualHeight, 'top');    
}