Changing the position of Bootstrap popovers based on the popover's X position in relation to window edge?

Solution 1:

I just noticed that the placement option could either be a string or a function returning a string that makes the calculation each time you click on a popover-able link.

This makes it real easy to replicate what you did without the initial $.each function:

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

Solution 2:

For Bootstrap 3, there is

placement: 'auto right'

which is easier. By default, it will be right, but if the element is located in the right side of the screen, the popover will be left. So it should be:

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

Solution 3:

Based on the documentation you should be able to use auto in combination with the preferred placement e.g. auto left

http://getbootstrap.com/javascript/#popovers: "When "auto" is specified, it will dynamically reorient the popover. For example, if placement is "auto left", the tooltip will display to the left when possible, otherwise it will display right."

I was trying to do the same thing and then realised that this functionality already existed.

Solution 4:

So I figured out a way to do this effectively. For my particular project I'm building an iPad website so I knew exactly what the pixel X/Y value would be to reach the edge of the screen. Your thisX and thisY values will vary.

Since the popovers are being placed by inline styling anyway, I simply grab the left and top values for each link to decide which direction the popover should be. This is done by appending html5 data- values that .popover() uses upon execution.

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

Any comments/improvements are welcome but this gets the job done if you're willing to put the values in manually.