Enable and disable jquery and javascripts dynamically using lab.js

LAB.js Loading And Blocking JavaScript

    


http://labjs.com/documentation.php




Browsers tested and passing the Test Suite (please help to fill in gaps):
Windows: IE 6+, FF 1.5+, Chrome (latest), Opera 9.6+, Safari 4+, Netscape 7.2+, Mozilla 1.7
Mac (OSX): Safari 3.2+, Netscape 9, FF 1.5+, Opera 9.6+, Mozilla 1.7, Camino 2
Linux: FF 1.5+, Opera 9.5+, Netscape 9
Known unsupported

Safari 2, Opera 8, Konquerer (3.4, 4.1), FF 4b7 (only this exact release. <= b6 and b8+ are ok), Blackberry 4

Builds

It is recommended that you simply use the distribution-included minified files LAB.min.js and LAB-debug.min.js in production and development, respectively. However, some developers may want to use their own minification tools to "build" LAB.min.js themselves, from the source file (LAB.src.js). This is fine, but make sure you don't use too aggressive of a minifier/compiler, as it's possible you could alter something about LABjs in an unexpected and breaking way. Typically, compressors like YUIC and Packer (without base62) are quite safe and should be fine.

As of v2.0, LABjs source code (LAB.src.js) has DEBUG-mode code in it, delimited by /!*START_DEBUG*/ and /*!END_DEBUG*/ comments. This debug code is intended to be removed if minifying and building LAB.min.js from the original source code (but left in if building LAB-debug.min.js). This removal is possible with a simple preprocessing regex replace to remove the DEBUG-mode code from the source before minification. For instance, the following regular expression should work for that purpose:

//*!START_DEBUG(?:.|n)+END_DEBUG*//
The LAB-debug.min.js file skipped this step before minification, thus it includes the debug code. The LAB.min.js file however has the DEBUG-mode code stripped from it.

NOTE: It should also be safe to simply pass LAB.min.js or LAB-debug.min.js to your own minifier (even though they are already minified), which will simply do a harmless re-minification of the file. The best option, however, would be to instruct your build process to ignore minification on these files.

Documentation

Old and busted:

<script src="framework.js"></script>
<script src="plugin.framework.js"></script>
<script src="myplugin.framework.js"></script>
<script src="init.js"></script>
New hotness:

<script>
  $LAB
  .script("framework.js").wait()
  .script("plugin.framework.js")
  .script("myplugin.framework.js").wait()
  .script("init.js").wait();
</script>
In the above example, all scripts load in parallel (by default). "framework.js" needs to execute first, before the others. But "plugin.framework.js" and "myplugin.framework.js" have no dependencies between them, so their execution order is not important (first-come, first-served). "init.js" needs to wait for all 3 scripts to execute before it runs.

There are a few other variations on the .script(…) signature. For instance, you don't have to do a single script() call for each file (though I think it makes thing more readable). You can pass as many scripts singularly as parameters to one script() call. You can also pass an array of scripts, and it will loop through them and load them in the same way. Lastly, you can pass in an object instead of string, and the object literal can contain "src", "type", and "charset" specifications, if you need to override the defaults (for instance, load a "text/vbscript" script).

How to deal with inline scripts

So, there's some special gotchas you need to look out for when using LABjs not only to load scripts but also to "couple" inline scripts to execute in the proper order with the loaded scripts. Take this expanded example from above:

<script src="framework.js"></script>
<script src="plugin.framework.js"></script>
<script src="myplugin.framework.js"></script>
<script>
  myplugin.init();
</script>
<script>
  framework.init();
  framework.doSomething();
</script>
In this example, the browser would normally make sure that the two inline script blocks at the end will not even be parsed/executed until after the 4 scripts have been loaded. So, the references to "myplugin.init", "framework.init", and "framework.doSomething" will already be guaranteed to be defined (in the scripts that are loaded before the code is parsed).

But, because LABjs is an asynchronous loader, this "guarantee" will not be true. So, this code will fail:

<script>
  $LAB
  .script("framework.js").wait()
  .script("plugin.framework.js")
  .script("myplugin.framework.js")
</script>
<script>
  myplugin.init();
</script>
<script>
  framework.init();
  framework.doSomething();
</script>
The reason is because "myplugin.init", "framework.init", and "framework.doSomething" will be undefined symbols the instant after the $LAB chain first executes and starts loading the scripts. To make this code asynchronous safe, we do this instead:

<script>
  $LAB
  .script("framework.js").wait()
  .script("plugin.framework.js")
  .script("myplugin.framework.js")
  .wait(function(){
     myplugin.init();
     framework.init();
     framework.doSomething();
  });
</script>
We wrap the inline script code in a ".wait(function(){ … })" wrapper, which will defer its execution until the proper time in the loading order of the chain.

A simple pattern for converting <script src="…"></script> and <script>… /* inline code */ …</script> tags into $LAB API calls, use these two rules:

For every <script src="…"></script> tag you are replacing, you should have a ".script(…)" call
For every <script>… /*inline code*/ …</script> inline script block with code in it, we need a ".wait(function(){ … })" call to wrap around the code
If this still is a little confusing, it's ok! Read more about converting inline synchronous code to LABjs suitable asynchronous code over on getiblog.

Special "Feature" Note(s)

LABjs is able to handle non-feature-testable behavior in older legacy browsers through the use of two small but fairly solid browser inference sniffs. This is different from feature-detection (which is always preferable when possible), but with script-loading quirk behavior, there's no way to feature-detect (in those older legacy browsers), so we simply have to fork behavior based on browser family. So, the following two browser inference sniffs are used:

opera_or_gecko = (global.opera && Object.prototype.toString.call(global.opera) == "[object Opera]") ||
("MozAppearance" in document.documentElement.style),

The Opera inference relies on the fact that Opera declares an "opera" property on the window object, and that it's a special native, whose toString() return value cannot be duplicated by someone just declaring a window.opera property themselves. This gives a reasonably strong inference that we are in fact in the Opera browser.

The Mozilla inference relies on "MozAppearance" only appearing in Gecko browsers in the documentElement's style object. This isn't as solid as the Opera inference, but Gecko/FF has had this property for a really long time and there's a good chance they won't remove it, nor would any other browser have any reason to add a property of that name.

LABjs feature-tests for `async=true` (aka "ordered async") on script-inserted script elements. Read more about this feature on the Dynamic Script Execution Order WHATWG Wiki Page and Henri Sivonen's HTML5 Script Execution Changes.

The HTML Spec has officially been updated to include the "async=false" behavior, that LABjs employs a feature-detect for. FF4+, Webkit (March 2011+), IE10p2+, and Chrome 12+ now have this implemented (and Opera is coming soon).

LABjs also feature-tests for "real preloading". This type of preloading doesn't rely on the "cache preloading" hacks, but instead directly preloads the script (once) and then allows the execution of that code on-demand without a second (cached) request. This functionality has been present in IE since version 4, is suggested in the HTML spec (not required), and has been proposed to be officially declared a requirement. Even if it's never actually standardized any further, it's the best method available for IE, so it's worth it. Read more about the proposal to make this a requirement: Script Execution Control.

LABjs API

Methods

$LAB.setGlobalDefaults()
$LAB.setOptions()
$LAB.script()
$LAB.wait()
$LAB.queueScript()
$LAB.queueWait()
$LAB.runQueue()
$LAB.noConflict()
$LAB.sandbox()




Reference from:
http://chenpeng.info/html/869

Comments