是否根据弹出窗口相对于窗口边缘的X位置更改Bootstrap弹出窗口的位置?


83

我到处搜寻了互联网,而我发现此stackoverflow帖子很有见地,是否可以根据屏幕宽度更改Bootstrap弹出窗口的位置?,它仍然没有回答我的问题,可能是由于我在理解位置/偏移时遇到了麻烦。

这就是我想要做的。我希望Twitter Bootstap Popover的位置为RIGHT,除非热点Popover的位置超出视口,然后我希望它的位置为LEFT。我正在制作一个具有热点的iPad Web应用程序,当您按一个热点时,会显示信息,但是当水平滚动锁定时,我不希望它出现在视口之外。

我在想它会变成这样:

$('.infopoint').popover({
        trigger:'hover',
        animation: false,
        placement: wheretoplace 
    });
    function wheretoplace(){
        var myLeft = $(this).offset.left;

        if (myLeft<500) return 'left';
        return 'right';
    }

有什么想法吗?谢谢!

Answers:


177

我只是注意到,放置选项可以是字符串,也可以是返回字符串函数,每次单击可弹出式链接时,该字符串都会进行计算。

这使得无需初始$ .each函数即可轻松复制您所做的事情

var options = {
    placement: function (context, source) {
        var position = $(source).position();

        if (position.left > 515) {
            return "left";
        }

        if (position.left < 515) {
            return "right";
        }

        if (position.top < 110){
            return "bottom";
        }

        return "top";
    }
    , trigger: "click"
};
$(".infopoint").popover(options);

1
这是最好的方法,因为auto根据您在弹出窗口中放置的页面布局和内容,并非总是能正常工作。
布朗·戴维斯

谢谢你 如果我们在不归属您的情况下使用它,可以吗?
D.Tate

6
@ D.Tate我相信stackoverflow上的所有内容都应该没有任何归属地可用。发疯了;)
bchhun 2015年

3
选择left 515&的逻辑是什么top 110
Murali Murugesan

1
@MuraliMurugesan完全没有逻辑;我只使用了问题中提供的数字。您可以使用任何您想要的。
bchhun

35

对于Bootstrap 3,有

placement: 'auto right'

这比较容易。默认情况下,它将为右,但是如果元素位于屏幕的右侧,则弹出框将为左。因此应该是:

$('.infopoint').popover({
   trigger:'hover',
   animation: false,
   placement: 'auto right'
});

2
到目前为止,我对此有不同的经验。我还没有看过Bootstrap源代码,但是看起来它仅考虑元素的位置,而不考虑弹出窗口的将来位置。因此,位于边缘上或超出窗口边缘的元素最多在边缘处有一个弹出框,例如,位于边缘上方的元素(例如)在折叠以下具有一个弹出框。
戴夫

1
不,它不应该是公认的答案。“放置”选项不考虑窗口边缘,仅考虑父元素/容器边界。因此,如果您具有“自动顶部”,则当您向下滚动时,它仍将显示在顶部窗口中。
rzb

31

根据文档,您应该可以auto与首选展示位置结合使用,例如auto left

http://getbootstrap.com/javascript/#popovers:“指定”自动“时,它将动态调整弹出窗口的方向。例如,如果放置为”自动左“,则工具提示将在可能的情况下显示在左侧,否则它会显示正确。”

我试图做同样的事情,然后意识到此功能已经存在。


2
自动向左提供水平滚动条
Jitendra Vyas 2014年

3
viewport如果您不希望根据元素的父元素进行计算,也可以指定一个。
allicarn 2014年

5

因此,我想出了一种有效的方法。对于我的特定项目,我正在构建一个iPad网站,因此我确切地知道到达屏幕边缘的像素X / Y值是多少。您的thisX和thisY值将有所不同。

由于弹出式窗口无论如何都是通过内联样式放置的,因此我只需抓住每个链接的left和top值即可确定弹出式窗口应朝哪个方向移动。这是通过在执行时附加.popover()使用的html5数据值来完成的。

if ($('.infopoint').length>0){
    $('.infopoint').each(function(){
        var thisX = $(this).css('left').replace('px','');
        var thisY = $(this).css('top').replace('px','');
        if (thisX > 515)
            $(this).attr('data-placement','left');
        if (thisX < 515)
            $(this).attr('data-placement','right');
        if (thisY > 480)
            $(this).attr('data-placement','top');
        if (thisY < 110)
            $(this).attr('data-placement','bottom');
    });
    $('.infopoint').popover({
        trigger:'hover',
        animation: false,
        html: true
    });
}

欢迎任何评论/改进,但是如果您愿意手动输入值,就可以完成工作。


2

bchhun的回答使我处在正确的轨道上,但我想检查源与视口边缘之间的实际可用空间。如果没有足够的空间,我也想尊重data-placement属性作为具有适当后备选项的首选项。这样,除非没有足够的空间让弹出框显示在右侧,否则“正确”将始终正确。这就是我的处理方式。它对我有用,但感觉有点麻烦。如果有人对采用更清洁,更简洁的解决方案有任何想法,我将很感兴趣。

