?
Solved

jQuery $(window).width() working only in Firefox

Posted on 2013-01-02
13
Medium Priority
?
731 Views
Last Modified: 2013-01-05
I have put together a function to get screen width and a rough estimate of download speed and write those values to hidden textbox.

Then, I intend to access the values in .net to deliver best resolution images to the user.

The code works in Firefox, but not IE or Chrome. In the page, I have only included the min jquery file below.

<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>

Here is the javascript...


 
     function getSpeedWidth() {
            var w = $(window).width();
            var h = $(window).height();
            document.getElementById('txtScrnWidth').value = w;
            document.getElementById('txtScrnHeight').value = h;

            var imageAddr = "../images/Logo_UMS_Trans.png";
            var startTime, endTime;
            var downloadSize = 19865.6;
            var download = new Image();
            download.onload = function () {
                endTime = (new Date()).getTime();
                var duration = (endTime - startTime) / 1000;
                var bitsLoaded = downloadSize * 8;
                var speedBps = (bitsLoaded / duration).toFixed(2);
                var speedKbps = (speedBps / 1024).toFixed(2);
                document.getElementById('txtSpeed').value = speedKbps;
            }
            startTime = (new Date()).getTime();
            download.src = imageAddr;
        }
 

Open in new window

0
Comment
Question by:hitman3030
  • 9
  • 3
13 Comments
 
LVL 17

Expert Comment

by:sonawanekiran
ID: 38735835
The problem is your onload function executes asynchronously.  here is solution to your problem

http://stackoverflow.com/questions/8645143/wait-for-image-to-be-loaded-before-going-on
0
 

Author Comment

by:hitman3030
ID: 38738637
I'm getting closer. I added "when done"  to the code and cleaned everything up. It still only works in Firefox, so I must be missing something. Javascript is my third language and I am struggling with this.

Here is the modified code:
      function getSpeedSize() {
            var startTime, endTime;
            var img = new Image();
            var downloadSize = 19866.6;
            var imageAddr = "../images/Logo_UMS_Trans.png" + "?n=" + Math.random();
            startTime = (new Date()).getTime();
            img.src = imageAddr;
            $.when(img.onload).done(function () {
                // callback when file is loaded
                endTime = (new Date()).getTime();
                storeValues(downloadSize, startTime, endTime);
            })
        }

        function storeValues(downloadSize, startTime, endTime) {
            var duration = (endTime - startTime) / 1000;
            var bitsLoaded = downloadSize * 8;
            var speedBps = (bitsLoaded / duration).toFixed(2);
            var speedKbps = (speedBps / 1024).toFixed(2);
            document.getElementById('txtSpeed').value = speedKbps;
            getHeightWidth();
        }
  
        function getHeightWidth() {
            var w = $(window).width();
            var h = $(window).height();
            document.getElementById('txtScrnWidth').value = w;
            document.getElementById('txtScrnHeight').value = h;
        }

Open in new window

0
 

Author Comment

by:hitman3030
ID: 38738670
In the jQuery docs I found this: "If a single argument is passed to jQuery.when and it is not a Deferred, it will be treated as a resolved Deferred and any doneCallbacks attached will be executed immediately. "

I am only passing one argument. Is there a way to still make it defer? Do I have to load two graphics? Is there a simple "space holder" argument that I can pass to "up the count" but not actually do anything to slow that function?
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 

Author Comment

by:hitman3030
ID: 38738729
As a test, I added an additional image to download, but no change.
0
 
LVL 11

Expert Comment

by:mcnute
ID: 38739536
WHERE and WHEN do you call the functions above in your code?
0
 

Author Comment

by:hitman3030
ID: 38741061
I've tried three variations:

1) adding it to the BODY tag onload event
2) putting it just after the HEAD tag without wrapping it in a function declaration so that it would execute as soon as encountered
3) placing a Query(document).load call just after the HEAD tag.

All three produce the same end result. All works only in FFox only.
0
 
LVL 11

Expert Comment

by:mcnute
ID: 38741152
Can you post full code please within the code method in the comment box? If not I have a fourth option for you:

put your function into a <script></script> tag on the bottom of your page just behind your <body> tag. So it is between the closing body and html tag. What happens then?

And I strongly suggest you to use Chrome Developer Tools and click on the console tab in it and reload the page, so you can see which error is being thrown exactly. Or use the IE Developer Tools pressing F12 in IE  7+. There the same, click the console tab and reload page with Tools open and see which error is being thrown into console.

Hope that helps debugging! If you tell us, we can help even better. Or can you provide a link, this would be an Experts dream ;-)
0
 

Author Comment

by:hitman3030
ID: 38742557
I moved the js to the location you suggested. Still only works in FFox. I debugged in IE and did not get any errors. I could step through each line. I have to admit when it opened the jquery file to trace that code, it was hard to follow.

At one time, I thought the fields may not be loaded at the time it's setting value. I have the hidden fields at the top of the page just after the BODY and FORM tags and have the JS at the bottom just before the HTML tag  now.

The page is loaded at this url: upmyscore.com/lp/

Here are the blocks of code:

</head>
<body style="margin-top:-25px;" >
    <form id="form1" runat="server">
        <input type="hidden" runat="server" id="txtScrnWidth" name="txtScrnWidth" />
        <input type="hidden" runat="server" id="txtScrnHeight" name="txtScnHeight" />
        <input type="hidden" runat="server" id="txtSpeed" name="txtSpeed" />

Open in new window


Then at the bottom:

