views:

49

answers:

1

We have some JavaScript code that resizes <div/> elements (adjusts height/width/padding/margin etc.) based on the dimensions of a parent <div/> element, specifically the height and width of the parent we use in the calculation. The parent div height and width is defined in a external CSS file, and <link> is used to include the stylesheet, in the <head> section of the page. All stylesheets are included before javascripts. The JavaScript resize code is fired inside of a jQuery document ready event using the standard $(function() {}). All stylesheets and javascripts automatically have timestamps appended to them (Rails application) to ensure they are not cached (in development).

In Firefox 3.6 the resizing works every time. However in Safari 5, occasionally the resizing fails, because the parent height/width is incorrect, which appears to be because the stylesheet has not loaded before the JavaScript. Frustratingly, this happens every few times, and is different depending on the browser/machine load. I can put the resizing code inside a setTimeout() and delay it by 1 second or so and get it to work reliably, but this is not a releasable solution because it is too slow, and still varies by machine. Ideally there would be a way to guarantee the stylesheet is downloaded, then fire the JS resize code.

First of all, is this a bad design, to have JS resizing based on CSS loaded from an external stylesheet? I'm considering trying to place the height and width inline so it is rendered from the server, but this requires significant app code change and tighter coupling to the UI, and I'd like to avoid inline style if possible. Is there a webkit event by chance when stylesheets are loaded? I don't think there is. Any suggestions on a method other than a timeout to ensure all stylesheets are loaded before firing JavaScript? Anyone else experienced differences in stylesheet load order/timing between Webkit and other browsers and have a solution to share? I could use some fresh thinking on this problem.

Note: in general for images, we use the load ($(thing).load(fn(){})) event on images to ensure they are loaded before applying any JavaScript to them. That would be a good pattern to follow if such a thing existed. Thanks!

+1  A: 

Co-worker (@johnreilly) found a couple solutions, one polls the document.readyState property when the browser is Safari looking for a value of complete.

http://stackoverflow.com/questions/318630/get-real-image-width-and-height-with-javascript-in-safari-chrome/318796#318796

Another creates a cssLoaded custom event and uses :after pseudo-selector to avoid polling. http://stilbuero.de/demo/cssloaded/

So the first solution is acceptable. I'm putting it in the main javascript file and using $.trigger() to emit a custom event to our handlers that depend on Webkit having fully downloaded the stylesheets.

Andy Atkinson