There have been some breaking changes in jQuery APIs for Deferred since JsDefer was implemented.
A recent JsDefer commit modifies jquery.defer.js to make it agains compatible with current jQuery APIs.
However the non-jquery version of JsDefer - jsdefer.js - uses the previous Deferred APIs, which means that you cannot currently load jsdefer.js and then have it load jQuery! You need to determine up front whether you want the version with or without jQuery...
Apart from the above fixes, JsDefer is not being actively updated at the moment, but will probably become active again at some point after JsViews V1.0 has shipped.
- Wrapped scripts
- Unwrapped scripts
- Optional script definition (deferDef) defines dependencies
- Optional deferring of DomReady at global or individual request level
- Can also add dependencies for script - or add new definitions - in the script itself, if wrapped
- Execution order based on dependency
- Parallel/serial loading based on definitions, dependency, and wrapped versus unwrapped, and whether dependencies are defined in separate def file or in script itself.
- Passing options to scripts
- Wrapped script can provide a return value
- Failure bubbling
- Integration with Deferred (as in jQuery 1.5) enables or simplifies many use-case scenarios
- Use of $,when and other deferred features:
when( scripts, json, domReady ).then( myCallback );
- Exposing 'promises' (named deferreds)
- Setting: min true/false, for debug versus minified versions
- Wrapped scripts 'self executing' when used as static scripts
- Composite scripts (also able to be loaded statically in page)
- jQuery independent version
- Small
- Different versions of the Movies Demo app are provided to illustrate different use scenarios for JsDefer.
- Basic Features: Currently no unit tests are provided (they will come) but the FeatureTests/Basic folder provides some examples for testing different feature details.
- Advanced Features: This folder shows how to use JsDefer with or without jQuery. These samples illustrate some less-commonly used features. The AsyncTemplates folder explores some experimental integration with jQuery Templates.
// Note: If scripts have been defined in a deferDef declaration, this will
// trigger parallel loading of all dependent scripts,
// and will execute scripts in the correct order
// Load movies script
$.defer( "...movieApp.js" )
.done( workWithMovies )
.fail( failCallback );
$.deferSettings.delayDomReady = true;
$.defer( "...movieApp.js" );
$( function() {
workWithMoviesAndDom();
});
$.defer( "...movieApp.js", { pageSize: 4 })
.done( function( movieApp ) {
workWithMovies( movieApp );
});
// Load both data and scripts in parallel,
// and process when data, scripts and DOM are ready
$.when(
$.defer( "...movieApp.js", { pageSize: 4 } ),
getMovies( "Cartoons" ),
$.ready
)
.done( function( movieApp, data ) {
workWithMoviesAndDom( movieApp );
});
// Use unminified versions of script
$.deferSettings.min = false;
// Delay DomReady by default. (Can also override as a setting, for individual defer() requests.)
$.deferSettings.delayDomReady = true;
$.deferDef({
// Just set the URL
tmpl: "http://...jquery.tmpl.js",
// Specify url and dependencies
tmplplus: {
url: "http://.../jquery.tmplplus.js",
depends: "tmpl"
},
tmplCombined: {
url: "myCombinedFiles/tmplCombined.js",
// This script has both minified and unminified versions
urlMin: "myCombinedFiles/tmpl.min.js",
// It is a combined script: it can be used in place of the tmpl and tmplplus scripts
contains: [ "tmpl", "tmplplus" ]
},
yahooHelper: {
url: "http://.../yahooHelper.js",
// This script is not wrapped, and therefore will load sequentially after its dependencies:
// i.e. it will only be requested after any script that it depends on has loaded and executed
bare: true,
},
movieApp: {
url: "movieApp.js",
// Note that this script is wrapped (default is bare: false), and so will be loaded in parallel along
// with its dependencies. However its contents will not be executed until after execution of dependent scripts.
// Depends on both a declared and undeclared scripts
depends: [ "tmplplus", "http://...datamodel.js", "yahooHelper" ]
}
});
// Can optionally use typed methods to do a deferred load of any resource script defined in
// the deferDef definition (plus its dependencies):
$.defer.movieApp()
.done( workWithMovies )
.fail( failCb );
Note: This can be loaded by any script loader that recognizes the $deferRun global name for the wrapper function.
$deferRun(
function( $, options ) {
// Script code here
doStuff( options );
return myObject;
}
);
Use this wrapper syntax to create a wrapped script which can also be loaded as a static script in the absence of a script loader recognizing the $deferRun wrapper function
((window.$deferRun || function( run ){ run(); }) (
function( $, options ) {
// Script code here
}
));
Note: If the dependent script was already declared in a deferDef definition, then it will have loaded in parallel. Otherwise, if only declared here, it will be loaded in series - after this script loads, but before the body of this script is executed.
((window.$deferRun || function( run ){ run(); }) (
function( $, options ) {
// Script code here
},
// Declare one or more dependent scripts
"myOtherCode.js"
));
((window.$deferRun || function( run ){ run(); }) (
function( $, options ) {
// Script code here
},
{
// Declare one or more dependent scripts
depends: ["...myOtherCode.js", "myComponent"],
// Declare some deferDer script definitions
def: {
myComponent: {
url: "...myComponent.js",
minUrl: "...myComponent.min.js",
depends: "...componentCore.js"
}
}
}));
The different wrapped scripts within this script are identical to the individual wrapped scripts that they replace.
tmplCombined.js:
$deferRun(
function( $, options ) {
$deferRun(
function( $, options ) {
// Script code for tmpl.js here
});
$deferRun(
function( $, options ) {
// Script code for tmplplus here
});
});
Associated script definition, and invocation
$.deferDef({
tmplCombined: {
url: "myCombinedFiles/tmplCombined.js",
contains: [ "http://...tmpl.js", "http://...tmplplus.js" ]
}
});
$.defer.tmplCombined();
// Note: The above will make one HTTP request for the composite file,
// but is otherwise equivalent to the following two requests:
//$.defer( "http://...tmpl.js" );
//$.defer( "http://...tmplplus.js" );
// The individual wrapped scripts will execute in the correct order based on the
// declared dependencies of the individual scripts files they represent,
// but the individual files will not be loaded, once the composite
// script has been requested.
$deferRun(
function( $, options ) {
$deferRun(
function( $, options ) {
// Script code for sub script 1 here
});
$deferRun(
function( $, options ) {
// Script code for sub script 2 here
});
},
{
depends: [ "...OtherCode.js", "foo" ],
def: {
myVal: {
url: "...foo.js",
minUrl: "...foo.min.js",
depends: "...fooCore.js"
}
}
}
);
Use the following wrapper syntax to create a composite script that can also be loaded statically
Note: if loaded statically, the individual wrapped scripts will execute in document order
((window.$deferRun || function( run ){ run(); }) (
function( $, options ) {
((window.$deferRun || function( run ){ run(); }) (
function( $, options ) {
// Script code for sub script 1 here
}));
((window.$deferRun || function( run ){ run(); }) (
function( $, options ) {
// Script code for sub script 2 here
}));
((window.$deferRun || function( run ){ run(); }) (
function( $, options ) {
// Script code for sub script 3 here
}));
}));
<script src="../../jqueryui/jqueryuidefs.js" type="text/javascript"></script>
<script type="text/javascript">
var movieApp = { pageSize: 4 };
// Declare inline deferDef script definition, in addition to static jQueryUiDefs.js file above
$.deferDef({
tmpl: "http://...jquery.tmpl.js",
tmplplus: {
url: "http://.../jquery.tmplplus.js",
depends: "tmpl"
},
movies: {
url: "movies.js",
depends: "tmplplus"
}
});
$.deferSettings.delayDomReady = true;
// Load and execute all required scripts:
$.defer.movies();
$.defer.datePicker();
// Use delayed DomReady event to use loaded scripts and access DOM
$( function() {
$.movies( movieApp );
movieApp.getMovies( 0, "Cartoons" )
.done( function( data ) {
movieApp.render( data );
$( "#genres li" ).click( movieApp.selectGenre );
});
<script src="../../jqueryui/jqueryuidefs.js" type="text/javascript"></script>
<script src="../../MovieAppDefs.js" type="text/javascript"></script>
<script type="text/javascript">
// Load and execute all required scripts, and fetch data
// Use loaded scripts and data, and access DOM
$.when(
$.defer.movies({ pageSize: 4 }),
getMovies( 0, "Cartoons" ),
$.defer.datePicker(),
$.ready
)
.done( function( movieApp, data ) {
movieApp.render( data );
$( "#genres li" ).click( movieApp.selectGenre );
<script src="../../jqueryui/jqueryuidefs.js" type="text/javascript"></script>
<script src="../../MovieAppDefs.js" type="text/javascript"></script>
<script type="text/javascript">
$( function() {
$("#loadApp").click( function() {
// Only load the scripts and data if the user clicks on this button.
$.when(
$.defer.movies({ pageSize: 4 }),
getMovies( 0, "Cartoons" ),
$.defer.datePicker()
)
.done( function( movieApp, data ) {
movieApp.render( data );
$( "#genres li" ).click( movieApp.selectGenre );