类似于jQuery.offset()的纯JavaScript函数?

17
在俄罗斯社交网络Ok.ru的小型iframe应用程序中,我使用以下调用来调整iframe大小:
<div id="fb-root"></div> 
<script src="http://api.odnoklassniki.ru/js/fapi.js" 
type="text/javascript"></script> 
<script type="text/javascript"> 
FAPI.init("http://api.odnoklassniki.ru/", "XXX_YYY",
function() {
        alert("clientHeight " + document.getElementById("fb-root").clientHeight);
        alert("offsetHeight " + document.getElementById("fb-root").offsetHeight);
        FAPI.UI.setWindowSize(720, 1200);
}, function(error){
        alert("API initialization failed");
});
</script> 
</body> 
</html>

即目前iframe高度是硬编码为1200

虽然它能正常工作,但我想使用#fb-root元素的高度/位置。

请问有人知道可以在这里使用哪个JavaScript或CSS函数吗?如果我不想仅为一个$(#fb-root).offset()调用而包含jQuery

我还查看了他们的库http://api.odnoklassniki.ru//js/fapi.js,但它不包括这样的函数。

更新

我已经在我的源代码中添加了两个警报调用,但它们只会打印出

clientHeight 0
offsetHeight 0

更新

以下代码似乎在 Google Chrome 和 Mozilla Firefox 中为我的 iframe 应用程序正常工作,无论我添加多少个
进行测试。但在 Internet Explorer 中,它无法调整窗口大小,并显示 alert top=1107(而不是 Google Chrome 中的 top=1157),因此底部的 html 表格被截断:

preferans

... here my flash game + html table with players ...
<br>
<br>
<br>
<br>
<br>
<br>
<div id="fb-root"></div>
<script src="http://api.odnoklassniki.ru/js/fapi.js" type="text/javascript"></script>
<script type="text/javascript">
FAPI.init("http://api.odnoklassniki.ru/", "XXX_YYY",
function() {
        var top = findTop(document.getElementById("fb-root"));
        FAPI.UI.setWindowSize(720, Math.max(top, 1200));
}, function(error){
        alert("API initialization failed");
});
function findTop(obj) {
        if(!obj) return 0;
        return obj.offsetTop + findTop(obj.offsetParent);
}
</script>

</body>
</html>

3
请不要发布需要注册的网址,也不要发布俄语网址……这很无用。请注意修改文本以使其更通俗易懂,但不要改变原来的意思。 - gblazex
1
Facebook的问题怎么样?这里有很多,需要注册才能查看。 - Alexander Farber
但是每个人都在FB上,所以如果你想帮忙,它并不需要你注册。而且它肯定不只是俄语。 :) - gblazex
3
无论是俄罗斯、匈牙利还是美国的社交网络,都无关紧要。我一直在尝试解决一个JavaScript/iframe问题,并且已经在开始和之后提供了足够的信息。如果您查看我在Stackoverflow上的其他问题,您会发现我总是这样做(提供足够的信息和测试用例,并在询问任何问题时回应每个评论)。 - Alexander Farber
4个回答

26

查看jQuery中的代码,偏移量是这样计算的:

function getOffset(element)
{
    if (!element.getClientRects().length)
    {
      return { top: 0, left: 0 };
    }

    let rect = element.getBoundingClientRect();
    let win = element.ownerDocument.defaultView;
    return (
    {
      top: rect.top + win.pageYOffset,
      left: rect.left + win.pageXOffset
    });   
}


1
非常感谢,它节省了我很多时间。 - Mayur Kukadiya

10

Quirksmode有一个JavaScript教程/函数,展示了如何找到元素的坐标,在此处查看

一旦你拥有它的坐标,你可以使用iframe的offsetHeight属性来读取它的高度。


