Ändern der Position von Bootstrap-Popovers basierend auf der X-Position des Popovers in Bezug auf die Fensterkante?


83

Ich habe das Internet weit und breit durchsucht und fand diesen Stackoverflow-Beitrag aufschlussreich. Ist es möglich, die Position von Bootstrap-Popovers basierend auf der Bildschirmbreite zu ändern? Ich habe meine Frage immer noch nicht beantwortet, wahrscheinlich aufgrund meines Problems, Position / Versatz zu verstehen.

Folgendes versuche ich zu tun. Ich möchte, dass die Twitter-Bootstap-Popover-Position RECHTS ist, es sei denn, das Hotspot-Popover wird außerhalb des Ansichtsfensters positioniert, und ich möchte, dass es LINKS positioniert wird. Ich erstelle eine iPad-Web-App mit Hotspots. Wenn Sie auf einen Hotspot klicken, werden Informationen angezeigt, aber ich möchte nicht, dass sie außerhalb des Ansichtsfensters angezeigt werden, wenn das horizontale Scrollen gesperrt ist.

Ich denke, es würde ungefähr so ​​gehen:

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

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

Gedanken? Vielen Dank!

Antworten:


177

Mir ist gerade aufgefallen, dass die Platzierungsoption entweder eine Zeichenfolge oder eine Funktion sein kann, die eine Zeichenfolge zurückgibt, die die Berechnung jedes Mal durchführt, wenn Sie auf einen Popover-fähigen Link klicken.

Dies macht es wirklich einfach, das zu replizieren, was Sie ohne die anfängliche Funktion $ .each getan haben :

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
Dies ist der beste Weg, da autodies je nach Seitenlayout und Inhalt, den Sie in das Popover einfügen, nicht immer einwandfrei funktioniert.
Bron Davies

Danke dafür. Ist es in Ordnung, wenn wir es ohne Zuschreibung an Sie verwenden?
D.Tate

6
@ D.Tate Ich glaube, dass alles, was mit Stackoverflow zu tun hat, ohne Namensnennung verwendet werden kann. Gehen Sie verrückt damit;)
bchhun

3
Was ist die Logik der Wahl von left 515&top 110
Murali Murugesan

1
@MuraliMurugesan überhaupt keine Logik; Ich habe lediglich die in der Frage angegebenen Nummern verwendet. Sie können verwenden, was Sie wollen.
Bchhun

33

Für Bootstrap 3 gibt es

placement: 'auto right'

das ist einfacher. Standardmäßig ist es rechts, aber wenn sich das Element auf der rechten Seite des Bildschirms befindet, bleibt das Popover übrig. So sollte es sein:

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

2
Ich habe bisher gemischte Erfahrungen damit gemacht. Ich habe mir die Bootstrap-Quelle noch nicht angesehen, aber es sieht so aus, als würde nur die Elementpositionierung berücksichtigt und nicht die zukünftige Position des Popovers. Elemente, die sich am Rand oder hinter dem Fensterrand befinden, erhalten also höchstens ein Popover am Rand, aber Elemente, die sich (beispielsweise) direkt über dem Rand befinden, erhalten ein Popover unterhalb der Falte.
Daved

1
Nein, es sollte nicht die akzeptierte Antwort sein. Die Option "Platzierung" berücksichtigt nicht die Fensterkanten, sondern nur die Grenzen des übergeordneten Elements / Containers. Wenn Sie also z. B. "Auto Top" haben, wird es beim Scrollen nach unten immer noch im oberen Fenster angezeigt.
RZB

31

Basierend auf der Dokumentation sollten Sie in der Lage sein, autoin Kombination mit der bevorzugten Platzierung zu verwenden, zauto left

http://getbootstrap.com/javascript/#popovers : "Wenn" auto "angegeben ist, wird das Popover dynamisch neu ausgerichtet. Wenn die Platzierung beispielsweise" auto left "ist, wird der Tooltip nach Möglichkeit links angezeigt es wird rechts angezeigt. "

Ich habe versucht, dasselbe zu tun, und dann festgestellt, dass diese Funktionalität bereits vorhanden ist.


2
Auto links gibt horizontale Bildlaufleiste
Jitendra Vyas

3
Sie können auch a angeben, viewportwenn Sie nicht möchten, dass es basierend auf dem übergeordneten Element berechnet wird.
Allicarn

5

Also habe ich einen Weg gefunden, dies effektiv zu tun. Für mein spezielles Projekt baue ich eine iPad-Website, damit ich genau wusste, wie hoch der Pixel-X / Y-Wert sein würde, um den Bildschirmrand zu erreichen. Ihre thisX- und thisY-Werte variieren.

Da die Popover ohnehin durch Inline-Styling platziert werden, greife ich einfach zu den linken und oberen Werten für jeden Link, um zu entscheiden, in welche Richtung das Popover gehen soll. Dies erfolgt durch Anhängen von HTML5-Datenwerten, die .popover () bei der Ausführung verwendet.

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

Kommentare / Verbesserungen sind willkommen, aber dies erledigt den Job, wenn Sie bereit sind, die Werte manuell einzugeben.


2

Die Antwort von bchhun brachte mich auf den richtigen Weg, aber ich wollte überprüfen, ob tatsächlich Platz zwischen der Quelle und dem Rand des Ansichtsfensters verfügbar ist. Ich wollte auch das Datenplatzierungsattribut als Präferenz mit geeigneten Fallbacks berücksichtigen, wenn nicht genügend Speicherplatz vorhanden war. Auf diese Weise würde "richtig" immer nach rechts gehen, es sei denn, es wäre nicht genügend Platz für das Popover vorhanden, um es beispielsweise auf der rechten Seite anzuzeigen. So habe ich damit umgegangen. Es funktioniert bei mir, aber es fühlt sich etwas umständlich an. Wenn jemand Ideen für eine sauberere und präzisere Lösung hat, würde mich das interessieren.

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

Sie können auch versuchen,

==> Ziel- / Quellposition im Ansichtsfenster abrufen
==> Überprüfen Sie, ob der Abstand von unten kleiner als Ihre QuickInfo-Höhe ist
==> Wenn der Abstand von unten kleiner als Ihre Tooltip-Höhe ist, scrollen Sie einfach die Seite nach oben

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

Sie können Auto bei der Datenplatzierung verwenden, z. B. Datenplatzierung = "Auto links". Es wird automatisch an Ihre Bildschirmgröße angepasst und die Standardplatzierung bleibt erhalten.


0

Zusätzlich zu Bchhuns großartiger Antwort können Sie dies tun, wenn Sie eine Absoulte-Positionierung wünschen

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

Ich habe mein Problem in AngularJS wie folgt gelöst:

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

Mit dieser Funktion wird die Position des Bootstrap-Popover-Floats basierend auf der Elementposition an die beste Position verschoben.


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

Sie können dieses auch ausprobieren, wenn Sie es an fast allen Stellen auf der Seite benötigen.

Sie können es allgemein konfigurieren und dann einfach verwenden.

Auf diese Weise können Sie auch HTML-Elemente und alles verwenden, was Sie wollen :)

$(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>

Zusatz


Um weitere Optionen festzulegen, können Sie hier klicken .

Noch mehr finden Sie hier .

Aktualisieren


Wenn Sie das Popup nach dem Klicken möchten, können Sie die JS-Option folgendermaßen trigger: "click"ändern:

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

Sie können es auch in HTML-Anzeigen data-trigger="click"wie folgt anpassen:

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

Ich denke, es wird mehr orientierter Code und wiederverwendbarer und für alle hilfreicher sein :).

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.