多行链接中引导工具提示的解决方法

Workaround for Bootstrap tooltip in multiple-line links

本文关键字:工具提示 解决 方法 链接      更新时间:2024-05-25

我知道在官方的Bootstrap页面中,它说white-space: nowrap;应该添加到带有工具提示的多行链接中。

然而,我正在开发一个Chrome扩展,我想在任何网页上添加工具提示,而不改变其原始布局。因此,所提出的解决方案对我来说并不理想

我尝试手动设置工具提示的位置。当这种情况发生时,它将返回最左边的位置。因此,我尝试了这个解决方案,它返回正确的位置(链接的起始位置,而不是最左边的位置)。

问题是,无论我设置放置left还是right,它都不会按照我的意愿进行定位。如果设置为right,它将显示在窗口外,因为它将起点放在最右边的位置。如果设置为left,它也会显示在窗口外,因为它位于最左边的位置。

参见Fiddle

在这种情况下,理想情况下,我希望它位于链接起点的左侧(在第一行中)。

有没有解决方法可以实现这一点?

您可以使用鼠标位置作为工具提示锚,也可以修改工具提示javascript代码来实现这一点,如如何使popover出现在鼠标进入悬停目标的位置?中所述?。您可以将底部代码与链接中的代码合并以实现两者,并选择您喜欢的代码。

在bootstrap-oltip.js中,替换(我想是第1602行)(很抱歉格式不好)

 Tooltip.prototype.getPosition 
 and
 Tooltip.prototype.getCalculatedOffset

分别具有的功能

Tooltip.prototype.getPosition = function($element) {
  $element = $element || this.$element
  var el = $element[0]
  var isBody = el.tagName == 'BODY'
  var elRect = el.getBoundingClientRect()
  if (elRect.width == null) {
    // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
    elRect = $.extend({}, elRect, {
      width: elRect.right - elRect.left,
      height: elRect.bottom - elRect.top
    })
  }
  var rects = el.getClientRects();
  var firstRect = rects[0];
  var lastRect = rects[rects.length - 1];
  firstRect = $.extend({}, firstRect, {
    width: firstRect.right - firstRect.left,
    height: firstRect.bottom - firstRect.top
  })
  lastRect = $.extend({}, lastRect, {
    width: lastRect.right - lastRect.left,
    height: lastRect.bottom - lastRect.top
  })

  var elOffset = isBody ? {
    top: 0,
    left: 0
  } : $element.offset()
  var elScrollTop = elOffset.top - elRect.top;
  var elScrollLeft = elOffset.left - elRect.left;
  firstRect.top += elScrollTop;
  lastRect.top += elScrollTop;
  firstRect.left += elScrollLeft;
  lastRect.left += elScrollLeft;
  firstRect = {
    firstRect: firstRect
  };
  lastRect = {
    lastRect: lastRect
  };
  var scroll = {
    scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop()
  }
  var outerDims = isBody ? {
    width: $(window).width(),
    height: $(window).height()
  } : null
  return $.extend({}, elRect, scroll, outerDims, elOffset, firstRect, lastRect)
}
Tooltip.prototype.getCalculatedOffset = function(placement, pos, actualWidth, actualHeight) {
  return placement == 'bottom' ? {
      top: pos.top + pos.height,
      left: pos.left + pos.width / 2 - actualWidth / 2
    } :
    placement == 'top' ? {
      top: pos.top - actualHeight,
      left: pos.left + pos.width / 2 - actualWidth / 2
    } :
    placement == 'left' ? {
      top: pos.top + pos.height / 2 - actualHeight / 2,
      left: pos.left - actualWidth
    } :
    placement == 'textleft' ? {
      top: pos.firstRect.top + (pos.firstRect.height / 2) - actualHeight / 2,
      left: pos.firstRect.left - actualWidth
    } :
    placement == 'textright' ? {
      top: pos.lastRect.top + (pos.lastRect.height / 2) - actualHeight / 2,
      left: pos.lastRect.right
    } :
    /* placement == 'right' */
    {
      top: pos.top + pos.height / 2 - actualHeight / 2,
      left: pos.left + pos.width
    }
}

现在您可以使用位置"textleft"answers"textright"。这适用于Bootstrap v3.3.6。它可以通过不直接编辑引导程序源而是扩展它来改进(而且它有点脏)。

此外,您还需要将其添加到工具提示箭头的css中。

.tooltip.textright {
  padding: 0 5px;
  margin-left: 3px;
}
.tooltip.textleft {
  padding: 0 5px;
  margin-left: -3px;
}
.tooltip.textleft .tooltip-arrow{
  top: 50%;
  right: 0;
  margin-top: -5px;
  border-width: 5px 0 5px 5px;
  border-left-color: #000;
}
.tooltip.textright .tooltip-arrow{
  top: 50%;
  left: 0;
  margin-top: -5px;
  border-width: 5px 5px 5px 0;
  border-right-color: #000;
}

这是小提琴:JSFiddle

这是对@Gökhan Kurt答案的改进

他的解决方案将工具提示放置在多行链接的左侧或右侧。然而,我想改进一下,让它看起来更好。因此,当您将鼠标悬停在上面一行时,工具提示将显示在链接的左侧;当您将鼠标悬停在底线时,工具提示将显示在链接的右侧。

为此,我检测用户将链接悬停在哪里。如果它在窗户的右侧附近,就意味着它在上面。否则,这就是底线。如果在工具提示选项中设置container: 'body',则此操作有效。

对于Bootstrap v3.3.6,工具提示插件源代码:

enter功能中获取鼠标位置:

if (obj instanceof $.Event) {
  self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
  var mousePos = { x: -1, y: -1 };
  mousePos.x = obj.pageX;
  mousePos.y = obj.pageY;
  window.mousePos = mousePos;
}

show函数中,清除放置CSS类(因为每次悬停链接时可能会有所不同),并根据鼠标位置设置新的放置:

var isTextPlacement = /textleft|textright/.test(placement)
if(isTextPlacement){
    $tip.removeClass("textright");
    $tip.removeClass("textleft");
}
//390 is hardcoded value which is the max size of the tooltip, you may adjust to your case
if(placement == 'textleft' && window.mousePos.x < 390){
  placement = 'textright';
}else if(placement == 'textright' && window.mousePos.x > $(window).width() - 390){
  placement = 'textleft';
}

对于getCalculatedOffset,我使用了以下内容,如果不能应用textright,则应用textleft

  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
    var windowWidth = $(window).width();
    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2 } :
           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
           placement=='left'?{ top: pos.top+pos.height/2-actualHeight/2, left: pos.left-actualWidth }:
           placement == 'right' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } :
           placement=='textleft' && window.mousePos.x > 390 ? { top: pos.firstRect.top+(pos.firstRect.height/2)-actualHeight/2, left: pos.firstRect.left-actualWidth }:
           /*placement=='textright'*/ window.mousePos.x < windowWidth - 390 ? { top: pos.lastRect.top+(pos.lastRect.height/2)-actualHeight/2, left: pos.lastRect.right }:
           /*apply textleft*/         { top: pos.firstRect.top+(pos.firstRect.height/2)-actualHeight/2, left: pos.firstRect.left-actualWidth }
  }

就是这样。检查JSFiddle(调整输出窗口的大小,使链接跨越两行,并与@Gökhan Kurt的答案进行比较。由于硬编码为390px,您可能需要将其设置得更大)。