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

83

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

Вот что я пытаюсь сделать. Я хочу, чтобы положение всплывающего окна Bootstap в Twitter было ПРАВИЛЬНО, если только всплывающее окно горячей точки не будет располагаться за пределами области просмотра, тогда я хочу, чтобы оно было расположено ВЛЕВО. Я делаю веб-приложение для iPad, в котором есть горячие точки. Когда вы нажимаете на горячую точку, появляется информация, но я не хочу, чтобы она отображалась за пределами области просмотра, когда горизонтальная прокрутка заблокирована.

Я думаю, это будет примерно так:

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

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

Мысли? Благодаря!

j0e
источник

Ответы:

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);
bchhun
источник
1
Это лучший способ, потому что autoон не всегда работает идеально в зависимости от макета страницы и содержимого, которое вы помещаете во всплывающее окно.
Брон Дэвис
Спасибо за это. Можно ли использовать его без ссылки на вас?
D.Tate
6
@ D.Tate Я считаю, что все в stackoverflow можно использовать без указания авторства. Сходи с ума;)
bchhun
3
Какова логика выбора left 515&top 110
Мурали Муругесан
1
@MuraliMurugesan вообще никакой логики; Я просто использовал цифры, указанные в вопросе. Вы можете использовать все, что хотите.
bchhun
35

Для Bootstrap 3 есть

placement: 'auto right'

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

$('.infopoint').popover({
   trigger:'hover',
   animation: false,
   placement: 'auto right'
});
Ханс Тионо
источник
2
Пока что у меня был неоднозначный опыт. Я еще не смотрел исходный код Bootstrap, но похоже, что он учитывает только позиционирование элемента, а не предполагаемое положение всплывающего окна. Таким образом, элементы, которые находятся на краю или за краем окна, получают всплывающее окно максимум на краю, но элементы, которые находятся чуть выше края (например), получают всплывающее окно ниже сгиба.
Давид
1
Нет, это не должен быть принятый ответ. Опция «размещение» не учитывает края окна , только границы родительского элемента / контейнера. Так что, если у вас есть, например, «автоматический верх», он все равно будет отображаться в верхней части окна при прокрутке вниз.
rzb 01
31

Основываясь на документации, вы должны иметь возможность использовать autoв сочетании с предпочтительным размещением, напримерauto left

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

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

Хэмиш Роуз
источник
2
auto left дает горизонтальную полосу прокрутки
Jitendra Vyas
3
Вы также можете указать, viewportесли не хотите, чтобы он вычислялся на основе родительского элемента.
allicarn
5

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

Поскольку всплывающие окна в любом случае размещаются с помощью встроенного стиля, я просто беру значения left и top для каждой ссылки, чтобы решить, в каком направлении должно быть всплывающее окно. Это делается путем добавления значений данных html5, которые использует .popover () при выполнении.

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

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

j0e
источник
2

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

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

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

Абхишек Ананд
источник
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);
яблоко16
источник
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 = '';
       }

};
Suvra
источник
-2

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

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

Таким образом, вы также можете использовать элемент 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"как this-

        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>

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

Абрар Джахин
источник