jQuery 根据弹出窗口相对于窗口边缘的 X 位置更改 Bootstrap 弹出窗口的位置?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9956958/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Changing the position of Bootstrap popovers based on the popover's X position in relation to window edge?
提问by j0e
I have scoured the Internet far and wide and while I found this stackoverflow post insightful Is it possible to change the position of Bootstrap popovers based on screen width?, it still didn't answer my question, likely due to my trouble understanding position/offset.
我已经在互联网上广泛搜索,虽然我发现这个 stackoverflow 帖子很有见地是否可以根据屏幕宽度更改 Bootstrap 弹出框的位置?,它仍然没有回答我的问题,可能是由于我无法理解位置/偏移量。
Here's what I'm trying to do. I want the Twitter Bootstap Popover position to be RIGHT unless the hotspot popover will be positioned beyond the viewport, then I want it to be positioned LEFT. I'm making an iPad web app that has hot spots, when you push on a hotspot, information appears but I don't want it to appear outside of the viewport when horizontal scrolling is locked.
这就是我想要做的。我希望 Twitter Bootstap Popover 的位置是 RIGHT,除非热点 popover 将被定位在视口之外,然后我希望它被定位在 LEFT。我正在制作一个有热点的 iPad 网络应用程序,当你按下一个热点时,信息会出现,但我不希望它在水平滚动被锁定时出现在视口之外。
I'm thinking it'd go something like this:
我想它会是这样的:
$('.infopoint').popover({
trigger:'hover',
animation: false,
placement: wheretoplace
});
function wheretoplace(){
var myLeft = $(this).offset.left;
if (myLeft<500) return 'left';
return 'right';
}
Thoughts? Thanks!
想法?谢谢!
回答by bchhun
I just noticed that the placementoption could either be a stringor a function returning a stringthat 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 $.eachfunction:
这使得在没有初始$.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);
回答by Hans Tiono
For Bootstrap 3, there is
对于 Bootstrap 3,有
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'
});
回答by Hamish Rouse
Based on the documentation you should be able to use auto
in combination with the preferred placement e.g. auto left
根据文档,您应该能够auto
与首选位置结合使用,例如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."
http://getbootstrap.com/javascript/#popovers: "当指定"auto"时,它会动态地重定向popover。例如,如果placement为"auto left",则工具提示将尽可能向左显示,否则它会正确显示。”
I was trying to do the same thing and then realised that this functionality already existed.
我试图做同样的事情,然后意识到这个功能已经存在。
回答by j0e
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.
所以我想出了一种有效地做到这一点的方法。对于我的特定项目,我正在构建一个 iPad 网站,因此我确切地知道到达屏幕边缘的像素 X/Y 值是多少。您的 thisX 和 thisY 值会有所不同。
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.
由于无论如何都会通过内联样式放置弹出框,因此我只需获取每个链接的左值和上值来决定弹出框应该朝哪个方向。这是通过附加 .popover() 在执行时使用的 html5 数据值来完成的。
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.
欢迎任何评论/改进,但如果您愿意手动输入值,这可以完成工作。
回答by chasingmaxwell
bchhun's answer got me on the right track, but I wanted to check for actual space available between the source and the viewport edge. I also wanted to respect the data-placement attribute as a preference with appropriate fallbacks if there wasn't enough space. That way "right" would always go right unless there wasn't enough space for the popover to show on the right side, for example. This was the way I handled it. It works for me, but it feels a bit cumbersome. If anyone has any ideas for a cleaner, more concise solution, I'd be interested to see it.
bchhun 的回答让我走上了正确的道路,但我想检查源和视口边缘之间的实际可用空间。如果没有足够的空间,我还想尊重 data-placement 属性作为具有适当回退的偏好。例如,除非没有足够的空间让弹出窗口显示在右侧,否则“正确”将始终向右。这就是我处理它的方式。它对我有用,但感觉有点麻烦。如果有人对更清洁、更简洁的解决方案有任何想法,我很想看看。
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);
回答by Mohan Dere
You can also try this one,
你也可以试试这个
==> Get target/source position in viewport
==> Check whether space from bottom is less that your tooltip height
==> If space from bottom is less that your tooltip height, then just scroll page up
==> 在视口中获取目标/源位置
==> 检查底部空间是否小于工具提示高度
==> 如果底部空间小于工具提示高度,则向上滚动页面
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";
}
回答by Suvra
$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 = '';
}
};
回答by Abhishek Anand
You can use auto in data placement like data-placement="auto left". It will automatic adjust according to your screen size and default placement will be left.
您可以在数据放置中使用 auto,例如 data-placement="auto left"。它将根据您的屏幕大小自动调整,并保留默认位置。
回答by apple16
In addition to bchhun's great answer, if you want absoulte positioning, you can do this
除了 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);
回答by Gustavo Benício
I solved my problem in AngularJS as follows:
我在 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
};
This function do the position of Bootstrap popover float to the best position, based on element position.
此函数根据元素位置将 Bootstrap popover 的位置浮动到最佳位置。