Bootstrap tooltip\popover - решение непоследовательного размещения слева

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

Когда popover (или всплывающая подсказка, что бы то ни было, они в основном одинаковы) приближается к краю экрана - если это правая сторона, когда она приближается к краю - она ​​будет сокращаться, чтобы не заходить на экран ( он работает только до определенной точки, но это обычно достаточно).

Это не происходит, когда размещение находится слева.

то есть:.

правильное размещение:

Нормальная ширина:

enter image description here

Рядом с краем:

enter image description here

размещение слева:

Нормальная ширина:

enter image description here

близко к краю:

enter image description here

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

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

Любые идеи?

p.s.

Я использую Bootstrap 3.1.1. Новый 3.2 не решает проблему (и я бы хотел избежать обновления на этом этапе).


Основное обновление!

После некоторого копания я понял, что это не имеет никакого отношения к бутстрапу - это просто css - кажется, что когда вы позиционируете элемент абсолютно и подталкиваете его в стороны, он будет стараться оставаться на экране.

Я никогда не знал об этом поведении, и это происходит автоматически - но только в направлении, которое вы нажимаете - то есть div, нажатый слева, будет сжиматься при достижении правого края экрана и наоборот.

Просто случается, что popovers только позиционируется с назначением left - вот почему мы видим несоответствующее поведение - когда оно толкает вправо, оно сжимается, но не в другом направлении.

Итак, решение - вместо этого назначить right - звучит просто? Не так много. Я взял исходный код и немного его обработал, добавив эти строки (где-то arond line 250 в jsfiddle):

if (placement == 'left' && offset.left < 0) {
    var right = ( $(window).width() + 10 ) - ( offset.left + actualWidth ); 

    offset.left = 0;
    $tip.offset(offset);
    $tip.css({ 'right': right });
}

Кажется разумным, не так ли? Если смещение влево меньше 0 (т.е. Оно выходит за пределы экрана), тогда вычислите ширину окна и удалите из него левое смещение и ширину popover (actualWidth), и вы получите расстояние справа.

Затем убедитесь, что reset смещение осталось и примените правильное позиционирование. Но... это только сорта работает, то есть это работает только во второй раз.

Проверьте для себя! Наведите один раз, и он будет утерян, потяните мышь в сторону и повторите попытку, и вдруг она правильно позиционируется. Какого черта?

изменить

Хорошо, похоже, это очень много, поэтому я проясню:

Я знаю о размещении auto. Я не хочу этого. Я хочу контролировать, куда идет popover, позволяя ему автоматически решать это не решение проблемы, просто избегая этого

Ответы

Ответ 1

Хорошо, я подошел немного ближе.

После назначения right в css значения actualWidth и actualHeight будут изменены, поэтому вам необходимо обновить эти переменные. Вокруг строки 253 в jsfiddle:

if (placement == 'left' && offset.left < 0) {
    var right = (  $(window).width() + 10) - ( offset.left + actualWidth ); 

    offset.left = 0;
    $tip.offset(offset);
    $tip.css({ 'right': right });
    actualWidth  = $tip[0].offsetWidth;
    actualHeight = $tip[0].offsetHeight;
}

Это работает в первый раз, когда вы наводите курсор, но каждый раз после этого он устанавливает слишком высокое значение top, поэтому вы не можете прочитать верхнюю часть всплывающей подсказки.

UPDATE: Похоже, что наличие значения right задает позиционирование в функции applyPlacement. Чтобы исправить это, снимите значение right перед установкой начальной фактической ширины и фактической высоты (вокруг строки 225):

$tip.css({ 'right': '' });
// check to see if placing tip in new offset caused the tip to resize itself
var actualWidth  = $tip[0].offsetWidth
var actualHeight = $tip[0].offsetHeight

Ответ 2

Я считаю, что это имеет много общего с браузером/клиентом, который обращается к веб-странице. Например, чтобы отобразить наконечник на правильной стороне (не сгруппированный или неразборчивый с левой или правой стороны), определите смещениеLeft и offsetTop элемента объекта с помощью javascript и поместите его соответствующим образом. У вас могут быть разные страницы для разных разрешений.

Пример CSS для ширины экрана от 400 до 720 пикселей:

@media screen and (min-width:400px) and (max-width:721px)

некоторый псевдокод:

if (this.offsetLeft < 200)   //if there not enough room to display the tip
tip.offsetLeft += 200;

Ответ 3

Я думаю, что вы в основном получили его, он отлично работает для меня.

Просто добавьте минимальное определение ширины так, чтобы оно не стало слишком маленьким.

if (/bottom|top/.test(placement)) {
  var delta = 0

  if (offset.left < 0) {
    delta       = offset.left * -2
    offset.left = 0

    $tip.offset(offset)

    actualWidth  = $tip[0].offsetWidth
    actualHeight = $tip[0].offsetHeight
  } 

  this.replaceArrow(delta - width + actualWidth, actualWidth, 'left');

} else {
    if (placement == 'left' && offset.left < 0) {
        var right = (  $(window).width() + 10) - ( offset.left + actualWidth ); 

        offset.left = 0;
        $tip.offset(offset);
        $tip.css({ 'right': right });
    }

    this.replaceArrow(actualHeight - height, actualHeight, 'top');    
}