Skip to content
This repository has been archived by the owner on Nov 9, 2017. It is now read-only.

Commit

Permalink
Set the "async" property of dynamic script nodes to false to preserve…
Browse files Browse the repository at this point in the history
… execution order in browsers that support it.

This will (hopefully) bring back parallel script loading in Firefox 4 as
soon as it supports this feature.
  • Loading branch information
rgrove committed Nov 27, 2010
1 parent d844409 commit 3d96b90
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 31 deletions.
13 changes: 8 additions & 5 deletions HISTORY
Expand Up @@ -2,16 +2,19 @@ LazyLoad Changelog
================================================================================

Version 2.0.1 (git)
* Scripts are no longer loaded in parallel by default in Firefox 4+ (Gecko
2+), since Gecko has intentionally removed support for preserving the
execution order of dynamically-inserted scripts. See
https://bugzilla.mozilla.org/show_bug.cgi?id=591981
* Firefox 4.0 beta 7 removed support for preserving the execution order of
dynamically inserted scripts. A workaround (setting the script's "async"
property to false) has been proposed and may be implemented in future FF4
betas or in the final release. LazyLoad detects whether this feature is
supported; if it is, scripts will be loaded in parallel. Otherwise, scripts
will be loaded synchronously to preserve execution order. For more info,
see http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
* Stylesheet load completion is now detected reliably in WebKit by polling
document.styleSheets for changes. Thanks to Jonathan Cook for suggesting
this solution.
* Dynamically created script and link nodes are now given a "lazyload" class
so they can be identified later.
* Charset for dynamically created script and link nodes is set to "utf-8".
* The charset for dynamically created script and link nodes is set to "utf-8".

Version 2.0.0 (2009-08-06)
* Added support for CSS. Caveat: Gecko and WebKit don't support the onload
Expand Down
67 changes: 41 additions & 26 deletions lazyload.js
@@ -1,4 +1,4 @@
/*jslint browser: true, eqeqeq: true, bitwise: true, newcap: true, immed: true */
/*jslint browser: true, eqeqeq: true, bitwise: true, newcap: true, immed: true, regexp: false */

/**
* LazyLoad makes it easy and painless to lazily load one or more external
Expand Down Expand Up @@ -52,6 +52,9 @@ LazyLoad = (function () {
// Reference to the browser's document object.
var d = document,

// User agent and feature test information.
env,

// Reference to the <head> element.
head,

Expand All @@ -66,10 +69,7 @@ LazyLoad = (function () {
queue = {css: [], js: []},

// Reference to the browser's list of stylesheets.
styleSheets = d.styleSheets,

// User agent information.
ua;
styleSheets = d.styleSheets;

// -- Private Methods --------------------------------------------------------

Expand Down Expand Up @@ -134,23 +134,30 @@ LazyLoad = (function () {
}

/**
* Populates the <code>ua</code> variable with useragent information. Uses a
* paraphrased version of the YUI useragent detection code.
* Populates the <code>env</code> variable with user agent and feature test
* information. Uses a paraphrased version of the YUI user agent detection
* code.
*
* @method getUserAgent
* @method getEnv
* @private
*/
function getUserAgent() {
// No need to run again if ua is already populated.
if (ua) {
function getEnv() {
// No need to run again if already populated.
if (env) {
return;
}

var nua = navigator.userAgent,
pF = parseFloat,
m;

ua = {
env = {
// True if this browser supports disabling async mode on dynamically
// created script nodes. This feature should show up in FF4. See
// http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
async: d.createElement('script').async === true,

// Browser version numbers sniffed from the user agent string.
gecko : 0,
ie : 0,
opera : 0,
Expand All @@ -160,22 +167,22 @@ LazyLoad = (function () {
m = nua.match(/AppleWebKit\/(\S*)/);

if (m && m[1]) {
ua.webkit = pF(m[1]);
env.webkit = pF(m[1]);
} else {
m = nua.match(/MSIE\s([^;]*)/);

if (m && m[1]) {
ua.ie = pF(m[1]);
env.ie = pF(m[1]);
} else if ((/Gecko\/(\S*)/).test(nua)) {
ua.gecko = 1;
env.gecko = 1;

m = nua.match(/rv:([^\s\)]*)/);

if (m && m[1]) {
ua.gecko = pF(m[1]);
env.gecko = pF(m[1]);
}
} else if (m = nua.match(/Opera\/(\S*)/)) { // assignment
ua.opera = pF(m[1]);
} else if ((m = nua.match(/Opera\/(\S*)/))) { // assignment
env.opera = pF(m[1]);
}
}
}
Expand Down Expand Up @@ -208,8 +215,7 @@ LazyLoad = (function () {
isCSS = type === 'css',
i, len, node, p, pendingUrls, url;

// Determine browser type and version.
getUserAgent();
getEnv();

if (urls) {
// Cast urls to an Array.
Expand All @@ -220,13 +226,18 @@ LazyLoad = (function () {
//
// Sadly, Firefox <4 and Opera are the only browsers capable of loading
// scripts in parallel while preserving execution order. In all other
// browsers, scripts must be loaded sequentially. Firefox 4+ intentionally
// removed execution order preservation.
// browsers, scripts must be loaded sequentially. Firefox 4 beta 7
// intentionally removed execution order preservation.
//
// There's a chance that FF4 final will add support for manually
// specifying whether execution order should be preserved. LazyLoad tests
// for that capability and will use it if it's present; otherwise, it will
// fall back to the slower, safer synchronous mode.
//
// All browsers respect CSS specificity based on the order of the link
// elements in the DOM, regardless of the order in which the stylesheets
// are actually downloaded.
if (isCSS || (ua.gecko && ua.gecko < 2) || ua.opera) {
if (isCSS || (env.gecko && (env.async || env.gecko < 2)) || env.opera) {
queue[type].push({
urls : [].concat(urls), // concat ensures copy by value
callback: callback,
Expand Down Expand Up @@ -271,9 +282,13 @@ LazyLoad = (function () {
'class': 'lazyload',
src : url
});

if (env.async) {
node.async = false;
}
}

if (ua.ie) {
if (env.ie) {
node.onreadystatechange = function () {
var readyState = this.readyState;

Expand All @@ -282,12 +297,12 @@ LazyLoad = (function () {
_finish();
}
};
} else if (isCSS && (ua.gecko || ua.webkit)) {
} else if (isCSS && (env.gecko || env.webkit)) {
// Gecko and WebKit don't support the onload event on link nodes. In
// WebKit, we can poll for changes to document.styleSheets to figure out
// when stylesheets have loaded, but in Gecko we just have to finish
// after a brief delay and hope for the best.
if (ua.webkit) {
if (env.webkit) {
p.urls[i] = node.href; // resolve relative URLs (or polling won't work)
poll();
} else {
Expand Down

0 comments on commit 3d96b90

Please sign in to comment.