javascript 在 Firefox for Android 中的 onload 事件期间 window.innerWidth 的值错误?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28402100/
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
Wrong value for window.innerWidth during onload event in Firefox for Android?
提问by Frank
Okay, so, the problem I am facing is this: my mobile Firefox browser is not retrieving the correct values for window.innerWidth
, document.documentElement.clientWidth
, or even the width of a div
styled to take up the whole client window after page load.
好了,所以,我所面临的问题是这样的:我的手机火狐浏览器不检索正确的价值观window.innerWidth
,document.documentElement.clientWidth
,的甚至宽度div
风格的页面加载后,占据整个客户端窗口。
I am not crazy, my code works just fine in every other browser! For some reason Firefox initializes these values with defaults and then gets the correct values later on. If at any point I interrupt my JavaScript with an alert()
, these properties magically become accurate afterwards.
我没有疯,我的代码在其他所有浏览器中都能正常工作!出于某种原因,Firefox 使用默认值初始化这些值,然后稍后获取正确的值。如果在任何时候我用 中断了我的 JavaScript alert()
,这些属性之后会神奇地变得准确。
I have scoured the internet for an answer and all I can find is a hack workaround: use window.setTimeout
to delay the use of these properties until they have time to populate correctly. That is crazy! Users want speed, not an extra delay just to view my site on a Firefox browser.
我已经在互联网上搜索了答案,我能找到的只是一个 hack 解决方法:用于window.setTimeout
延迟这些属性的使用,直到它们有时间正确填充。这很疯狂!用户想要速度,而不是仅仅为了在 Firefox 浏览器上查看我的网站而带来的额外延迟。
What I don't understand is that I can set a div
up to fill the client window perfectly before the values become accurate. I do this in css by setting width and height of my div's id to 100%. document.documentElement
is basically the same as document.getElementById("my_div");
after all the document elements have loaded, so, how does the browser know how big the div
should be when it doesn't have the correct dimensions of the client window in the first place?
我不明白的是,我可以设置一个设置div
来在值变得准确之前完美地填充客户端窗口。我在 css 中通过将 div id 的宽度和高度设置为 100% 来做到这一点。document.documentElement
与document.getElementById("my_div");
加载所有文档元素后基本相同,因此,当浏览器div
首先没有正确的客户端窗口尺寸时,它如何知道应该有多大?
I have tried running my code inside a window.addEventListener("load",function(event_){ //My Code });
but still these values will not generate. Is there a page load event that comes after window.onload
?
我试过在 a 中运行我的代码,window.addEventListener("load",function(event_){ //My Code });
但仍然不会生成这些值。之后是否有页面加载事件window.onload
?
If anyone can tell me why only Firefox mobile seems to display this odd behavior I will give you a mental high five.
如果有人能告诉我为什么只有 Firefox mobile 会显示这种奇怪的行为,我会给你打五分。
Here's a bit of sample code for recreating the problem:
下面是一些重现问题的示例代码:
<!DOCTYPE HTML>
<html>
<head>
<!-- Added " after javascript during edit. -->
<script type="text/javascript">
window.addEventListener("load",function(event_){
var output=document.getElementById("output");
/* Returns some default value like 980. */
output.innerHTML=window.innerWidth;
alert("After this alert, the value will change.");
/* Returns an accurate value like 511. */
output.innerHTML=window.innerWidth;
});
</script>
<!-- Added title during edit. -->
<title>Title</title>
</head>
<body>
<p id="output">Default Output</p>
</body>
</html>
My Firefox for android version is 35.0.1. My Android version is 4.4.4. On my device, Firefox displays "980" in the output p element, shows the alert, and then displays "980" again. After page refresh, the first two steps remain the same, but the output after the alert changes to 360. This happens with document.documentElement.clientWidth
as well. No properties I try seem to get the correct values. It seems that Firefox has some sort of delay after page load before it has access to the client window's dimensions...
我的 Firefox for android 版本是 35.0.1。我的安卓版本是 4.4.4。在我的设备上,Firefox 在输出 p 元素中显示“980”,显示警报,然后再次显示“980”。页面刷新后,前两步保持不变,但alert后的输出变为360。这种情况也发生document.documentElement.clientWidth
。我尝试的任何属性似乎都没有得到正确的值。似乎 Firefox 在页面加载后有某种延迟,然后才能访问客户端窗口的尺寸......
I tried the verge.airve.com plugin without JQuery and its initial feedback remained at 980. It also initialized as 980 on Chrome, which was weird, because Chrome worked as expected without it...
我在没有 JQuery 的情况下尝试了 verge.airve.com 插件,它的初始反馈仍然是 980。它也在 Chrome 上初始化为 980,这很奇怪,因为 Chrome 没有它就按预期工作......
After much debate a solution was found! Firefox apparently resizes the window after it is loaded (I guess for good measure, who really knows)! So, by adding a resize event handler in addition to window.onload, this problem can be averted! See accepted answer below for more details.
经过一番讨论,终于找到了解决办法!Firefox 在加载后显然会调整窗口大小(我想这是一个很好的衡量标准,谁真的知道)!因此,通过在 window.onload 之外添加一个 resize 事件处理程序,可以避免这个问题!有关更多详细信息,请参阅下面接受的答案。
回答by MaxZoom
Make sure your measurement is done when whole document is loaded and resized.
确保在整个文档加载和调整大小时完成测量。
window.onload = showViewport;
window.onresize = showViewport;
function showViewport() {
var output=document.getElementById("output");
var width = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
var height= Math.max(document.documentElement.clientHeight, window.innerHeight || 0)
output.innerHTML = "Viewport size is " + width + "x" + height;
}
<body>
<p id="output">Default Output</p>
</body>
回答by bencergazda
I can confirm the issue, for example in Firefox 38.0.1 on Android 4.1.2. Created a js binfor testing purposes.
我可以确认该问题,例如在 Android 4.1.2 上的 Firefox 38.0.1 中。创建了一个js bin用于测试目的。
I'd like to check window.innerWidth for custom DOM manipulations on different resolutions (mobile, tablet and desktop size), so it'd be important to get the correct window.innerWidth value already in the document.ready() state and not just only in the window.load().
我想检查 window.innerWidth 以在不同分辨率(移动设备、平板电脑和桌面大小)上进行自定义 DOM 操作,因此重要的是在 document.ready() 状态中获取正确的 window.innerWidth 值而不是仅在 window.load() 中。
$('#inline').html($(window).width());
$(document).ready(function() {
$('#ready').html(window.innerWidth);
});
$(window).load(function() {
$('#load').html(window.innerWidth);
});
setTimeout(function() {
$('#setTimeout').html(window.innerWidth);
}, 1000);
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>JS Bin</title>
</head>
<body>
<p><span id="inline"></span></p>
<p>$(document).ready(): <span id="ready"></span></p>
<p>$(window).load(): <span id="load"></span></p>
<p>setTimeout(1000): <span id="setTimeout"></span></p>
</body>
</html>
(I wanted to add only a comment, and not answer, but no reputations yet to do so :-)
(我只想添加评论,而不是回答,但还没有声誉这样做:-)
回答by P. Wormer
The problem (innerWidth === 980) persists for Firefox 40.0 under Android 4.4.4. A 1 msec wait is a circumvention. Replace
在 Android 4.4.4 下,Firefox 40.0 的问题 (innerWidth === 980) 仍然存在。1 毫秒的等待是一种规避。代替
window.onload = myProgram;经过
window.onload = function() {setTimeout(myProgram, 1)};
In the meantime I encountered this problem while adapting a fairly elaborate site to small screens. Firefox obeys the CSS following "@media only screen and (max-width: 768px)". However, when one tries to set event handlers depending on device widths, Firefox fails miserably. I needed the above trick with 0.5 second wait at all spots where I picked up the device width. This wait time was necessary for Nexus 7 (2012), but who knows what is needed for other devices?
与此同时,我在将一个相当复杂的网站适应小屏幕时遇到了这个问题。Firefox 遵循“@media only screen and (max-width: 768px)”的 CSS。然而,当人们试图根据设备宽度设置事件处理程序时,Firefox 就会惨遭失败。我需要在我拿起设备宽度的所有位置等待 0.5 秒的上述技巧。这个等待时间对于 Nexus 7 (2012) 来说是必要的,但谁知道其他设备需要什么?
回答by JAnton
I was facing the same issue while using BrowserComponent
in CodeNameOne
and Android
我在使用BrowserComponent
inCodeNameOne
和 Android 时遇到了同样的问题
My solution was to put the js inside a function like so
我的解决方案是将 js 放在像这样的函数中
function runScripts()
{
//get width here
}
And listen to the onLoad
event of the BrowserComponent
to execute this script once the browser has been fully loaded
并在浏览器完全加载后监听以执行此脚本的onLoad
事件BrowserComponent
like so:
像这样:
BrowserComponent browser = new BrowserComponent();
browser.addWebEventListener("onLoad", new ActionListener() {
public void actionPerformed(ActionEvent evt) {
browser.execute("runScripts()");
}
});
browser.setURL("http://www.URL.com");
Handling window.onload
in the html wasn't enough to wait for the appropriate width to be served
window.onload
在 html 中处理不足以等待提供适当的宽度
Besides this solution I also found that window.setTimeout(runScripts, 500);
works to get the right document width, at the expense of wasting half a second
除了这个解决方案,我还发现它window.setTimeout(runScripts, 500);
可以获得正确的文档宽度,代价是浪费了半秒
回答by Yung Ab
window.setTimeout(yourFunction, 1);
This did the job for me, 1ms is enough.
这对我来说完成了工作,1ms 就足够了。