【问题标题】:Changing the position of Bootstrap popovers based on the popover's X position in relation to window edge?根据弹出框相对于窗口边缘的 X 位置更改 Bootstrap 弹出框的位置?
【发布时间】:2012-04-14 23:08:14
【问题描述】:

我在互联网上四处搜寻,虽然我发现这篇 stackoverflow 帖子很有见地 Is it possible to change the position of Bootstrap popovers based on screen width?,但它仍然没有回答我的问题,可能是因为我无法理解位置/偏移量。

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

我想它会是这样的:

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

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

想法?谢谢!

【问题讨论】:

    标签: jquery twitter-bootstrap offset popover


    【解决方案1】:

    我刚刚注意到 placement 选项可以是 string返回字符串 的函数,每次点击时都会进行计算在一个可弹出的链接上。

    这使得在没有初始 $.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);
    

    【讨论】:

    • 这是最好的方法,因为 auto 并不总是能完美运行,具体取决于您放入弹出框的页面布局和内容。
    • 谢谢。如果我们在不署名的情况下使用它可以吗?
    • @D.Tate 我相信 stackoverflow 上的所有内容都应该可以在没有任何归属的情况下使用。为它疯狂;)
    • 选择left 515&top 110的逻辑是什么
    • @MuraliMurugesan 完全没有逻辑;我只是使用了问题中提供的数字。你可以使用任何你想要的。
    【解决方案2】:

    对于 Bootstrap 3,有

    placement: 'auto right'
    

    这更容易。默认情况下,它是正确的,但如果元素位于屏幕的右侧,则弹出框将在左侧。所以应该是:

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

    【讨论】:

    • 到目前为止,我在这方面的经历参差不齐。我还没有查看 Bootstrap 源代码,但看起来它只考虑了元素定位,而不是 popover 的预期位置。因此,位于边缘或超出窗口边缘的元素最多会在边缘出现弹出框,但刚好在边缘上方的元素(例如)会在折叠下方获得弹出框。
    • 不,它不应该是公认的答案。 “放置”选项不考虑窗口边缘,只考虑父元素/容器边界。所以如果你有例如当您向下滚动时,“自动顶部”仍会显示在顶部关闭窗口中。
    【解决方案3】:

    根据文档,您应该能够将auto 与首选位置结合使用,例如auto left

    http://getbootstrap.com/javascript/#popovers: “当指定“auto”时,它会动态地重新定位弹出框。例如,如果放置为“auto left”,则工具提示将尽可能向左显示,否则将显示在右侧。”

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

    【讨论】:

    • 自动向左提供水平滚动条
    • 如果您不希望根据元素的父级计算它,也可以指定viewport
    【解决方案4】:

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

    由于无论如何都是通过内联样式放置弹出框,我只需抓住每个链接的左侧和顶部值来决定弹出框应该是哪个方向。这是通过附加 .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
        });
    }
    

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

    【讨论】:

      【解决方案5】:

      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);
      

      【讨论】:

        【解决方案6】:

        你也可以试试这个,

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

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

        【讨论】:

          【解决方案7】:

          除了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);
          

          【讨论】:

            【解决方案8】:

            我在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 弹出框浮动到最佳位置。

            【讨论】:

              【解决方案9】:
              $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 = '';
                     }
              
              };
              

              【讨论】:

                【解决方案10】:

                您可以在数据放置中使用自动,例如 data-placement="auto left"。它将根据您的屏幕尺寸自动调整,并保留默认位置。

                【讨论】:

                  【解决方案11】:

                  如果您在页面的几乎所有位置都需要它,您也可以尝试这个。

                  你可以用一般的方式配置它然后使用它。

                  这样你也可以使用 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>

                  加法


                  更多选项可以去here

                  更多内容请关注here

                  更新


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

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

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

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

                  我认为这将是更有针对性的代码,更可重用,对所有人更有帮助:)。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2023-03-07
                    • 2017-09-06
                    • 2018-10-31
                    • 1970-01-01
                    相关资源
                    最近更新 更多