web-dev-qa-db-fra.com

Changer la position des popovers Bootstrap en fonction de la position X du popover par rapport au bord de la fenêtre?

J'ai parcouru l'Internet de très loin et j'ai trouvé ce stackoverflow post perspicace Est-il possible de changer la position des popovers Bootstrap en fonction de la largeur de l'écran? , cela ne répond toujours pas à ma question, probablement à cause de mes difficultés à comprendre la position/décalage.

Voici ce que j'essaie de faire. Je souhaite que la position Twitter Bootstap Popover soit à DROITE, à moins que la fenêtre contextuelle de hotspot ne se positionne au-delà de la fenêtre d'affichage. Je souhaite ensuite qu'elle soit positionnée à GAUCHE. Je crée une application Web pour iPad qui comporte des points chauds. Lorsque vous appuyez sur un point chaud, des informations s'affichent, mais je ne souhaite pas qu'elles apparaissent en dehors de la fenêtre d'affichage lorsque le défilement horizontal est verrouillé.

Je pense que ça donnerait quelque chose comme ça:

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

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

Pensées? Merci!

78
j0e

Je viens de remarquer que l'option placement pourrait être une fonction string ou renvoyant une chaîne qui effectue le calcul chaque fois que vous cliquez sur un lien popover-capable.

Cela facilite la réplication de ce que vous avez fait sans la fonction $ .each initiale:

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

Selon la documentation, vous devriez pouvoir utiliser auto en combinaison avec l'emplacement préféré, par exemple. auto left

http://getbootstrap.com/javascript/#popovers : "Lorsque" auto "est spécifié, il réoriente dynamiquement le popover. Par exemple, si le placement est" auto gauche ", l'info-bulle s'affiche à gauche. si possible, sinon il affichera à droite. "

J'essayais de faire la même chose et je me suis rendu compte que cette fonctionnalité existait déjà.

31
Hamish Rouse

Pour Bootstrap 3, il y a

placement: 'auto right'

ce qui est plus facile. Par défaut, ce sera à droite, mais si l'élément est situé dans la partie droite de l'écran, le popover sera laissé. Donc ça devrait être:

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

J'ai donc trouvé un moyen de le faire efficacement. Pour mon projet particulier, je construis un site Web pour iPad afin de savoir exactement quelle serait la valeur en pixels X/Y pour atteindre le bord de l'écran. Vos valeurs thisX et thisY varieront.

Comme les popovers sont placés par un style en ligne de toute façon, je saisis simplement les valeurs de gauche et du haut de chaque lien pour décider dans quelle direction le popover doit être. Cela se fait en ajoutant les valeurs de données html5 que .popover () utilise lors de son exécution.

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

Tous les commentaires/améliorations sont les bienvenus, mais le travail est fait si vous êtes prêt à saisir les valeurs manuellement. 

5
j0e

la réponse de bchhun m'a mis sur la bonne voie, mais je voulais vérifier l'espace disponible entre la source et Edge. Je voulais également respecter l'attribut data-placement en tant que préférence avec des solutions de secours appropriées s'il n'y avait pas assez d'espace. De cette façon, "right" irait toujours bien sauf s'il n'y avait pas assez d'espace pour que le popover apparaisse à droite, par exemple. C'était la façon dont je l'ai géré. Cela fonctionne pour moi, mais c'est un peu lourd. Si quelqu'un a des idées pour une solution plus propre et plus concise, je serais intéressé de le voir.

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
chasingmaxwell

Vous pouvez aussi essayer celui-ci, 

==> Obtenir la position cible/source dans la fenêtre
==> Vérifier si l’espace en bas est inférieur à la hauteur de votre info-bulle
==> Si l'espace à partir du bas est inférieur à la hauteur de votre info-bulle, faites simplement défiler la page vers le haut. 

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";
}
1
Mohan Dere

En plus de l'excellente réponse de btc hun, si vous souhaitez un positionnement absolu, vous pouvez le faire.

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
apple16

J'ai résolu mon problème dans AngularJS comme suit: 

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

Cette fonction permet de positionner le flottant Bootstrap Popover dans la meilleure position, en fonction de la position de l'élément.

0
Gustavo Benício

Vous pouvez utiliser auto dans le placement de données comme data-placement = "auto left". Il s'ajustera automatiquement en fonction de la taille de votre écran et l'emplacement par défaut sera laissé.

0
Abhishek Anand