</body>
<script>
    var startTime, endTime;
    var img1 = new Image();
    var downloadSize1 = 19866.6;
    var imageAddr1 = "../images/Logo_UMS_Trans.png" + "?n=" + Math.random();
    var img2 = new Image();
    var downloadSize2 = 19866.6;
    var imageAddr2 = "../images/Logo_UMS_Trans.png" + "?n=" + Math.random();
    startTime = (new Date()).getTime();
    downloadSize = downloadSize1 + downloadSize2;
    img1.src = imageAddr1;
    img2.src = imageAddr2;
    $.when(img1.onload, img2.onload).done(function () {
        // callback when everything was loaded
        endTime = (new Date()).getTime();
        storeValues(downloadSize, startTime, endTime);
    })


    function storeValues(downloadSize, startTime, endTime) {
        var duration = (endTime - startTime) / 1000;
        var bitsLoaded = downloadSize * 8;
        var speedBps = (bitsLoaded / duration).toFixed(2);
        var speedKbps = (speedBps / 1024).toFixed(2);
        document.getElementById('txtSpeed').value = speedKbps;
        getHeightWidth();
    }

    function getHeightWidth() {
        var w = $(window).width();
        var h = $(window).height();
        document.getElementById('txtScrnWidth').value = w;
        document.getElementById('txtScrnHeight').value = h;
    }

</script>
</html>

Open in new window

0
 

Author Comment

by:hitman3030
ID: 38742603
As I continue to debug it in IE, I can see that the code is executing a second time immediately on completion of the first, but I don't know why.
0
 

Author Comment

by:hitman3030
ID: 38742778
I can confirm that the three values are present in all browsers (width, height, speed). In debug, the value is assigned to the hidden field (ie  document.getElementById('txtScrnWidth').value = w;)...
But there is no value when you look at the source code after loading, except for FFox.)

Since I have the values, is there a better way to make them available to .net. (I'm coding in vb)
Maybe stuff them in an array saved in a cookie? I was trying to avoid cookies here. Thanks for any ideas.
0
 

Author Comment

by:hitman3030
ID: 38743064
BREAK THROUGH: The code will work as originally posted if I assign the values to a regular textbox. It is the hidden field that does not work. I have no idea why. I placed them both together on the page and tested and retested. The hidden fields show the value in FFox only while the regular textbox shows values in all browsers I tested.

Also, I dropped the jQuery "when done"
Here is the final code placed in the HEAD tag:

<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<script>
    var imageAddr = "../images/Logo_UMS_Trans.png" + "?n=" + Math.random();
    var startTime, endTime;
    var downloadSize = 19866.6;
    var download = new Image();
    download.onload = function () {
        endTime = (new Date()).getTime();
        storeValues();
    }
    startTime = (new Date()).getTime();
    download.src = imageAddr;

    function storeValues() {
        var duration = (endTime - startTime) / 1000;
        var bitsLoaded = downloadSize * 8;
        var speedBps = (bitsLoaded / duration).toFixed(2);
        var speedKbps = (speedBps / 1024).toFixed(2);
        document.getElementById('txtSpeed1').value = speedKbps;
        getHeightWidth()
    }

    function getHeightWidth() {
        var w = $(window).width();
        var h = $(window).height();
        var newH = document.createElement('input');
        document.getElementById('txtScrnWidth1').value = w;
        document.getElementById('txtScrnHeight1').value = h;
    }

</script>

Open in new window

0
 
LVL 11

Accepted Solution

by:
mcnute earned 1500 total points
ID: 38743140
Hello again. Now I can help you better.

First I would recommend to clean up your code according to w3c validator. Always a good idea.
W3C-Errors and Fixing

Second:
Since you have jquery already there, I would do the following changes to your code which I tested on a IE 8.
$(function(){
    var startTime, endTime;
    var img1 = new Image();
    var downloadSize1 = 19866.6;
    var imageAddr1 = "../images/Logo_UMS_Trans.png" + "?n=" + Math.random();
    var img2 = new Image();
    var downloadSize2 = 19866.6;
    var imageAddr2 = "../images/Logo_UMS_Trans.png" + "?n=" + Math.random();
    startTime = (new Date()).getTime();
    downloadSize = downloadSize1 + downloadSize2;
    img1.src = imageAddr1;
    img2.src = imageAddr2;

    endTime = (new Date()).getTime();
    storeValues(downloadSize, startTime, endTime);
 

    function storeValues(downloadSize, startTime, endTime) {
        var duration = (endTime - startTime) / 1000;
        var bitsLoaded = downloadSize * 8;
        var speedBps = (bitsLoaded / duration).toFixed(2);
        var speedKbps = (speedBps / 1024).toFixed(2);
        $('#txtSpeed').val(speedKbps);
        getHeightWidth();
    }

    function getHeightWidth() {
        var w = $(window).width();
        var h = $(window).height();
        $('#txtScrnWidth').val(w);
        $('#txtScrnHeight').val(h);
    }

});

Open in new window


The problem was that the onload function was never triggered so the storeValues function never was executed. By wrapping that into a jqeury onload function altogether you get by this issue. I've worked with the code you have on your website, there it is stlightly different. Let me know if the issue continues.
0
 

Author Closing Comment

by:hitman3030
ID: 38746369
This worked! I had to add the img.onload(function)  back into the code to make it wait before setting an end time. Otherwise, the speed calc was before the file finished downloading. Thanks.

I also ended up storing this in a cookie.
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction If you're like most people, you have occasionally made a typographical error when you're entering information into an online form.  And to your consternation, the browser remembers the error, and offers to autocomplete your future entr…
Introduction JSON is an acronym for JavaScript Object Notation.  It is a text-string data transport mechanism, capable of representing simple or complex data structures in a consistent and easy-to-read manner.  Similar in concept to XML, but more e…
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
Suggested Courses
Course of the Month15 days, 8 hours left to enroll

850 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question