var options = {
  placement: function (context, source) {
    var $win, $source, winWidth, popoverWidth, popoverHeight, offset, toRight, toLeft, placement, scrollTop;

    $win = $(window);
    $source = $(source);
    placement = $source.attr('data-placement');
    popoverWidth = 400;
    popoverHeight = 110;
    offset = $source.offset();

    // Check for horizontal positioning and try to use it.
    if (placement.match(/^right|left$/)) {
      winWidth = $win.width();
      toRight = winWidth - offset.left - source.offsetWidth;
      toLeft = offset.left;

      if (placement === 'left') {
        if (toLeft > popoverWidth) {
          return 'left';
        }
        else if (toRight > popoverWidth) {
          return 'right';
        }
      }
      else {
        if (toRight > popoverWidth) {
          return 'right';
        }
        else if (toLeft > popoverWidth) {
          return 'left';
        }
      }
    }

    // Handle vertical positioning.
    scrollTop = $win.scrollTop();
    if (placement === 'bottom') {
      if (($win.height() + scrollTop) - (offset.top + source.offsetHeight) > popoverHeight) {
        return 'bottom';
      }
      return 'top';
    }
    else {
      if (offset.top - scrollTop > popoverHeight) {
        return 'top';
      }
      return 'bottom';
    }
  },
  trigger: 'click'
};
$('.infopoint').popover(options);

1

您也可以尝试这个

==>获取视口中的目标/源位置
==>检查底部空间是否小于工具提示高度
==>如果底部空间小于工具提示高度,则向上滚动页面

placement: function(context, source){
  //get target/source position in viewport
  var bounds = $(source)[0].getBoundingClientRect();
      winHeight = $(window).height();

  //check wheather space from bottom is less that your tooltip height
  var rBottom = winHeight - bounds.bottom;

  //Consider 180 == your Tooltip height
  //if space from bottom is less that your tooltip height, this will scrolls page up
  //We are keeping tooltip position is fixed(at bottom)

  if (rBottom < 180){
    $('html, body').animate({ scrollTop: $(document).scrollTop()+180 }, 'slow');
  }

  return "bottom";
}


0

除了bchhun的好答案之外,如果您要绝对定位,也可以这样做

var options = {
    placement: function (context, source) {
         setTimeout(function () {
               $(context).css('top',(source.getBoundingClientRect().top+ 500) + 'px')
         },0)
         return "top";
    },
    trigger: "click"
};
$(".infopoint").popover(options);

0

我在AngularJS中解决了我的问题,如下所示:

var configPopOver = {
        animation: 500,
        container: 'body',
        placement: function (context, source) {
                    var elBounding = source.getBoundingClientRect();
                    var pageWidth = angular.element('body')[0].clientWidth
                    var pageHeith = angular.element('body')[0].clientHeith

                    if (elBounding.left > (pageWidth*0.34) && elBounding.width < (pageWidth*0.67)) {
                        return "left";
                    }

                    if (elBounding.left < (pageWidth*0.34) && elBounding.width < (pageWidth*0.67)) {
                        return "right";
                    }

                    if (elBounding.top < 110){
                        return "bottom";
                    }

                    return "top";
                },
        html: true
    };

此功能根据元素位置将Bootstrap弹出浮标的位置移至最佳位置。


0
$scope.popoverPostion = function(event){
    $scope.pos = '';

       if(event.x <= 207 && event.x >= 140){
           $scope.pos = 'top';
           event.x = '';
       }
       else if(event.x < 140){
           $scope.pos = 'top-left';
           event.x = '';
       }
       else if(event.x > 207){
           $scope.pos = 'top-right';
           event.x = '';
       }

};

-2

如果您在页面的几乎所有位置都需要它,也可以尝试使用此方法。

U可以以一般方式对其进行配置,然后再使用它。

这样,您还可以使用HTML元素和您想要的任何东西:)

$(document).ready(function()
                  {
  var options =
      {
        placement: function (context, source)
        {
          var position = $(source).position();
          var content_width = 515;  //Can be found from a JS function for more dynamic output
          var content_height = 110;  //Can be found from a JS function for more dynamic output

          if (position.left > content_width)
          {
            return "left";
          }

          if (position.left < content_width)
          {
            return "right";
          }

          if (position.top < content_height)
          {
            return "bottom";
          }

          return "top";
        }
        , trigger: "hover"
        , animation: "true"
        , html:"true"
      };
  $('[data-toggle="popover"]').popover(options);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>


<div class="container">
	<h3>Popover Example</h3>
	<a id="try_ppover" href="#" data-toggle="popover" title="Popover HTML Header" data-content="<div class='jumbotron'>Some HTML content inside the popover</div>">Toggle popover</a>
</div>

加成


要设置更多选项,您可以转到此处

这里可以找到更多。

更新资料


如果您想在点击后弹出,则可以将JS选项更改为trigger: "click"这样-

        return ..;
    }
    ......
    , trigger: "click"
    ......
};

您也可以data-trigger="click"像这样在HTML中自定义它-

<a id="try_ppover" href="#" data-toggle="popover" data-trigger="click" title="Popover Header" data-content="<div class='jumbotron'>Some content inside the popover</div>">Toggle popover</a>

我认为这将是面向更多方向的代码,更加可重用,并且对所有人也有帮助:)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.