Sunday 29 April 2012

Web script measuring sizes of images or divs breaks the first time, but not the rest with Javascript or JQuery

Problem:

A script that uses the width or height function to measure a loaded div or an image seems to break the first time the page is loaded, but not any subsequent times.

Possible diagnosis:

There are actually two problems in the above situation. The first problem is that the bug seemingly cannot be reproduced. The second problem is that the script will break for any users seeing the containing page for the first time.

One situation where this can occur is because the script is run by the browser prior to an image being loaded. For instance, the following example script can have this error occur:

$(document).ready(function(){
var divWidth = $("#mydivwithanimage").width();
doSomethingImportantWithWidth(divWidth);
});

The reason this script fails is because even though JQuery waits until the DOM is loaded prior to executing this script, this doesn't necessarily mean that other page components being loaded, such as images, have completed loading before this script is run. This leads to the funny problem that the script will only fail the first time it is run in an open browser, as the browser will cache all loaded images and other page components and often load them before the script is run when the page is reloaded.

Solution (for debugging):

The solution to reproducing this error while debugging is to clear all browser caches (javascript variables as well as loaded components) prior to re-running the script. In Firefox, you can simply clear your cache prior to completely quitting your browser. This should work with most other browsers, too. After re-launching the browser, the bug should appear once again.

Solution:

To correct the script, you need to ensure that it is run after all page components, such as images, are loaded, and not simply just the DOM. If you are using JQuery, rather than using $(document).ready(), use $(window).load(), e.g.

$(window).load(function(){
// ... your stuff here ...
});

For regular javascript, you can use the 'complete' property, e.g.

var myImage = new Image();
myImage.src = "img/myimage.png";

// ... later on ...
if(myImage.complete){
// ... do stuff ...
}

No comments:

Post a Comment