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

时间:2016-04-13 09:38:42

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

我知道在official Bootstrap page中它表示white-space: nowrap;应添加到工具提示的多行链接中。

但是,我正在开发Chrome扩展程序,我想在任何网页上添加工具提示,而不更改其原始布局。因此,建议的解决方案对我来说并不理想。

我尝试手动设置工具提示的位置。当发生这种情况时,它将返回最左边的位置。所以,我尝试this solution,它返回正确的位置(链接的开始,而不是最左边的位置)。

问题是,无论是我设置展示位置left还是right,它都不会按我的意愿定位。如果设置为right,它将显示在窗口外部,因为它从最右边的位置开始。如果设置为left,它也会显示在窗口外部,因为它位于最左侧的位置。

See Fiddle

在这种情况下,理想情况下我希望将它放在链接的起始点(第一行)。

是否有解决方法可以实现这一目标?

2 个答案:

答案 0 :(得分:1)

您可以将鼠标位置用作工具提示锚点,也可以修改工具提示javascript代码以实现此目的,如How to make popover appear where my mouse enters the hover target?中所示。您可以将底部代码与链接中的代码合并以实现两者并选择您喜欢的代码。

在bootstrap-tooltip.js中,替换(我认为第1602行)(抱歉格式不佳)

becomeFirstResponder

分别用于

 Tooltip.prototype.getPosition 
 and
 Tooltip.prototype.getCalculatedOffset

现在您可以使用“textleft”和“textright”的展示位置。 这适用于Bootstrap v3.3.6。可以通过不直接编辑引导源但扩展它来改进它(它有点脏)。

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

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

这是小提琴:JSFiddle

答案 1 :(得分:0)

这是@GökhanKurt答案的改进。

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

为此,我检测用户悬停链接的位置。如果它靠近窗口的右侧,则意味着它是上面的线。否则,这是底线。如果您在工具提示选项中设置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,我使用了以下内容,如果无法应用textleft,则会应用textright

  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ökhanKurt回答。由于硬编码390px,您可能需要将其设置得更大。)