【问题标题】:How to re-position a Bootstrap Popover after dynamic content insertion?如何在动态内容插入后重新定位 Bootstrap Popover?
【发布时间】:2014-06-23 18:16:55
【问题描述】:

所以基本上每当我使用空的content 选项加载Bootstrap Popover 并将内容动态插入其中时,弹出框都会丢失其正确位置。

例如:

$('td.chartSection').each(function () {
    var $thisElem = $(this);
    $thisElem.popover({
        placement: 'top',
        trigger: 'hover',
        html: true,
        container: $thisElem,
        delay: {
            hide: 500
        },
        content: ' '
    });
});

//After popup is shown, run this event
$('td.chartSection').on('shown.bs.popover', function () {
    var $largeChart = $(this).find('.popover .popover-content');

    //Insert some dummy content
    $largeChart.html("dfjhgqrgf regqef  f wrgb wrbgqwtgtrg <br /> wfghjqerghqreg fbvwqbtwfbvfgb <br />efgwetrg");
});

我的问题:

有没有$('td.chartSection').popover('recalculate')等可以重新计算popovers位置的方法。

或者是否有另一种方法来重新定位弹出框,而无需使用 CSS 样式手动执行此操作?

WORKING DEMO

【问题讨论】:

    标签: javascript jquery css twitter-bootstrap


    【解决方案1】:

    在 DOM 中动态插入其他元素后,我遇到了定位问题,我使用 container 选项解决了这些问题。默认情况下,我的弹出框附加到body

    将它们附加到最近的容器上解决了位置问题。

    <div id="test">
        <span
            data-container="#test" data-toggle="popover" data-placement="top" title="Help"
            data-trigger="hover" tabindex="-1" data-html="true"
            data-content="Some text">
    </div>
    

    【讨论】:

      【解决方案2】:
      window.dispatchEvent(new Event('resize'));
      

      这对我有用。

      【讨论】:

        【解决方案3】:

        在 Popover 内容更新后,如果您在页面内容上向上或向下滚动,Popover 会自动定位并再次可读,因此在动态内容更新后重新定位 Popover 的更简单的解决方法是向下和向上滚动通过 pure javascript 获取页面上的 1 个像素:

        var y = $(window).scrollTop(); //your current y position on the page $(window).scrollTop(y+1).scrollTop(y-1);

        【讨论】:

          【解决方案4】:

          这是受上面@AlexCheuk 回答的启发,但我需要一个使用 Bootstrap 2 的解决方案。另外,在我的项目中,我不需要更改弹出框的位置,所以我把它删掉了。

          $(function() {
              $.fn.popover.Constructor.prototype.reposition = function () {
                  console.log('popover reposition is called');
                  var $tip = this.tip();
          
                  var placement = typeof this.options.placement === 'function' ? this.options.placement.call(this, $tip[0], this.$element[0]) : this.options.placement;
          
                  var pos = this.getPosition();
                  var actualWidth = $tip[0].offsetWidth;
                  var actualHeight = $tip[0].offsetHeight;
          
                  function getCalculatedOffset (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 == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width };
                  }
          
                  var calculatedOffset = getCalculatedOffset(placement, pos, actualWidth, actualHeight);
          
                  this.applyPlacement(calculatedOffset, placement);
                  console.log(this);
              };
          });
          

          称呼它:

          $element.popover('reposition')
          

          【讨论】:

          • 我为“自动”放置添加了一些代码,然后从提示中获取实际放置。当弹出框的实际位置由于网站上的位置而设置为右侧时,它也适用于 data-placement="auto left"。
          • if (placement.search('auto') >-1) {placement = $tip.hasClass('top') ? 'top' : $tip.hasClass('bottom') ? '底部' : $tip.hasClass('left') ? 'left' : $tip.hasClass('right') ? '对' : '自动'; // console.log(['自动放置', Placement]); }
          【解决方案5】:

          使用 Bootstrap v3.3.7:

          您可以扩展 Popover 构造函数以添加对重新定位功能的支持。您可以将此脚本放在加载引导程序的位置下方。

          JSFiddle Demo

          <script src="bootstrap.js"></script>
          <script type="text/javascript">
          $(function () {
              $.fn.popover.Constructor.prototype.reposition = function () {
                  var $tip = this.tip()
                  var autoPlace = true
          
                  var placement = typeof this.options.placement === 'function' ? this.options.placement.call(this, $tip[0], this.$element[0]) : this.options.placement
          
                  var pos = this.getPosition()
                  var actualWidth = $tip[0].offsetWidth
                  var actualHeight = $tip[0].offsetHeight
          
                  if (autoPlace) {
                      var orgPlacement = placement
                      var viewportDim = this.getPosition(this.$viewport)
          
                      placement = placement === 'bottom' &&
                          pos.bottom + actualHeight > viewportDim.bottom ? 'top' : placement === 'top' &&
                          pos.top - actualHeight < viewportDim.top ? 'bottom' : placement === 'right' &&
                          pos.right + actualWidth > viewportDim.width ? 'left' : placement === 'left' &&
                          pos.left - actualWidth < viewportDim.left ? 'right' : placement
          
                      $tip
                          .removeClass(orgPlacement)
                          .addClass(placement)
                  }
          
                  var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
          
                  this.applyPlacement(calculatedOffset, placement)
              }
          })
          </script>
          

          然后在插入内容后需要重新定位工具提示时在脚本中。你可以打电话:

          $element.popover('reposition')
          

          【讨论】:

          • 我希望这个可以工作,但如果动态内容与原始内容差异太大,那么它实际上并没有正确重新定位。 jsfiddle.net/e90npd0v/9
          • @KSib 我修复了您的 JSFiddle jsfiddle.net/e90npd0v/12,因为根本没有触发重新定位。
          • 这是更好的解决方案,没有闪烁。谢谢!
          • 谢谢,太好了。我将为下面的 Bootstrap 2 创建类似的函数。
          • 这是一个很好的解决方案,因为它适用于具有动态内容的弹出框。它不会重建破坏动态内容的弹出框,而是简单地移动它们。
          【解决方案6】:

          我遇到过类似的情况,我有一个弹出框,其中已经包含一些 HTML(加载微调器),并且当 ajax 调用返回时我正在更改内容。在我的 ajax 回调函数中,这是我用来更改定位使其居中的代码:

          var originalHeight = $(popover).height();
          
          $(popover).find('.popover-content').html(data);
          
          var newHeight = $(popover).height();
          var top = parseFloat($(popover).css('top'));
          var changeInHeight = newHeight - originalHeight;
          
          $(popover).css({ top: top - (changeInHeight / 2) });
          

          【讨论】:

          • 效果很好,但我删除了最后一行中的分隔部分(changeInHeight / 2),所以我最终得到:$(popover).css({ top: top - changeInHeight });
          【解决方案7】:

          当它已经加载到页面时,我使用此代码调整弹出框的高度:

             var popover = $(this).closest('.popover');
             var sender = popover.prev();
             var adjustment = (sender.position().top - popover.height()) + 15;
             popover.css({ top: adjustment });
          

          变量 sender 是弹出框居中的目标。

          【讨论】:

            【解决方案8】:

            如果弹出框的位置是“顶部”(如问题所示),您可以从页面顶部调整其绝对位置。

            我创建了一个函数来计算弹出框的高度,然后将其在页面上向上移动它的高度。

            function adjustPopoverHeight($popoverElement) {     
                var height = $popoverElement.height();
                var adjustment = 0 - height - 4;
                $popoverElement.css({ top: adjustment });
            }
            

            并与 ajax 请求一起使用以获取数据:

             $.ajax({
                type: 'GET',
                url: url,
                contentType: 'application/json; charset=utf-8',
                dataType: 'json'
            }).done(function(dat) { 
                //set the popover content to whatever you like
            
                //adjust height of popover
                var $popoverElement = $('.popover');
                adjustPopoverHeight($popoverElement);
            })
            

            【讨论】:

              【解决方案9】:

              我刚刚打过电话

              button.popover('show');

              它重新定位了它。

              【讨论】:

              • 这确实有效,但每次触发时都会使弹出框闪烁,因为它被隐藏并再次显示。
              • 是的,此解决方案适用于弹出框没有动态生成内容的简单情况。它还会闪烁。
              【解决方案10】:

              我采用了 jme11 的答案的概念并针对 Bootstrap 3.3.2+ 进行了更新

              $('button')
                .popover({
                  trigger: 'manual',
                  html: true,
                  container: 'body',
                })
                .click(function() {
                  var $this = $(this);
                  var popover_obj = $this.data('bs.popover');
                  if (popover_obj.tip().hasClass('in')) {
                    popover_obj.hide();
                  } else {
                    var opts = popover_obj.options;
                    opts.content = $('<div/>').text('hello world');
                    popover_obj.init('popover', $this, opts);
                    popover_obj.show();
                  }
                })
              ;
              

              在 popover 对象上有一个名为 setContent 的方法,但由于某种原因它对我不起作用。如果你想尝试,它看起来像这样:

              popover_obj.setContent($('<div/>').text('hello world'));
              

              【讨论】:

                【解决方案11】:

                不,没有重新计算,也没有简单的方法来做到这一点。也就是说,您可以通过这种方式动态注入弹出框:

                $('td.chartSection').on('mouseenter', function() {
                    var myPopOverContent = 'This is some static content, but could easily be some dynamically obtained data.';
                    $(this).data('container', 'body');
                    $(this).data('toggle', 'popover');
                    $(this).data('placement', 'top');
                    $(this).data('content', myPopOverContent);
                    $(this).popover('show');
                });
                
                $('td.chartSection').on('mouseout', function() {
                    $(this).popover('hide');
                });
                

                只需将您小提琴中的所有 js 替换为上述内容并检查一下...

                【讨论】:

                • 如果您想在弹出框的内容/正文中添加 html,这是最简单的方法。但是您需要设置该选项: $(this).data('html', true);并且显然将 html 放入 myPopOverContent
                猜你喜欢
                • 2018-03-30
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-11-02
                • 2012-05-30
                • 2014-05-28
                • 2018-08-18
                • 2021-07-01
                相关资源
                最近更新 更多