Зміна положення поповерів Bootstrap на основі положення X поповера щодо краю вікна?


83

Я обшукав Інтернет далеко і широко, і, хоча я знайшов цей пост 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';
    }

Думки? Дякую!

Відповіді:


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він не завжди працює ідеально залежно від макета сторінки та вмісту, який ви розміщуєте у вікні.
Брон Девіс,

Дякую за це. Це нормально, якщо ми використовуємо його без приписування вам?
Д.Тейт

6
@ D.Tate Я вважаю, що все на stackoverflow має бути корисним без будь-яких приписів.
Божеволіє

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, але схоже, воно враховує лише позиціонування елемента, а не майбутню позицію. Отже, елементи, які знаходяться на краю або поза краєм вікна, отримують поповер на краю максимум, а елементи, що знаходяться трохи вище краю (наприклад), отримують поповер під згином.
Daved

1
Ні, це не повинна бути прийнятою відповіддю. Варіант "розміщення" не враховує краї вікна , лише межі батьківського елемента / контейнера. Отже, якщо у вас є, наприклад, "автоматичний верх", він все одно відображатиметься у верхній частині вікна при прокручуванні вниз.
rzb

31

Виходячи з документації, ви повинні мати можливість використовувати її autoв поєднанні з бажаним місцем розташування, наприкладauto left

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

Я намагався зробити те саме, а потім зрозумів, що ця функціональність вже існує.


2
авто ліворуч дає горизонтальну смугу прокрутки
Jitendra Vyas

3
Ви також можете вказати, viewportякщо ви не хочете, щоб він обчислювався на основі батьківського елемента.
allicarn

5

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

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

Будь-які коментарі / вдосконалення вітаються, але це робить роботу, якщо ви готові вводити значення вручну.


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

Ви можете використовувати автоматичне розміщення даних, наприклад data-position = "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);

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

Ви також можете спробувати цей, якщо вам він потрібен майже у всіх місцях сторінки.

Ви можете налаштувати його загальним чином, а потім просто використовувати.

Таким чином, ви також можете використовувати елемент 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"
    ......
};

Ви також можете налаштувати його в 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>

Думаю, це буде більш орієнтований код, більш використаний і корисніший для всіх :).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.