Wrong value for window.innerWidth during onload event in Firefox for Android?

半世苍凉 提交于 2021-02-06 10:52:28

问题


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.

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.

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.

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?

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?

If anyone can tell me why only Firefox mobile seems to display this odd behavior I will give you a mental high five.

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...

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...

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.


回答1:


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>



回答2:


I can confirm the issue, for example in Firefox 38.0.1 on Android 4.1.2. Created a js bin for testing purposes.

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().

$('#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 :-)




回答3:


The problem (innerWidth === 980) persists for Firefox 40.0 under Android 4.4.4. A 1 msec wait is a circumvention. Replace

window.onload = myProgram; 
by
 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?




回答4:


I was facing the same issue while using BrowserComponent in CodeNameOne and Android

My solution was to put the js inside a function like so

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

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

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




回答5:


window.setTimeout(yourFunction, 1);

This did the job for me, 1ms is enough.



来源:https://stackoverflow.com/questions/28402100/wrong-value-for-window-innerwidth-during-onload-event-in-firefox-for-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!