这似乎是一个可靠的解决方案,因为它从元素通过所有容器遍历DOM,即使所讨论的元素高度为零,只要其中一些容器具有高度,它也应该能够正常工作。有什么想法可以解释为什么它被投票否决了吗? - brennanyoung
谢谢你的回答,我已经用可运行的代码更新了我的问题。有什么想法为什么它在MSIE上失败了吗? - Alexander Farber
我建议在window.load事件中尝试调用findTop函数,或者在单独的按钮调用中尝试,以查看是否会得到不同的信息。我听说过如果IE仍在加载dom,则可能会给出错误的偏移属性信息。另一个尝试的方法是为“fb-root” div设置position:relative,并查看是否会得到不同的答案。如果这样做,请还要检查html元素的margin和padding。 - patorjk

1
如果document.getElementById("fb-root").clientHeight返回0,那肯定意味着你的"fb-root" div要么没有显示,要么还是空的。
我已经查看了fapi.js,它似乎调用FAPI.init函数会创建一个id为"FAPI_Flash_wrap"的span,将其附加到文档的body中,然后在此span中嵌入一个id为"FAPI_Flash"的flash对象。

So I would try retrieving an element with id "FAPI_Flash_wrap" or "FAPI_Flash" instead of "fb-root":

<script type="text/javascript">
FAPI.init("http://api.odnoklassniki.ru/", "XXX_YYY",
function() {
    alert("Height = " + document.getElementById("FAPI_Flash_wrap").offsetHeight);
    alert("Width = " + document.getElementById("FAPI_Flash_wrap").offsetWidth);
    FAPI.UI.setWindowSize(720, 1200);
}, function(error){alert("API initialization failed");}
);
</script>
I hope this works!

如果是这种情况,那么就使用它。
<script type="text/javascript">
FAPI.init("http://api.odnoklassniki.ru/", "XXX_YYY",
function() {
    var height = document.getElementById("FAPI_Flash_wrap").offsetHeight;
    var width = document.getElementById("FAPI_Flash_wrap").offsetWidth;
    FAPI.UI.setWindowSize(width, height);
}, function(error){alert("API initialization failed");}
);
</script>

抱歉,警报根本没有出现,页面也没有被调整大小。在Firebug控制台中,我看到许多警告,但没有相关的错误。当我将我的原始代码放回,并硬编码高度时 - 然后它突然可以正常工作。 - Alexander Farber
嗯,奇怪。如果您在Firebug命令行中尝试“alert(document.getElementById(someID));”,它必然会弹出“[object someInterfaceName]”或“null”,因此您可以检查此时是否存在id为“someID”的元素。如果“FAPI_Flash_wrap”和“FAPI_Flash”都不存在,则成功加载游戏后页面的完整HTML可能会有所帮助。 - Luc125

0
使用 offsetHeightclientHeight 来获取 div 的高度:
document.getElementById("fb-root").offsetHeight // including border
document.getElementById("fb-root").clientHeight // excluding border 

使用offsetLeftoffsetTop来获取div相对于其offsetParent的位置。 offsetParent是第一个父级盒子,它的position样式为fixed、relative或absolute。

谢谢,但是getElementById()在所有主流浏览器中都能正常工作吗? - Alexander Farber
是的,几乎所有浏览器都支持 getElementById请参阅此链接 - baotuo
不幸的是,由于某种原因,offsetHeight和clientHeight都被打印为0-请参见我的更新问题。 - Alexander Farber
你确定在获取 #fb-root 的高度时它已经有内容了吗?如果你使用 Safari 或 Chrome(或者在 Firefox 中使用 FireBug),你可以在开发者工具的控制台中运行 document.getElementById("fb-root").offsetHeight 来检查它是否有效。祝好运。 - baotuo
fb-root没有内容,但是当我把xxx放进去时:<div id="fb-root">xxx</div> - 什么也不会改变。Firebug控制台打印:[06:44:17.768] TypeError: document.getElementById("fb-root")为空 - Alexander Farber
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接