Изменение положения всплывающих окон Bootstrap на основе положения X всплывающего окна по отношению к краю окна?

я прочесал интернет повсюду, и пока я нашел этот пост StackOverflow проницательным можно ли изменить положение всплывающих окон Bootstrap на основе ширины экрана?, он все еще не ответил на мой вопрос, вероятно, из-за моей проблемы с пониманием позиции/смещения.

вот что я пытаюсь сделать. Я хочу, чтобы позиция Twitter Bootstap Popover была правильной, если только точка доступа не будет расположена за пределами окна просмотра, тогда я хочу, чтобы она была слева. Я делаю веб-приложение iPad с горячими точками, когда вы нажимаете на горячую точку, появляется информация, но я не хочу, чтобы она появлялась за пределами окна просмотра, когда горизонтальная прокрутка заблокирована.

Я думаю, что это что-то вроде этого:

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

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

мысли? Спасибо!

10 ответов


Я только что заметил, что размещение может быть строка или функция возвращает строку это делает расчет каждый раз, когда вы нажимаете на ссылку popover.

Это упрощает репликацию того, что вы сделали без начального $.каждый:

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 в сочетании с предпочтительным размещением, например,auto left

http://getbootstrap.com/javascript/#popovers: "Когда указано "auto", он будет динамически переориентировать popover. Например, если размещение "auto left", всплывающая подсказка будет отображаться слева, когда это возможно, в противном случае она будет отображаться справа."

Я пытался сделать то же самое, а потом понял, что эта функция уже существовать.


для Bootstrap 3, есть

placement: 'auto right'

что легче. По умолчанию он будет правым, но если элемент находится в правой части экрана, всплывающее окно будет левым. Так и должно быть:

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

поэтому я придумал способ сделать это эффективно. Для моего конкретного проекта Я создаю веб-сайт iPad, поэтому я точно знал, какое значение пикселя X/Y будет достигать края экрана. Ваши значения thisX и thisY будут отличаться.

поскольку popovers размещаются встроенным стилем в любом случае, я просто хватаю левое и верхнее значения для каждой ссылки, чтобы решить, в каком направлении должен быть 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
    });
}

любые комментарии/улучшения приветствуются, но это получает работу, если вы готовы поместить значения вручную.


ответ bchhun вывел меня на правильный путь, но я хотел проверить фактическое пространство между источником и краем видового экрана. Я также хотел уважать атрибут размещения данных как предпочтение с соответствующими резервными вариантами, если не было достаточно места. Таким образом," право " всегда будет идти направо, если только не будет достаточно места для popover, чтобы показать на правой стороне, например. Вот как я с этим справился. Это работает для меня, но кажется немного громоздким. Если у кого есть идеи для более чистого, более сжатого решения, мне было бы интересно увидеть его.

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

вы также можете попробовать этот,

==> получить целевую / исходную позицию в viewport
==> Проверьте, является ли пространство снизу меньше, чем высота всплывающей подсказки
==> Если пространство снизу меньше высоты всплывающей подсказки, просто прокрутите страницу вверх

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

вы можете использовать auto в размещении данных, например data-placement= "auto left". Он будет автоматически настраиваться в соответствии с размером экрана и размещение по умолчанию будет оставлено.


в дополнение к большому ответу bchhun, если вы хотите absoulte позиционирования, вы можете сделать это

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

Я решил свою проблему в 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 popover float в наилучшее положение, основанное на положении элемента.


вы также можете попробовать это, если вам это нужно почти во всех местах на странице.

U может настроить его в общем виде, а затем просто использовать его.

таким образом, 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>

дополнение


для установки дополнительных параметров, u может пойти здесь.

еще больше можно найти здесь.

обновление


если вы хотите всплывающее окно после щелчка, вы можете изменить опцию JS на trigger: "click" как это-

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

U также может настроить его в HTML ading 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>

Я думаю, что это будет более ориентированный код и более повторно используемый и более полезный для всех :).