├── MIT-LICENSE.txt ├── README.md ├── demos ├── feature-tests │ ├── advanced │ │ ├── 1_named-deferreds-no-globals.html │ │ ├── 2_no-cache.html │ │ ├── 3_aliases-for-definitions.html │ │ ├── 4_multiple.html │ │ ├── 5_overlapping-composites.html │ │ └── async-templates │ │ │ ├── 1_pass-deferred.html │ │ │ ├── 2_pass-url.html │ │ │ ├── 3_wait-also-for-domready.html │ │ │ ├── 4_remote-composite-templates.html │ │ │ └── jquery.tmpl.experimental.js │ ├── basic │ │ ├── 1a_delay-domready.html │ │ ├── 1b_delay-domready.html │ │ ├── 2a_def.html │ │ ├── 2b_def.html │ │ ├── 3_join-with-when.html │ │ ├── 4_bare.html │ │ ├── 5a_composite.html │ │ ├── 5b_composite-with-def.html │ │ ├── 6_static.html │ │ ├── 7_fail.html │ │ ├── 8_add-dependencies.html │ │ └── 9_template-and-data.html │ ├── console-test.js │ ├── resources │ │ ├── bare1.js │ │ ├── bare1.min.js │ │ ├── bare2.js │ │ ├── f.js │ │ ├── folder1 │ │ │ ├── a.js │ │ │ ├── a.min.js │ │ │ └── add-dependencies.js │ │ ├── folder2 │ │ │ ├── c.js │ │ │ ├── composite-dcf.js │ │ │ ├── composite-fed.js │ │ │ ├── d.js │ │ │ └── e.js │ │ └── myscriptdefs.js │ ├── templates-and-data │ │ ├── mydata.js │ │ ├── myrichdata.js │ │ ├── mytmpl.js │ │ └── richtmpls.js │ └── with-or-without-jquery │ │ ├── 1_with-jquery.html │ │ └── 2_non-jquery-version.html └── movies │ ├── pages │ ├── 1_movies.html │ ├── 2_movies-when-data-and-script.html │ ├── 3_movie-lazy-load.html │ └── 4_movies-and-jquery-lazy-load.html │ └── resources │ ├── css │ ├── jquery-ui-1.8.1.custom.css │ └── movies.css │ ├── images │ ├── ui-bg_diagonals-thick_75_f3d8d8_40x40.png │ ├── ui-bg_dots-small_65_a6a6a6_2x2.png │ ├── ui-bg_flat_0_333333_40x100.png │ ├── ui-bg_flat_65_ffffff_40x100.png │ ├── ui-bg_flat_75_ffffff_40x100.png │ ├── ui-bg_glass_55_fbf8ee_1x400.png │ ├── ui-bg_glass_75_dadada_1x400.png │ ├── ui-bg_highlight-hard_100_eeeeee_1x100.png │ ├── ui-bg_highlight-hard_100_f6f6f6_1x100.png │ ├── ui-bg_highlight-soft_15_cc0000_1x100.png │ ├── ui-icons_004276_256x240.png │ ├── ui-icons_cc0000_256x240.png │ └── ui-icons_ffffff_256x240.png │ ├── jqueryplugins │ └── templates │ │ ├── jquery.tmpl.js │ │ └── jquery.tmplplus.js │ ├── jqueryui │ ├── datepicker │ │ ├── datepicker.js │ │ └── datepicker.min.js │ ├── jqueryuidefs.js │ └── pager │ │ └── jquery.pager.js │ ├── movieapp.js │ ├── movieappdefs.js │ └── movieplugin.js ├── jquery.defer.js ├── jquery.defer.min.js ├── jquery.defer.min.js.map ├── jsdefer.js ├── jsdefer.min.js └── jsdefer.min.js.map /MIT-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Boris Moore https://github.com/BorisMoore/jsdefer 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JsDefer recent Status: 2 | 3 | There have been some breaking changes in jQuery APIs for Deferred since JsDefer was implemented. 4 | 5 | A recent JsDefer commit modifies jquery.defer.js to make it agains compatible with current 6 | jQuery APIs. 7 | 8 | However the non-jquery version of JsDefer - jsdefer.js - uses the previous Deferred APIs, 9 | which means that you cannot currently load jsdefer.js and then have it load jQuery! 10 | You need to determine up front whether you want the version with or without jQuery... 11 | 12 | Apart from the above fixes, JsDefer is not being actively updated at the moment, but will 13 | probably become active again at some point after JsViews V1.0 has shipped. 14 | 15 | # JsDefer Features: 16 | 17 | * Wrapped scripts 18 | * Unwrapped scripts 19 | * Optional script definition (deferDef) defines dependencies 20 | * Optional deferring of DomReady at global or individual request level 21 | * Can also add dependencies for script - or add new definitions - in the script itself, if wrapped 22 | * Execution order based on dependency 23 | * Parallel/serial loading based on definitions, dependency, and wrapped versus unwrapped, and whether 24 | dependencies are defined in separate def file or in script itself. 25 | * Passing options to scripts 26 | * Wrapped script can provide a return value 27 | * Failure bubbling 28 | * Integration with Deferred (as in jQuery 1.5) enables or simplifies many use-case scenarios 29 | * Use of $,when and other deferred features: `when( scripts, json, domReady ).then( myCallback );` 30 | * Exposing 'promises' (named deferreds) 31 | * Setting: min true/false, for debug versus minified versions 32 | * Wrapped scripts 'self executing' when used as static scripts 33 | * Composite scripts (also able to be loaded statically in page) 34 | * jQuery independent version 35 | * Small 36 | 37 | ## Demos 38 | 39 | ### Complete Demos 40 | * Different versions of the [Movies Demo app](https://github.com/BorisMoore/jsdefer/tree/master/demos/movies/pages) 41 | are provided to illustrate different use scenarios for JsDefer. 42 | 43 | ### Feature tests: 44 | 45 | * Basic Features: Currently no unit tests are provided (they will come) but the 46 | [FeatureTests/Basic](https://github.com/BorisMoore/jsdefer/tree/master/demos/feature-tests/basic) 47 | folder provides some examples for testing different feature details. 48 | * Advanced Features: 49 | [This folder](https://github.com/BorisMoore/jsdefer/tree/master/demos/featuretests/with-or-without-jquery) 50 | shows how to use JsDefer with or without jQuery. 51 | [These samples](https://github.com/BorisMoore/jsdefer/tree/master/demos/feature-tests/advanced) 52 | illustrate some less-commonly used features. 53 | The [AsyncTemplates](https://github.com/BorisMoore/jsdefer/tree/master/demos/feature-tests/advanced/async-templates) 54 | folder explores some experimental integration with 55 | [jQuery Templates](https://github.com/BorisMoore/jquery-tmpl). 56 | 57 | 58 | ## Syntax Examples: 59 | 60 | 61 | ### Request deferred script loading 62 | 63 | // Note: If scripts have been defined in a deferDef declaration, this will 64 | // trigger parallel loading of all dependent scripts, 65 | // and will execute scripts in the correct order 66 | 67 | // Load movies script 68 | $.defer( "...movieApp.js" ) 69 | .done( workWithMovies ) 70 | .fail( failCallback ); 71 | 72 | 73 | ### Deferred script loading using delayed DomReady event 74 | 75 | $.deferSettings.delayDomReady = true; 76 | 77 | $.defer( "...movieApp.js" ); 78 | 79 | $( function() { 80 | workWithMoviesAndDom(); 81 | }); 82 | 83 | 84 | ### Passing options and using return value 85 | 86 | $.defer( "...movieApp.js", { pageSize: 4 }) 87 | .done( function( movieApp ) { 88 | workWithMovies( movieApp ); 89 | }); 90 | 91 | 92 | ### Using $.when to handle parallel async processes 93 | 94 | // Load both data and scripts in parallel, 95 | // and process when data, scripts and DOM are ready 96 | $.when( 97 | $.defer( "...movieApp.js", { pageSize: 4 } ), 98 | getMovies( "Cartoons" ), 99 | $.ready 100 | ) 101 | .done( function( movieApp, data ) { 102 | workWithMoviesAndDom( movieApp ); 103 | }); 104 | 105 | 106 | ### Setting default options 107 | 108 | // Use unminified versions of script 109 | $.deferSettings.min = false; 110 | 111 | // Delay DomReady by default. (Can also override as a setting, for individual defer() requests.) 112 | $.deferSettings.delayDomReady = true; 113 | 114 | 115 | ### Create deferDef definition - to load and execute dependencies in correct order 116 | 117 | $.deferDef({ 118 | // Just set the URL 119 | tmpl: "http://...jquery.tmpl.js", 120 | 121 | // Specify url and dependencies 122 | tmplplus: { 123 | url: "http://.../jquery.tmplplus.js", 124 | depends: "tmpl" 125 | }, 126 | 127 | tmplCombined: { 128 | url: "myCombinedFiles/tmplCombined.js", 129 | 130 | // This script has both minified and unminified versions 131 | urlMin: "myCombinedFiles/tmpl.min.js", 132 | 133 | // It is a combined script: it can be used in place of the tmpl and tmplplus scripts 134 | contains: [ "tmpl", "tmplplus" ] 135 | }, 136 | 137 | yahooHelper: { 138 | url: "http://.../yahooHelper.js", 139 | 140 | // This script is not wrapped, and therefore will load sequentially after its dependencies: 141 | // i.e. it will only be requested after any script that it depends on has loaded and executed 142 | bare: true, 143 | }, 144 | 145 | movieApp: { 146 | url: "movieApp.js", 147 | 148 | // Note that this script is wrapped (default is bare: false), and so will be loaded in parallel along 149 | // with its dependencies. However its contents will not be executed until after execution of dependent scripts. 150 | 151 | // Depends on both a declared and undeclared scripts 152 | depends: [ "tmplplus", "http://...datamodel.js", "yahooHelper" ] 153 | } 154 | 155 | }); 156 | 157 | // Can optionally use typed methods to do a deferred load of any resource script defined in 158 | // the deferDef definition (plus its dependencies): 159 | 160 | $.defer.movieApp() 161 | .done( workWithMovies ) 162 | .fail( failCb ); 163 | 164 | 165 | ### Wrapped script 166 | 167 | _Note:_ This can be loaded by any script loader that recognizes 168 | the $deferRun global name for the wrapper function. 169 | 170 | $deferRun( 171 | 172 | function( $, options ) { 173 | 174 | // Script code here 175 | doStuff( options ); 176 | return myObject; 177 | 178 | } 179 | 180 | ); 181 | 182 | 183 | ### Self-executing wrapper 184 | 185 | _Use this wrapper syntax to create a wrapped script which can also be loaded as a static script 186 | in the absence of a script loader recognizing the $deferRun wrapper function_ 187 | 188 | ((window.$deferRun || function( run ){ run(); }) ( 189 | 190 | function( $, options ) { 191 | 192 | // Script code here 193 | 194 | } 195 | 196 | )); 197 | 198 | 199 | ### Declare dependencies on script itself 200 | 201 | _Note:_ If the dependent script was already declared in a deferDef definition, then 202 | it will have loaded in parallel. Otherwise, if only declared here, it will be loaded 203 | in series - after this script loads, but before the body of this script is executed. 204 | 205 | ((window.$deferRun || function( run ){ run(); }) ( 206 | 207 | function( $, options ) { 208 | 209 | // Script code here 210 | 211 | }, 212 | 213 | // Declare one or more dependent scripts 214 | "myOtherCode.js" 215 | 216 | )); 217 | 218 | 219 | ### Declare dependencies and a deferDef definition, on the script itself 220 | 221 | ((window.$deferRun || function( run ){ run(); }) ( 222 | 223 | function( $, options ) { 224 | 225 | // Script code here 226 | 227 | }, 228 | { 229 | // Declare one or more dependent scripts 230 | depends: ["...myOtherCode.js", "myComponent"], 231 | 232 | // Declare some deferDer script definitions 233 | def: { 234 | myComponent: { 235 | url: "...myComponent.js", 236 | minUrl: "...myComponent.min.js", 237 | depends: "...componentCore.js" 238 | } 239 | } 240 | })); 241 | 242 | 243 | ### Script combination: Composite scripts 244 | 245 | The different wrapped scripts within this script are identical to the 246 | individual wrapped scripts that they replace. 247 | 248 | _tmplCombined.js:_ 249 | 250 | $deferRun( 251 | function( $, options ) { 252 | 253 | $deferRun( 254 | function( $, options ) { 255 | // Script code for tmpl.js here 256 | }); 257 | 258 | $deferRun( 259 | function( $, options ) { 260 | // Script code for tmplplus here 261 | }); 262 | 263 | }); 264 | 265 | _Associated script definition, and invocation_ 266 | 267 | $.deferDef({ 268 | tmplCombined: { 269 | url: "myCombinedFiles/tmplCombined.js", 270 | 271 | contains: [ "http://...tmpl.js", "http://...tmplplus.js" ] 272 | } 273 | }); 274 | 275 | $.defer.tmplCombined(); 276 | 277 | // Note: The above will make one HTTP request for the composite file, 278 | // but is otherwise equivalent to the following two requests: 279 | 280 | //$.defer( "http://...tmpl.js" ); 281 | //$.defer( "http://...tmplplus.js" ); 282 | 283 | // The individual wrapped scripts will execute in the correct order based on the 284 | // declared dependencies of the individual scripts files they represent, 285 | // but the individual files will not be loaded, once the composite 286 | // script has been requested. 287 | 288 | 289 | ### Can also declare deferDef script definitions, dependencies, etc. on the composite file itself 290 | 291 | $deferRun( 292 | 293 | function( $, options ) { 294 | 295 | $deferRun( 296 | function( $, options ) { 297 | // Script code for sub script 1 here 298 | }); 299 | 300 | $deferRun( 301 | function( $, options ) { 302 | // Script code for sub script 2 here 303 | }); 304 | 305 | }, 306 | { 307 | depends: [ "...OtherCode.js", "foo" ], 308 | def: { 309 | myVal: { 310 | url: "...foo.js", 311 | minUrl: "...foo.min.js", 312 | depends: "...fooCore.js" 313 | } 314 | } 315 | } 316 | 317 | ); 318 | 319 | 320 | ### Self-executing composite script 321 | 322 | _Use the following wrapper syntax to create a composite 323 | script that can also be loaded statically_ 324 | 325 | _Note:_ if loaded statically, the individual wrapped scripts 326 | will execute in document order 327 | 328 | ((window.$deferRun || function( run ){ run(); }) ( 329 | function( $, options ) { 330 | 331 | ((window.$deferRun || function( run ){ run(); }) ( 332 | function( $, options ) { 333 | // Script code for sub script 1 here 334 | })); 335 | 336 | ((window.$deferRun || function( run ){ run(); }) ( 337 | function( $, options ) { 338 | // Script code for sub script 2 here 339 | })); 340 | 341 | ((window.$deferRun || function( run ){ run(); }) ( 342 | function( $, options ) { 343 | // Script code for sub script 3 here 344 | })); 345 | 346 | })); 347 | 348 | 349 | 350 | ### App example: 351 | 352 | #### Inline deferDef 353 | #### Delayed DomReady 354 | 355 | 356 | 357 | 396 | 397 | 398 | 419 | 420 | 421 | 5 | 6 | 7 | 8 | 9 | 24 | 25 | 26 | 27 | Results: 28 | 29 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /demos/feature-tests/advanced/2_no-cache.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 49 | 50 | 51 | 52 | Results: 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /demos/feature-tests/advanced/3_aliases-for-definitions.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 42 | 43 | 44 | 45 | Results: 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /demos/feature-tests/advanced/4_multiple.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 66 | 67 | 68 | Results: 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /demos/feature-tests/advanced/5_overlapping-composites.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 75 | 76 | 77 | Results: 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /demos/feature-tests/advanced/async-templates/1_pass-deferred.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /demos/feature-tests/advanced/async-templates/2_pass-url.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /demos/feature-tests/advanced/async-templates/3_wait-also-for-domready.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /demos/feature-tests/advanced/async-templates/4_remote-composite-templates.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /demos/feature-tests/advanced/async-templates/jquery.tmpl.experimental.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery Templates Plugin 1.0.0pre 3 | * http://github.com/jquery/jquery-tmpl 4 | * Requires jQuery 1.4.2 5 | * 6 | * Copyright Software Freedom Conservancy, Inc. 7 | * Dual licensed under the MIT or GPL Version 2 licenses. 8 | * http://jquery.org/license 9 | */ 10 | (function( jQuery, undefined ){ 11 | var oldManip = jQuery.fn.domManip, tmplItmAtt = "_tmplitem", htmlExpr = /^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /, 12 | newTmplItems = {}, wrappedItems = {}, appendToTmplItems, topTmplItem = { key: 0, data: {} }, itemKey = 0, cloneIndex = 0, stack = []; 13 | 14 | function newTmplItem( options, parentItem, fn, data ) { 15 | // Returns a template item data structure for a new rendered instance of a template (a 'template item'). 16 | // The content field is a hierarchical array of strings and nested items (to be 17 | // removed and replaced by nodes field of dom elements, once inserted in DOM). 18 | var newItem = { 19 | data: data || (parentItem ? parentItem.data : {}), 20 | _wrap: parentItem ? parentItem._wrap : null, 21 | tmpl: null, 22 | parent: parentItem || null, 23 | nodes: [], 24 | calls: tiCalls, 25 | nest: tiNest, 26 | wrap: tiWrap, 27 | html: tiHtml, 28 | update: tiUpdate 29 | }; 30 | if ( options ) { 31 | jQuery.extend( newItem, options, { nodes: [], parent: parentItem }); 32 | } 33 | if ( fn ) { 34 | // Build the hierarchical content to be used during insertion into DOM 35 | newItem.tmpl = fn; 36 | newItem._ctnt = newItem._ctnt || newItem.tmpl( jQuery, newItem ); 37 | newItem.key = ++itemKey; 38 | // Keep track of new template item, until it is stored as jQuery Data on DOM element 39 | (stack.length ? wrappedItems : newTmplItems)[itemKey] = newItem; 40 | } 41 | return newItem; 42 | } 43 | 44 | // Override appendTo etc., in order to provide support for targeting multiple elements. (This code would disappear if integrated in jquery core). 45 | jQuery.each({ 46 | appendTo: "append", 47 | prependTo: "prepend", 48 | insertBefore: "before", 49 | insertAfter: "after", 50 | replaceAll: "replaceWith" 51 | }, function( name, original ) { 52 | jQuery.fn[ name ] = function( selector ) { 53 | var $this = this; 54 | function doInsert() { 55 | var ret = [], insert = jQuery( selector ), elems, i, l, tmplItems, 56 | parent = this.length === 1 && this[0].parentNode; 57 | 58 | appendToTmplItems = newTmplItems || {}; 59 | if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) { 60 | insert[ original ]( $this[0] ); 61 | ret = $this; 62 | } else { 63 | for ( i = 0, l = insert.length; i < l; i++ ) { 64 | cloneIndex = i; 65 | elems = (i > 0 ? $this.clone(true) : $this).get(); 66 | jQuery( insert[i] )[ original ]( elems ); 67 | ret = ret.concat( elems ); 68 | } 69 | cloneIndex = 0; 70 | ret = $this.pushStack( ret, name, insert.selector ); 71 | } 72 | tmplItems = appendToTmplItems; 73 | appendToTmplItems = null; 74 | jQuery.tmpl.complete( tmplItems ); 75 | return ret; 76 | } 77 | if ( this.promise ) { 78 | return this.done( function( renderedTmpl ) { 79 | $this = renderedTmpl; 80 | doInsert(); 81 | }); 82 | } 83 | doInsert(); 84 | }; 85 | }); 86 | 87 | jQuery.fn.extend({ 88 | // Use first wrapped element as template markup. 89 | // Return wrapped set of template items, obtained by rendering template against data. 90 | tmpl: function( data, options, parentItem ) { 91 | return jQuery.tmpl( this[0], data, options, parentItem ); 92 | }, 93 | 94 | // Find which rendered template item the first wrapped DOM element belongs to 95 | tmplItem: function() { 96 | return jQuery.tmplItem( this[0] ); 97 | }, 98 | 99 | // Consider the first wrapped element as a template declaration, and get the compiled template or store it as a named template. 100 | template: function( name ) { 101 | return jQuery.template( name, this[0] ); 102 | }, 103 | 104 | domManip: function( args, table, callback, options ) { 105 | if ( args[0] && jQuery.isArray( args[0] )) { 106 | var dmArgs = jQuery.makeArray( arguments ), elems = args[0], elemsLength = elems.length, i = 0, tmplItem; 107 | while ( i < elemsLength && !(tmplItem = jQuery.data( elems[i++], "tmplItem" ))) {} 108 | if ( tmplItem && cloneIndex ) { 109 | dmArgs[2] = function( fragClone ) { 110 | // Handler called by oldManip when rendered template has been inserted into DOM. 111 | jQuery.tmpl.afterManip( this, fragClone, callback ); 112 | }; 113 | } 114 | oldManip.apply( this, dmArgs ); 115 | } else { 116 | oldManip.apply( this, arguments ); 117 | } 118 | cloneIndex = 0; 119 | if ( !appendToTmplItems ) { 120 | jQuery.tmpl.complete( newTmplItems ); 121 | } 122 | return this; 123 | } 124 | }); 125 | 126 | function maybeDeferred( res ) { 127 | return typeof res === "string" && res.charAt(0) === "@" ? 128 | jQuery.defer( res.substr( 1 ), { delayDomReady: true } ) : 129 | res; 130 | } 131 | 132 | jQuery.extend({ 133 | // Return wrapped set of template items, obtained by rendering template against data. 134 | tmpl: function( tmpl, data, options, parentItem ) { 135 | 136 | var topLevel = !parentItem; 137 | 138 | function render( theTmpl, theData ) { 139 | tmpl = theTmpl; 140 | data = theData; 141 | var ret; 142 | if ( topLevel ) { 143 | // This is a top-level tmpl call (not from a nested template using {{tmpl}}) 144 | parentItem = topTmplItem; 145 | tmpl = jQuery.template[tmpl] || jQuery.template( null, tmpl ); 146 | wrappedItems = {}; // Any wrapped items will be rebuilt, since this is top level 147 | } else if ( !tmpl ) { 148 | // The template item is already associated with DOM - this is a refresh. 149 | // Re-evaluate rendered template for the parentItem 150 | tmpl = parentItem.tmpl; 151 | newTmplItems[parentItem.key] = parentItem; 152 | parentItem.nodes = []; 153 | if ( parentItem.wrapped ) { 154 | updateWrapped( parentItem, parentItem.wrapped ); 155 | } 156 | // Rebuild, without creating a new template item 157 | return jQuery( build( parentItem, null, parentItem.tmpl( jQuery, parentItem ) )); 158 | } 159 | if ( !tmpl ) { 160 | return []; // Could throw... 161 | } 162 | if ( typeof data === "function" ) { 163 | data = data.call( parentItem || {} ); 164 | } 165 | if ( options && options.wrapped ) { 166 | updateWrapped( options, options.wrapped ); 167 | } 168 | ret = jQuery.isArray( data ) ? 169 | jQuery.map( data, function( dataItem ) { 170 | return dataItem ? newTmplItem( options, parentItem, tmpl, dataItem ) : null; 171 | }) : 172 | [ newTmplItem( options, parentItem, tmpl, data ) ]; 173 | 174 | if ( topLevel ) { 175 | asyncRender.resolve( jQuery( build( parentItem, null, ret ))); 176 | } else { 177 | return ret; 178 | }; 179 | } 180 | 181 | if ( topLevel ) { 182 | asyncRender = jQuery.Deferred(); 183 | 184 | jQuery.when( maybeDeferred( tmpl ), maybeDeferred( data )).done( render ); 185 | 186 | return asyncRender.promise( jQuery() ); 187 | } else { 188 | try { 189 | tmpl = jQuery.deferDef( tmpl.substr( 1 )).result; 190 | } 191 | catch(e) { 192 | throw "Error: Nested remote template not loaded." 193 | } 194 | return render( tmpl, data ); 195 | } 196 | }, 197 | 198 | // Return rendered template item for an element. 199 | tmplItem: function( elem ) { 200 | var tmplItem; 201 | if ( elem instanceof jQuery ) { 202 | elem = elem[0]; 203 | } 204 | while ( elem && elem.nodeType === 1 && !(tmplItem = jQuery.data( elem, "tmplItem" )) && (elem = elem.parentNode) ) {} 205 | return tmplItem || topTmplItem; 206 | }, 207 | 208 | // Set: 209 | // Use $.template( name, tmpl ) to cache a named template, 210 | // where tmpl is a template string, a script element or a jQuery instance wrapping a script element, etc. 211 | // Use $( "selector" ).template( name ) to provide access by name to a script block template declaration. 212 | 213 | // Get: 214 | // Use $.template( name ) to access a cached template. 215 | // Also $( selectorToScriptBlock ).template(), or $.template( null, templateString ) 216 | // will return the compiled template, without adding a name reference. 217 | // If templateString includes at least one HTML tag, $.template( templateString ) is equivalent 218 | // to $.template( null, templateString ) 219 | template: function( name, tmpl ) { 220 | if (tmpl) { 221 | // Compile template and associate with name 222 | if ( typeof tmpl === "string" ) { 223 | // This is an HTML string being passed directly in. 224 | tmpl = buildTmplFn( tmpl ) 225 | } else if ( tmpl instanceof jQuery ) { 226 | tmpl = tmpl[0] || {}; 227 | } 228 | if ( tmpl.nodeType ) { 229 | // If this is a template block, use cached copy, or generate tmpl function and cache. 230 | tmpl = jQuery.data( tmpl, "tmpl" ) || jQuery.data( tmpl, "tmpl", buildTmplFn( tmpl.innerHTML )); 231 | // Issue: In IE, if the container element is not a script block, the innerHTML will remove quotes from attribute values whenever the value does not include white space. 232 | // This means that foo="${x}" will not work if the value of x includes white space: foo="${x}" -> foo=value of x. 233 | // To correct this, include space in tag: foo="${ x }" -> foo="value of x" 234 | } 235 | return typeof name === "string" ? (jQuery.template[name] = tmpl) : tmpl; 236 | } 237 | // Return named compiled template 238 | return name ? (typeof name !== "string" ? jQuery.template( null, name ): 239 | name.charAt(0) === "@" ? name : (jQuery.template[name] || 240 | // If not in map, treat as a selector. (If integrated with core, use quickExpr.exec) 241 | jQuery.template( null, htmlExpr.test( name ) ? name : jQuery( name )))) : null; 242 | }, 243 | 244 | encode: function( text ) { 245 | // Do HTML encoding replacing < > & and ' and " by corresponding entities. 246 | return ("" + text).split("<").join("<").split(">").join(">").split('"').join(""").split("'").join("'"); 247 | } 248 | }); 249 | 250 | jQuery.extend( jQuery.tmpl, { 251 | tag: { 252 | "tmpl": { 253 | _default: { $2: "null" }, 254 | open: "if($notnull_1){_=_.concat($item.nest($1,$2));}" 255 | // tmpl target parameter can be of type function, so use $1, not $1a (so not auto detection of functions) 256 | // This means that {{tmpl foo}} treats foo as a template (which IS a function). 257 | // Explicit parens can be used if foo is a function that returns a template: {{tmpl foo()}}. 258 | }, 259 | "wrap": { 260 | _default: { $2: "null" }, 261 | open: "$item.calls(_,$1,$2);_=[];", 262 | close: "call=$item.calls();_=call._.concat($item.wrap(call,_));" 263 | }, 264 | "each": { 265 | _default: { $2: "$index, $value" }, 266 | open: "if($notnull_1){$.each($1a,function($2){with(this){", 267 | close: "}});}" 268 | }, 269 | "if": { 270 | open: "if(($notnull_1) && $1a){", 271 | close: "}" 272 | }, 273 | "else": { 274 | _default: { $1: "true" }, 275 | open: "}else if(($notnull_1) && $1a){" 276 | }, 277 | "html": { 278 | // Unecoded expression evaluation. 279 | open: "if($notnull_1){_.push($1a);}" 280 | }, 281 | "=": { 282 | // Encoded expression evaluation. Abbreviated form is ${}. 283 | _default: { $1: "$data" }, 284 | open: "if($notnull_1){_.push($.encode($1a));}" 285 | }, 286 | "!": { 287 | // Comment tag. Skipped by parser 288 | open: "" 289 | } 290 | }, 291 | 292 | // This stub can be overridden, e.g. in jquery.tmplplus for providing rendered events 293 | complete: function( items ) { 294 | newTmplItems = {}; 295 | }, 296 | 297 | // Call this from code which overrides domManip, or equivalent 298 | // Manage cloning/storing template items etc. 299 | afterManip: function afterManip( elem, fragClone, callback ) { 300 | // Provides cloned fragment ready for fixup prior to and after insertion into DOM 301 | var content = fragClone.nodeType === 11 ? 302 | jQuery.makeArray(fragClone.childNodes) : 303 | fragClone.nodeType === 1 ? [fragClone] : []; 304 | 305 | // Return fragment to original caller (e.g. append) for DOM insertion 306 | callback.call( elem, fragClone ); 307 | 308 | // Fragment has been inserted:- Add inserted nodes to tmplItem data structure. Replace inserted element annotations by jQuery.data. 309 | storeTmplItems( content ); 310 | cloneIndex++; 311 | } 312 | }); 313 | 314 | //========================== Private helper functions, used by code above ========================== 315 | 316 | function build( tmplItem, nested, content ) { 317 | // Convert hierarchical content into flat string array 318 | // and finally return array of fragments ready for DOM insertion 319 | var frag, ret = content ? jQuery.map( content, function( item ) { 320 | return (typeof item === "string") ? 321 | // Insert template item annotations, to be converted to jQuery.data( "tmplItem" ) when elems are inserted into DOM. 322 | (tmplItem.key ? item.replace( /(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g, "$1 " + tmplItmAtt + "=\"" + tmplItem.key + "\" $2" ) : item) : 323 | // This is a child template item. Build nested template. 324 | build( item, tmplItem, item._ctnt ); 325 | }) : 326 | // If content is not defined, insert tmplItem directly. Not a template item. May be a string, or a string array, e.g. from {{html $item.html()}}. 327 | tmplItem; 328 | if ( nested ) { 329 | return ret; 330 | } 331 | 332 | // top-level template 333 | ret = ret.join(""); 334 | 335 | // Support templates which have initial or final text nodes, or consist only of text 336 | // Also support HTML entities within the HTML markup. 337 | ret.replace( /^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/, function( all, before, middle, after) { 338 | frag = jQuery( middle ).get(); 339 | 340 | storeTmplItems( frag ); 341 | if ( before ) { 342 | frag = unencode( before ).concat(frag); 343 | } 344 | if ( after ) { 345 | frag = frag.concat(unencode( after )); 346 | } 347 | }); 348 | return frag ? frag : unencode( ret ); 349 | } 350 | 351 | function unencode( text ) { 352 | // Use createElement, since createTextNode will not render HTML entities correctly 353 | var el = document.createElement( "div" ); 354 | el.innerHTML = text; 355 | return jQuery.makeArray(el.childNodes); 356 | } 357 | 358 | // Generate a reusable function that will serve to render a template against data 359 | function buildTmplFn( markup ) { 360 | return new Function("jQuery","$item", 361 | "var $=jQuery,call,_=[],$data=$item.data;" + 362 | 363 | // Introduce the data as local variables using with(){} 364 | "with($data){_.push('" + 365 | 366 | // Convert the template into pure JavaScript 367 | jQuery.trim(markup) 368 | .replace( /([\\'])/g, "\\$1" ) 369 | .replace( /[\r\t\n]/g, " " ) 370 | .replace( /\$\{([^\}]*)\}/g, "{{= $1}}" ) 371 | .replace( /\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g, 372 | function( all, slash, type, fnargs, target, parens, args ) { 373 | var tag = jQuery.tmpl.tag[ type ], def, expr, exprAutoFnDetect; 374 | if ( !tag ) { 375 | throw "Template command not found: " + type; 376 | } 377 | def = tag._default || []; 378 | if ( parens && !/\w$/.test(target)) { 379 | target += parens; 380 | parens = ""; 381 | } 382 | if ( target ) { 383 | target = unescape( target ); 384 | args = args ? ("," + unescape( args ) + ")") : (parens ? ")" : ""); 385 | // Support for target being things like a.toLowerCase(); 386 | // In that case don't call with template item as 'this' pointer. Just evaluate... 387 | expr = parens ? (target.indexOf(".") > -1 ? target + unescape( parens ) : ("(" + target + ").call($item" + args)) : target; 388 | exprAutoFnDetect = parens ? expr : "(typeof(" + target + ")==='function'?(" + target + ").call($item):(" + target + "))"; 389 | } else { 390 | exprAutoFnDetect = expr = def.$1 || "null"; 391 | } 392 | fnargs = unescape( fnargs ); 393 | return "');" + 394 | tag[ slash ? "close" : "open" ] 395 | .split( "$notnull_1" ).join( target ? "typeof(" + target + ")!=='undefined' && (" + target + ")!=null" : "true" ) 396 | .split( "$1a" ).join( exprAutoFnDetect ) 397 | .split( "$1" ).join( expr ) 398 | .split( "$2" ).join( fnargs || def.$2 || "" ) + 399 | "_.push('"; 400 | }) + 401 | "');}return _;" 402 | ); 403 | } 404 | function updateWrapped( options, wrapped ) { 405 | // Build the wrapped content. 406 | options._wrap = build( options, true, 407 | // Suport imperative scenario in which options.wrapped can be set to a selector or an HTML string. 408 | jQuery.isArray( wrapped ) ? wrapped : [htmlExpr.test( wrapped ) ? wrapped : jQuery( wrapped ).html()] 409 | ).join(""); 410 | } 411 | 412 | function unescape( args ) { 413 | return args ? args.replace( /\\'/g, "'").replace(/\\\\/g, "\\" ) : null; 414 | } 415 | function outerHtml( elem ) { 416 | var div = document.createElement("div"); 417 | div.appendChild( elem.cloneNode(true) ); 418 | return div.innerHTML; 419 | } 420 | 421 | // Store template items in jQuery.data(), ensuring a unique tmplItem data data structure for each rendered template instance. 422 | function storeTmplItems( content ) { 423 | var keySuffix = "_" + cloneIndex, elem, elems, newClonedItems = {}, i, l, m; 424 | for ( i = 0, l = content.length; i < l; i++ ) { 425 | if ( (elem = content[i]).nodeType !== 1 ) { 426 | continue; 427 | } 428 | elems = elem.getElementsByTagName("*"); 429 | for ( m = elems.length - 1; m >= 0; m-- ) { 430 | processItemKey( elems[m] ); 431 | } 432 | processItemKey( elem ); 433 | } 434 | function processItemKey( el ) { 435 | var pntKey, pntNode = el, pntItem, tmplItem, key; 436 | // Ensure that each rendered template inserted into the DOM has its own template item, 437 | if ( (key = el.getAttribute( tmplItmAtt ))) { 438 | while ( pntNode.parentNode && (pntNode = pntNode.parentNode).nodeType === 1 && !(pntKey = pntNode.getAttribute( tmplItmAtt ))) { } 439 | if ( pntKey !== key ) { 440 | // The next ancestor with a _tmplitem expando is on a different key than this one. 441 | // So this is a top-level element within this template item 442 | // Set pntNode to the key of the parentNode, or to 0 if pntNode.parentNode is null, or pntNode is a fragment. 443 | pntNode = pntNode.parentNode ? (pntNode.nodeType === 11 ? 0 : (pntNode.getAttribute( tmplItmAtt ) || 0)) : 0; 444 | if ( !(tmplItem = newTmplItems[key]) ) { 445 | // The item is for wrapped content, and was copied from the temporary parent wrappedItem. 446 | tmplItem = wrappedItems[key]; 447 | tmplItem = newTmplItem( tmplItem, newTmplItems[pntNode]||wrappedItems[pntNode] ); 448 | tmplItem.key = ++itemKey; 449 | newTmplItems[itemKey] = tmplItem; 450 | } 451 | if ( cloneIndex ) { 452 | cloneTmplItem( key ); 453 | } 454 | } 455 | el.removeAttribute( tmplItmAtt ); 456 | } else if ( cloneIndex && (tmplItem = jQuery.data( el, "tmplItem" )) ) { 457 | // This was a rendered element, cloned during append or appendTo etc. 458 | // TmplItem stored in jQuery data has already been cloned in cloneCopyEvent. We must replace it with a fresh cloned tmplItem. 459 | cloneTmplItem( tmplItem.key ); 460 | newTmplItems[tmplItem.key] = tmplItem; 461 | pntNode = jQuery.data( el.parentNode, "tmplItem" ); 462 | pntNode = pntNode ? pntNode.key : 0; 463 | } 464 | if ( tmplItem ) { 465 | pntItem = tmplItem; 466 | // Find the template item of the parent element. 467 | // (Using !=, not !==, since pntItem.key is number, and pntNode may be a string) 468 | while ( pntItem && pntItem.key != pntNode ) { 469 | // Add this element as a top-level node for this rendered template item, as well as for any 470 | // ancestor items between this item and the item of its parent element 471 | pntItem.nodes.push( el ); 472 | pntItem = pntItem.parent; 473 | } 474 | // Delete content built during rendering - reduce API surface area and memory use, and avoid exposing of stale data after rendering... 475 | delete tmplItem._ctnt; 476 | delete tmplItem._wrap; 477 | // Store template item as jQuery data on the element 478 | jQuery.data( el, "tmplItem", tmplItem ); 479 | } 480 | function cloneTmplItem( key ) { 481 | key = key + keySuffix; 482 | tmplItem = newClonedItems[key] = 483 | (newClonedItems[key] || newTmplItem( tmplItem, newTmplItems[tmplItem.parent.key + keySuffix] || tmplItem.parent )); 484 | } 485 | } 486 | } 487 | 488 | //---- Helper functions for template item ---- 489 | 490 | function tiCalls( content, tmpl, data, options ) { 491 | if ( !content ) { 492 | return stack.pop(); 493 | } 494 | stack.push({ _: content, tmpl: tmpl, item:this, data: data, options: options }); 495 | } 496 | 497 | function tiNest( tmpl, data, options ) { 498 | // nested template, using {{tmpl}} tag 499 | return jQuery.tmpl( jQuery.template( tmpl ), data, options, this ); 500 | } 501 | 502 | function tiWrap( call, wrapped ) { 503 | // nested template, using {{wrap}} tag 504 | var options = call.options || {}; 505 | options.wrapped = wrapped; 506 | // Apply the template, which may incorporate wrapped content, 507 | return jQuery.tmpl( jQuery.template( call.tmpl ), call.data, options, call.item ); 508 | } 509 | 510 | function tiHtml( filter, textOnly ) { 511 | var wrapped = this._wrap; 512 | return jQuery.map( 513 | jQuery( jQuery.isArray( wrapped ) ? wrapped.join("") : wrapped ).filter( filter || "*" ), 514 | function(e) { 515 | return textOnly ? 516 | e.innerText || e.textContent : 517 | e.outerHTML || outerHtml(e); 518 | }); 519 | } 520 | 521 | function tiUpdate() { 522 | var coll = this.nodes; 523 | jQuery.tmpl( null, null, null, this).insertBefore( coll[0] ); 524 | jQuery( coll ).remove(); 525 | } 526 | })( jQuery ); 527 | -------------------------------------------------------------------------------- /demos/feature-tests/basic/1a_delay-domready.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 21 | 22 | 23 | 24 | Results: 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /demos/feature-tests/basic/1b_delay-domready.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 22 | 23 | 24 | 25 | Results: 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /demos/feature-tests/basic/2a_def.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 30 | 31 | 32 | 33 | Results: 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /demos/feature-tests/basic/2b_def.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 23 | 24 | 25 | 26 | Results: 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /demos/feature-tests/basic/3_join-with-when.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 37 | 38 | 39 | 40 | Results: 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /demos/feature-tests/basic/4_bare.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 31 | 32 | 33 | 34 | Results: 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /demos/feature-tests/basic/5a_composite.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 23 | 24 | 25 | Results: 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /demos/feature-tests/basic/5b_composite-with-def.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 31 | 32 | 33 | Results: 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /demos/feature-tests/basic/6_static.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | Results: 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /demos/feature-tests/basic/7_fail.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /demos/feature-tests/basic/8_add-dependencies.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 18 | 19 | 20 | 21 | Results: 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /demos/feature-tests/basic/9_template-and-data.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /demos/feature-tests/console-test.js: -------------------------------------------------------------------------------- 1 | var testloaded = {}; 2 | 3 | function log( message ) { 4 | var log, console = document.getElementById("results"); 5 | if ( console ) { 6 | log = console.innerHTML; 7 | console.innerHTML = log + "
" + message; 8 | } 9 | } 10 | 11 | $( function() { 12 | var haveResults, ret = "
Files or 'SubFiles' executed before DomReady ran in the following order:
"; 13 | for ( var i in testloaded ) { 14 | haveResults = true; 15 | ret += " " + i + ", "; 16 | } 17 | if ( haveResults ) { 18 | log( ret + "

" ); 19 | } 20 | }) 21 | -------------------------------------------------------------------------------- /demos/feature-tests/resources/bare1.js: -------------------------------------------------------------------------------- 1 | window.testloaded.bare1 = ""; 2 | -------------------------------------------------------------------------------- /demos/feature-tests/resources/bare1.min.js: -------------------------------------------------------------------------------- 1 | window.testloaded.bare1min = ""; 2 | -------------------------------------------------------------------------------- /demos/feature-tests/resources/bare2.js: -------------------------------------------------------------------------------- 1 | window.testloaded.bare2 = ""; 2 | -------------------------------------------------------------------------------- /demos/feature-tests/resources/f.js: -------------------------------------------------------------------------------- 1 | ((window.$deferRun || function( run ){ run(); }) ( 2 | 3 | function( $, options ) { 4 | window.testloaded.f = ""; 5 | return options && options.myVal + ". File: f"; 6 | } 7 | 8 | )); -------------------------------------------------------------------------------- /demos/feature-tests/resources/folder1/a.js: -------------------------------------------------------------------------------- 1 | ((window.$deferRun || function( run ){ run(); }) ( 2 | 3 | function( $, options ) { 4 | window.testloaded.a = ""; 5 | if ( $ ) { 6 | return options && options.myVal + ". File: a"; 7 | } 8 | } 9 | 10 | )); 11 | -------------------------------------------------------------------------------- /demos/feature-tests/resources/folder1/a.min.js: -------------------------------------------------------------------------------- 1 | (window.$deferRun||function(n){n()})(function(n,t){return window.testloaded.a="",n?t&&t.myVal+". File: a":void 0}); 2 | //@ sourceMappingURL=a.min.js.map -------------------------------------------------------------------------------- /demos/feature-tests/resources/folder1/add-dependencies.js: -------------------------------------------------------------------------------- 1 | ((window.$deferRun || function( run ){ run(); }) ( 2 | 3 | function( $, options ) { 4 | window.testloaded.addDependencies = ""; 5 | return options && options && options.myVal + ". File: addDependencies"; 6 | }, 7 | 8 | { 9 | depends: "c", 10 | def: { 11 | c: { 12 | url: "../folder2/c.js", 13 | depends: "d" 14 | }, 15 | d: "../folder2/d.js" 16 | } 17 | } 18 | 19 | )); 20 | -------------------------------------------------------------------------------- /demos/feature-tests/resources/folder2/c.js: -------------------------------------------------------------------------------- 1 | ((window.$deferRun || function( run ){ run(); }) ( 2 | 3 | function( $, options ) { 4 | window.testloaded.c = ""; 5 | return options && options.myVal + ". File: c"; 6 | } 7 | 8 | )); 9 | -------------------------------------------------------------------------------- /demos/feature-tests/resources/folder2/composite-dcf.js: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////// 2 | // Composite 3 | ((window.$deferRun || function( run ){ run(); }) ( 4 | function( $, options ) { 5 | 6 | ((window.$deferRun || function( run ){ run(); }) ( 7 | function( $, options ) { 8 | window.testloaded.d = ""; 9 | return options && options && options.myVal + ". File: d"; 10 | })); 11 | 12 | ((window.$deferRun || function( run ){ run(); }) ( 13 | function( $, options ) { 14 | window.testloaded.c = ""; 15 | return options && options && options.myVal + ". File: c"; 16 | })); 17 | 18 | ((window.$deferRun || function( run ){ run(); }) ( 19 | function( $, options ) { 20 | window.testloaded.f = ""; 21 | return options && options && options.myVal + ". File: f"; 22 | })); 23 | 24 | }, 25 | { 26 | depends: "../folder1/a.js", 27 | contains: ["d", "c", "../f.js"], 28 | def: { 29 | c: "c.js", 30 | d: { 31 | url: "d.js", 32 | depends: "c" 33 | } 34 | } 35 | } 36 | )); 37 | 38 | 39 | -------------------------------------------------------------------------------- /demos/feature-tests/resources/folder2/composite-fed.js: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////// 2 | // Composite 3 | ((window.$deferRun || function( run ){ run(); }) ( 4 | function( $, options ) { 5 | 6 | ((window.$deferRun || function( run ){ run(); }) ( 7 | function( $, options ) { 8 | window.testloaded.f = ""; 9 | return options && options && options.myVal + ". File: FED f"; 10 | })); 11 | 12 | ((window.$deferRun || function( run ){ run(); }) ( 13 | function( $, options ) { 14 | window.testloaded.e = ""; 15 | return options && options && options.myVal + ". File: FED e"; 16 | })); 17 | 18 | ((window.$deferRun || function( run ){ run(); }) ( 19 | function( $, options ) { 20 | window.testloaded.d = ""; 21 | return options && options && options.myVal + ". File: FED d"; 22 | })); 23 | 24 | } 25 | )); 26 | 27 | 28 | -------------------------------------------------------------------------------- /demos/feature-tests/resources/folder2/d.js: -------------------------------------------------------------------------------- 1 | ((window.$deferRun || function( run ){ run(); }) ( 2 | 3 | function( $, options ) { 4 | window.testloaded.d = ""; 5 | return options && options.myVal + ". File: d"; 6 | } 7 | 8 | )); 9 | -------------------------------------------------------------------------------- /demos/feature-tests/resources/folder2/e.js: -------------------------------------------------------------------------------- 1 | ((window.$deferRun || function( run ){ run(); }) ( 2 | 3 | function( $, options ) { 4 | window.testloaded.e = ""; 5 | return options && options.myVal + ". File: e"; 6 | }, 7 | 8 | "c.js" 9 | 10 | )); 11 | -------------------------------------------------------------------------------- /demos/feature-tests/resources/myscriptdefs.js: -------------------------------------------------------------------------------- 1 | $.deferDef({ 2 | a: { 3 | url: "folder1/a.js", 4 | minUrl: "folder1/a.min.js", 5 | depends: [ "e", "f.js" ] 6 | }, 7 | e: "folder2/e.js" 8 | }); 9 | -------------------------------------------------------------------------------- /demos/feature-tests/templates-and-data/mydata.js: -------------------------------------------------------------------------------- 1 | ((window.$deferRun || function( run ){ run(); }) ( 2 | 3 | function( $, options ) { 4 | return [ 5 | { 6 | firstName: "Pete", 7 | lastName: "Henrikson", 8 | url: "http://www.google.com", 9 | cities: [ 10 | "Seattle, WA", 11 | "San Francisco, CA" 12 | ] 13 | }, 14 | { 15 | firstName: "Rosa", 16 | lastName: "Almada", 17 | url: "http://www.google.com", 18 | cities: [ 19 | "New York, NY" 20 | ] 21 | } 22 | ]; 23 | } 24 | 25 | )); 26 | -------------------------------------------------------------------------------- /demos/feature-tests/templates-and-data/myrichdata.js: -------------------------------------------------------------------------------- 1 | ((window.$deferRun || function( run ){ run(); }) ( 2 | 3 | function( $, options ) { 4 | return [ 5 | { 6 | firstName: "Pete", 7 | lastName: "Henrikson", 8 | url: "http://www.google.com", 9 | cities: [ 10 | "Seattle, WA", 11 | "San Francisco, CA" 12 | ] 13 | }, 14 | { 15 | firstName: "Rosa", 16 | lastName: "Almada", 17 | url: "http://www.google.com", 18 | cities: [ 19 | "New York, NY" 20 | ] 21 | } 22 | ]; 23 | } 24 | 25 | )); 26 | -------------------------------------------------------------------------------- /demos/feature-tests/templates-and-data/mytmpl.js: -------------------------------------------------------------------------------- 1 | ((window.$deferRun || function( run ){ run(); }) ( 2 | 3 | function( $, options ) { 4 | return '
  • ${firstName} ${lastName}
  • '; 5 | } 6 | 7 | )); 8 | -------------------------------------------------------------------------------- /demos/feature-tests/templates-and-data/richtmpls.js: -------------------------------------------------------------------------------- 1 | $deferRun( function($) { 2 | $deferRun( function() { 3 | 4 | // outer 5 | return $.template( "
  • ${firstName} ${lastName}
  • Cities:
  • {{tmpl(cities) '@inner'}}" ); 6 | 7 | }); 8 | 9 | $deferRun( function() { 10 | 11 | // inner 12 | return $.template( "
  • ${$data}
  • " ); 13 | 14 | }); 15 | 16 | }); 17 | -------------------------------------------------------------------------------- /demos/feature-tests/with-or-without-jquery/1_with-jquery.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | 12 | 21 | 22 | 23 | 24 | Results: 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /demos/feature-tests/with-or-without-jquery/2_non-jquery-version.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | 20 | 21 | 22 | 23 | Results: 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /demos/movies/pages/1_movies.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | jQuery + OData + Netflix Catalog API 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 26 | 27 | 28 |
    29 |

    Netflix: Book a Movie...

    30 | 31 | 39 | 40 |
    41 | 42 |
    43 | 44 | 47 |
    45 | 0 items in Cart... 46 |
    48 |
    49 |
    50 | 51 | 59 | 60 | 79 | 80 | 90 | 91 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /demos/movies/pages/2_movies-when-data-and-script.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | jQuery + OData + Netflix Catalog API 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 47 | 48 | 49 |
    50 |

    Netflix: Book a Movie...

    51 | 52 | 60 | 61 |
    62 | 63 |
    64 | 65 | 68 |
    66 | 0 items in Cart... 67 |
    69 |
    70 |
    71 | 72 | 80 | 81 | 100 | 101 | 111 | 112 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /demos/movies/pages/3_movie-lazy-load.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | jQuery + OData + Netflix Catalog API 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 55 | 56 | 57 |
    58 |

    Netflix: Book a Movie...

    59 | 60 | 61 | 62 | 70 | 71 |
    72 | 73 |
    74 | 75 | 78 |
    76 | 0 items in Cart... 77 |
    79 |
    80 |
    81 | 82 | 90 | 91 | 110 | 111 | 121 | 122 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /demos/movies/pages/4_movies-and-jquery-lazy-load.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | jQuery + OData + Netflix Catalog API 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 58 | 59 | 60 |
    61 |

    Netflix: Book a Movie...

    62 | 63 | 64 | 65 | 73 | 74 |
    75 | 76 |
    77 | 78 | 81 |
    79 | 0 items in Cart... 80 |
    82 |
    83 |
    84 | 85 | 93 | 94 | 113 | 114 | 124 | 125 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /demos/movies/resources/css/jquery-ui-1.8.1.custom.css: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery UI CSS Framework 3 | * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) 4 | * Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. 5 | */ 6 | 7 | /* Layout helpers 8 | ----------------------------------*/ 9 | .ui-helper-hidden { display: none; } 10 | .ui-helper-hidden-accessible { position: absolute; left: -99999999px; } 11 | .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } 12 | .ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } 13 | .ui-helper-clearfix { display: inline-block; } 14 | /* required comment for clearfix to work in Opera \*/ 15 | * html .ui-helper-clearfix { height:1%; } 16 | .ui-helper-clearfix { display:block; } 17 | /* end clearfix */ 18 | .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } 19 | 20 | 21 | /* Interaction Cues 22 | ----------------------------------*/ 23 | .ui-state-disabled { cursor: default !important; } 24 | 25 | 26 | /* Icons 27 | ----------------------------------*/ 28 | 29 | /* states and images */ 30 | .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } 31 | 32 | 33 | /* Misc visuals 34 | ----------------------------------*/ 35 | 36 | /* Overlays */ 37 | .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } 38 | 39 | 40 | /* 41 | * jQuery UI CSS Framework 42 | * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) 43 | * Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. 44 | * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Arial,sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=6px&bgColorHeader=cc0000&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=15&borderColorHeader=e3a1a1&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=eeeeee&fcContent=333333&iconColorContent=cc0000&bgColorDefault=eeeeee&bgTextureDefault=04_highlight_hard.png&bgImgOpacityDefault=100&borderColorDefault=d8dcdf&fcDefault=004276&iconColorDefault=cc0000&bgColorHover=f6f6f6&bgTextureHover=04_highlight_hard.png&bgImgOpacityHover=100&borderColorHover=cdd5da&fcHover=111111&iconColorHover=cc0000&bgColorActive=ffffff&bgTextureActive=01_flat.png&bgImgOpacityActive=65&borderColorActive=eeeeee&fcActive=cc0000&iconColorActive=cc0000&bgColorHighlight=fbf8ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcd3a1&fcHighlight=444444&iconColorHighlight=004276&bgColorError=f3d8d8&bgTextureError=08_diagonals_thick.png&bgImgOpacityError=75&borderColorError=cc0000&fcError=2e2e2e&iconColorError=cc0000&bgColorOverlay=a6a6a6&bgTextureOverlay=09_dots_small.png&bgImgOpacityOverlay=65&opacityOverlay=40&bgColorShadow=333333&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=10&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px 45 | */ 46 | 47 | 48 | /* Component containers 49 | ----------------------------------*/ 50 | .ui-widget { font-family: Arial,sans-serif; font-size: 1.1em; } 51 | .ui-widget .ui-widget { font-size: 1em; } 52 | .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Arial,sans-serif; font-size: 1em; } 53 | .ui-widget-content { border: 1px solid #eeeeee; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #333333; } 54 | .ui-widget-content a { color: #333333; } 55 | .ui-widget-header { border: 1px solid #e3a1a1; background: #cc0000 url(images/ui-bg_highlight-soft_15_cc0000_1x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; } 56 | .ui-widget-header a { color: #ffffff; } 57 | 58 | /* Interaction states 59 | ----------------------------------*/ 60 | .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d8dcdf; background: #eeeeee url(images/ui-bg_highlight-hard_100_eeeeee_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #004276; } 61 | .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #004276; text-decoration: none; } 62 | .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #cdd5da; background: #f6f6f6 url(images/ui-bg_highlight-hard_100_f6f6f6_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #111111; } 63 | .ui-state-hover a, .ui-state-hover a:hover { color: #111111; text-decoration: none; } 64 | .ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #eeeeee; background: #ffffff url(images/ui-bg_flat_65_ffffff_40x100.png) 50% 50% repeat-x; font-weight: bold; color: #cc0000; } 65 | .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #cc0000; text-decoration: none; } 66 | .ui-widget :active { outline: none; } 67 | 68 | /* Interaction Cues 69 | ----------------------------------*/ 70 | .ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcd3a1; background: #fbf8ee url(images/ui-bg_glass_55_fbf8ee_1x400.png) 50% 50% repeat-x; color: #444444; } 71 | .ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #444444; } 72 | .ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cc0000; background: #f3d8d8 url(images/ui-bg_diagonals-thick_75_f3d8d8_40x40.png) 50% 50% repeat; color: #2e2e2e; } 73 | .ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #2e2e2e; } 74 | .ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #2e2e2e; } 75 | .ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } 76 | .ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } 77 | .ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } 78 | 79 | /* Icons 80 | ----------------------------------*/ 81 | 82 | /* states and images */ 83 | .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_cc0000_256x240.png); } 84 | .ui-widget-content .ui-icon {background-image: url(images/ui-icons_cc0000_256x240.png); } 85 | .ui-widget-header .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); } 86 | .ui-state-default .ui-icon { background-image: url(images/ui-icons_cc0000_256x240.png); } 87 | .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_cc0000_256x240.png); } 88 | .ui-state-active .ui-icon {background-image: url(images/ui-icons_cc0000_256x240.png); } 89 | .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_004276_256x240.png); } 90 | .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cc0000_256x240.png); } 91 | 92 | /* positioning */ 93 | .ui-icon-carat-1-n { background-position: 0 0; } 94 | .ui-icon-carat-1-ne { background-position: -16px 0; } 95 | .ui-icon-carat-1-e { background-position: -32px 0; } 96 | .ui-icon-carat-1-se { background-position: -48px 0; } 97 | .ui-icon-carat-1-s { background-position: -64px 0; } 98 | .ui-icon-carat-1-sw { background-position: -80px 0; } 99 | .ui-icon-carat-1-w { background-position: -96px 0; } 100 | .ui-icon-carat-1-nw { background-position: -112px 0; } 101 | .ui-icon-carat-2-n-s { background-position: -128px 0; } 102 | .ui-icon-carat-2-e-w { background-position: -144px 0; } 103 | .ui-icon-triangle-1-n { background-position: 0 -16px; } 104 | .ui-icon-triangle-1-ne { background-position: -16px -16px; } 105 | .ui-icon-triangle-1-e { background-position: -32px -16px; } 106 | .ui-icon-triangle-1-se { background-position: -48px -16px; } 107 | .ui-icon-triangle-1-s { background-position: -64px -16px; } 108 | .ui-icon-triangle-1-sw { background-position: -80px -16px; } 109 | .ui-icon-triangle-1-w { background-position: -96px -16px; } 110 | .ui-icon-triangle-1-nw { background-position: -112px -16px; } 111 | .ui-icon-triangle-2-n-s { background-position: -128px -16px; } 112 | .ui-icon-triangle-2-e-w { background-position: -144px -16px; } 113 | .ui-icon-arrow-1-n { background-position: 0 -32px; } 114 | .ui-icon-arrow-1-ne { background-position: -16px -32px; } 115 | .ui-icon-arrow-1-e { background-position: -32px -32px; } 116 | .ui-icon-arrow-1-se { background-position: -48px -32px; } 117 | .ui-icon-arrow-1-s { background-position: -64px -32px; } 118 | .ui-icon-arrow-1-sw { background-position: -80px -32px; } 119 | .ui-icon-arrow-1-w { background-position: -96px -32px; } 120 | .ui-icon-arrow-1-nw { background-position: -112px -32px; } 121 | .ui-icon-arrow-2-n-s { background-position: -128px -32px; } 122 | .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } 123 | .ui-icon-arrow-2-e-w { background-position: -160px -32px; } 124 | .ui-icon-arrow-2-se-nw { background-position: -176px -32px; } 125 | .ui-icon-arrowstop-1-n { background-position: -192px -32px; } 126 | .ui-icon-arrowstop-1-e { background-position: -208px -32px; } 127 | .ui-icon-arrowstop-1-s { background-position: -224px -32px; } 128 | .ui-icon-arrowstop-1-w { background-position: -240px -32px; } 129 | .ui-icon-arrowthick-1-n { background-position: 0 -48px; } 130 | .ui-icon-arrowthick-1-ne { background-position: -16px -48px; } 131 | .ui-icon-arrowthick-1-e { background-position: -32px -48px; } 132 | .ui-icon-arrowthick-1-se { background-position: -48px -48px; } 133 | .ui-icon-arrowthick-1-s { background-position: -64px -48px; } 134 | .ui-icon-arrowthick-1-sw { background-position: -80px -48px; } 135 | .ui-icon-arrowthick-1-w { background-position: -96px -48px; } 136 | .ui-icon-arrowthick-1-nw { background-position: -112px -48px; } 137 | .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } 138 | .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } 139 | .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } 140 | .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } 141 | .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } 142 | .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } 143 | .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } 144 | .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } 145 | .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } 146 | .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } 147 | .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } 148 | .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } 149 | .ui-icon-arrowreturn-1-w { background-position: -64px -64px; } 150 | .ui-icon-arrowreturn-1-n { background-position: -80px -64px; } 151 | .ui-icon-arrowreturn-1-e { background-position: -96px -64px; } 152 | .ui-icon-arrowreturn-1-s { background-position: -112px -64px; } 153 | .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } 154 | .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } 155 | .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } 156 | .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } 157 | .ui-icon-arrow-4 { background-position: 0 -80px; } 158 | .ui-icon-arrow-4-diag { background-position: -16px -80px; } 159 | .ui-icon-extlink { background-position: -32px -80px; } 160 | .ui-icon-newwin { background-position: -48px -80px; } 161 | .ui-icon-refresh { background-position: -64px -80px; } 162 | .ui-icon-shuffle { background-position: -80px -80px; } 163 | .ui-icon-transfer-e-w { background-position: -96px -80px; } 164 | .ui-icon-transferthick-e-w { background-position: -112px -80px; } 165 | .ui-icon-folder-collapsed { background-position: 0 -96px; } 166 | .ui-icon-folder-open { background-position: -16px -96px; } 167 | .ui-icon-document { background-position: -32px -96px; } 168 | .ui-icon-document-b { background-position: -48px -96px; } 169 | .ui-icon-note { background-position: -64px -96px; } 170 | .ui-icon-mail-closed { background-position: -80px -96px; } 171 | .ui-icon-mail-open { background-position: -96px -96px; } 172 | .ui-icon-suitcase { background-position: -112px -96px; } 173 | .ui-icon-comment { background-position: -128px -96px; } 174 | .ui-icon-person { background-position: -144px -96px; } 175 | .ui-icon-print { background-position: -160px -96px; } 176 | .ui-icon-trash { background-position: -176px -96px; } 177 | .ui-icon-locked { background-position: -192px -96px; } 178 | .ui-icon-unlocked { background-position: -208px -96px; } 179 | .ui-icon-bookmark { background-position: -224px -96px; } 180 | .ui-icon-tag { background-position: -240px -96px; } 181 | .ui-icon-home { background-position: 0 -112px; } 182 | .ui-icon-flag { background-position: -16px -112px; } 183 | .ui-icon-calendar { background-position: -32px -112px; } 184 | .ui-icon-cart { background-position: -48px -112px; } 185 | .ui-icon-pencil { background-position: -64px -112px; } 186 | .ui-icon-clock { background-position: -80px -112px; } 187 | .ui-icon-disk { background-position: -96px -112px; } 188 | .ui-icon-calculator { background-position: -112px -112px; } 189 | .ui-icon-zoomin { background-position: -128px -112px; } 190 | .ui-icon-zoomout { background-position: -144px -112px; } 191 | .ui-icon-search { background-position: -160px -112px; } 192 | .ui-icon-wrench { background-position: -176px -112px; } 193 | .ui-icon-gear { background-position: -192px -112px; } 194 | .ui-icon-heart { background-position: -208px -112px; } 195 | .ui-icon-star { background-position: -224px -112px; } 196 | .ui-icon-link { background-position: -240px -112px; } 197 | .ui-icon-cancel { background-position: 0 -128px; } 198 | .ui-icon-plus { background-position: -16px -128px; } 199 | .ui-icon-plusthick { background-position: -32px -128px; } 200 | .ui-icon-minus { background-position: -48px -128px; } 201 | .ui-icon-minusthick { background-position: -64px -128px; } 202 | .ui-icon-close { background-position: -80px -128px; } 203 | .ui-icon-closethick { background-position: -96px -128px; } 204 | .ui-icon-key { background-position: -112px -128px; } 205 | .ui-icon-lightbulb { background-position: -128px -128px; } 206 | .ui-icon-scissors { background-position: -144px -128px; } 207 | .ui-icon-clipboard { background-position: -160px -128px; } 208 | .ui-icon-copy { background-position: -176px -128px; } 209 | .ui-icon-contact { background-position: -192px -128px; } 210 | .ui-icon-image { background-position: -208px -128px; } 211 | .ui-icon-video { background-position: -224px -128px; } 212 | .ui-icon-script { background-position: -240px -128px; } 213 | .ui-icon-alert { background-position: 0 -144px; } 214 | .ui-icon-info { background-position: -16px -144px; } 215 | .ui-icon-notice { background-position: -32px -144px; } 216 | .ui-icon-help { background-position: -48px -144px; } 217 | .ui-icon-check { background-position: -64px -144px; } 218 | .ui-icon-bullet { background-position: -80px -144px; } 219 | .ui-icon-radio-off { background-position: -96px -144px; } 220 | .ui-icon-radio-on { background-position: -112px -144px; } 221 | .ui-icon-pin-w { background-position: -128px -144px; } 222 | .ui-icon-pin-s { background-position: -144px -144px; } 223 | .ui-icon-play { background-position: 0 -160px; } 224 | .ui-icon-pause { background-position: -16px -160px; } 225 | .ui-icon-seek-next { background-position: -32px -160px; } 226 | .ui-icon-seek-prev { background-position: -48px -160px; } 227 | .ui-icon-seek-end { background-position: -64px -160px; } 228 | .ui-icon-seek-start { background-position: -80px -160px; } 229 | /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ 230 | .ui-icon-seek-first { background-position: -80px -160px; } 231 | .ui-icon-stop { background-position: -96px -160px; } 232 | .ui-icon-eject { background-position: -112px -160px; } 233 | .ui-icon-volume-off { background-position: -128px -160px; } 234 | .ui-icon-volume-on { background-position: -144px -160px; } 235 | .ui-icon-power { background-position: 0 -176px; } 236 | .ui-icon-signal-diag { background-position: -16px -176px; } 237 | .ui-icon-signal { background-position: -32px -176px; } 238 | .ui-icon-battery-0 { background-position: -48px -176px; } 239 | .ui-icon-battery-1 { background-position: -64px -176px; } 240 | .ui-icon-battery-2 { background-position: -80px -176px; } 241 | .ui-icon-battery-3 { background-position: -96px -176px; } 242 | .ui-icon-circle-plus { background-position: 0 -192px; } 243 | .ui-icon-circle-minus { background-position: -16px -192px; } 244 | .ui-icon-circle-close { background-position: -32px -192px; } 245 | .ui-icon-circle-triangle-e { background-position: -48px -192px; } 246 | .ui-icon-circle-triangle-s { background-position: -64px -192px; } 247 | .ui-icon-circle-triangle-w { background-position: -80px -192px; } 248 | .ui-icon-circle-triangle-n { background-position: -96px -192px; } 249 | .ui-icon-circle-arrow-e { background-position: -112px -192px; } 250 | .ui-icon-circle-arrow-s { background-position: -128px -192px; } 251 | .ui-icon-circle-arrow-w { background-position: -144px -192px; } 252 | .ui-icon-circle-arrow-n { background-position: -160px -192px; } 253 | .ui-icon-circle-zoomin { background-position: -176px -192px; } 254 | .ui-icon-circle-zoomout { background-position: -192px -192px; } 255 | .ui-icon-circle-check { background-position: -208px -192px; } 256 | .ui-icon-circlesmall-plus { background-position: 0 -208px; } 257 | .ui-icon-circlesmall-minus { background-position: -16px -208px; } 258 | .ui-icon-circlesmall-close { background-position: -32px -208px; } 259 | .ui-icon-squaresmall-plus { background-position: -48px -208px; } 260 | .ui-icon-squaresmall-minus { background-position: -64px -208px; } 261 | .ui-icon-squaresmall-close { background-position: -80px -208px; } 262 | .ui-icon-grip-dotted-vertical { background-position: 0 -224px; } 263 | .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } 264 | .ui-icon-grip-solid-vertical { background-position: -32px -224px; } 265 | .ui-icon-grip-solid-horizontal { background-position: -48px -224px; } 266 | .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } 267 | .ui-icon-grip-diagonal-se { background-position: -80px -224px; } 268 | 269 | 270 | /* Misc visuals 271 | ----------------------------------*/ 272 | 273 | /* Corner radius */ 274 | .ui-corner-tl { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; border-top-left-radius: 6px; } 275 | .ui-corner-tr { -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; border-top-right-radius: 6px; } 276 | .ui-corner-bl { -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px; } 277 | .ui-corner-br { -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px; } 278 | .ui-corner-top { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; border-top-left-radius: 6px; -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; border-top-right-radius: 6px; } 279 | .ui-corner-bottom { -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px; -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px; } 280 | .ui-corner-right { -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; border-top-right-radius: 6px; -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px; } 281 | .ui-corner-left { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; border-top-left-radius: 6px; -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px; } 282 | .ui-corner-all { -moz-border-radius: 6px; -webkit-border-radius: 6px; border-radius: 6px; } 283 | 284 | /* Overlays */ 285 | .ui-widget-overlay { background: #a6a6a6 url(images/ui-bg_dots-small_65_a6a6a6_2x2.png) 50% 50% repeat; opacity: .40;filter:Alpha(Opacity=40); } 286 | .ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #333333 url(images/ui-bg_flat_0_333333_40x100.png) 50% 50% repeat-x; opacity: .10;filter:Alpha(Opacity=10); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/* Accordion 287 | ----------------------------------*/ 288 | .ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } 289 | .ui-accordion .ui-accordion-li-fix { display: inline; } 290 | .ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } 291 | .ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; } 292 | /* IE7-/Win - Fix extra vertical space in lists */ 293 | .ui-accordion a { zoom: 1; } 294 | .ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; } 295 | .ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } 296 | .ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; } 297 | .ui-accordion .ui-accordion-content-active { display: block; }/* Button 298 | ----------------------------------*/ 299 | 300 | .ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */ 301 | .ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */ 302 | button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */ 303 | .ui-button-icons-only { width: 3.4em; } 304 | button.ui-button-icons-only { width: 3.7em; } 305 | 306 | /*button text element */ 307 | .ui-button .ui-button-text { display: block; line-height: 1.4; } 308 | .ui-button-text-only .ui-button-text { padding: .4em 1em; } 309 | .ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; } 310 | .ui-button-text-icon .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; } 311 | .ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; } 312 | /* no icon support for input elements, provide padding by default */ 313 | input.ui-button { padding: .4em 1em; } 314 | 315 | /*button icon element(s) */ 316 | .ui-button-icon-only .ui-icon, .ui-button-text-icon .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; } 317 | .ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; } 318 | .ui-button-text-icon .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; } 319 | .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } 320 | 321 | /*button sets*/ 322 | .ui-buttonset { margin-right: 7px; } 323 | .ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; } 324 | 325 | /* workarounds */ 326 | button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */ 327 | 328 | 329 | 330 | 331 | 332 | /* Slider 333 | ----------------------------------*/ 334 | .ui-slider { position: relative; text-align: left; } 335 | .ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } 336 | .ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; } 337 | 338 | .ui-slider-horizontal { height: .8em; } 339 | .ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } 340 | .ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } 341 | .ui-slider-horizontal .ui-slider-range-min { left: 0; } 342 | .ui-slider-horizontal .ui-slider-range-max { right: 0; } 343 | 344 | .ui-slider-vertical { width: .8em; height: 100px; } 345 | .ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } 346 | .ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } 347 | .ui-slider-vertical .ui-slider-range-min { bottom: 0; } 348 | .ui-slider-vertical .ui-slider-range-max { top: 0; }/* Datepicker 349 | ----------------------------------*/ 350 | .ui-datepicker { width: 17em; padding: .2em .2em 0; } 351 | .ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } 352 | .ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } 353 | .ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } 354 | .ui-datepicker .ui-datepicker-prev { left:2px; } 355 | .ui-datepicker .ui-datepicker-next { right:2px; } 356 | .ui-datepicker .ui-datepicker-prev-hover { left:1px; } 357 | .ui-datepicker .ui-datepicker-next-hover { right:1px; } 358 | .ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } 359 | .ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } 360 | .ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; } 361 | .ui-datepicker select.ui-datepicker-month-year {width: 100%;} 362 | .ui-datepicker select.ui-datepicker-month, 363 | .ui-datepicker select.ui-datepicker-year { width: 49%;} 364 | .ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } 365 | .ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } 366 | .ui-datepicker td { border: 0; padding: 1px; } 367 | .ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } 368 | .ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } 369 | .ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } 370 | .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } 371 | 372 | /* with multiple calendars */ 373 | .ui-datepicker.ui-datepicker-multi { width:auto; } 374 | .ui-datepicker-multi .ui-datepicker-group { float:left; } 375 | .ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } 376 | .ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } 377 | .ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } 378 | .ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } 379 | .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } 380 | .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } 381 | .ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } 382 | .ui-datepicker-row-break { clear:both; width:100%; } 383 | 384 | /* RTL support */ 385 | .ui-datepicker-rtl { direction: rtl; } 386 | .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } 387 | .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } 388 | .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } 389 | .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } 390 | .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } 391 | .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } 392 | .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } 393 | .ui-datepicker-rtl .ui-datepicker-group { float:right; } 394 | .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } 395 | .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } 396 | 397 | /* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ 398 | .ui-datepicker-cover { 399 | display: none; /*sorry for IE5*/ 400 | display/**/: block; /*sorry for IE5*/ 401 | position: absolute; /*must have*/ 402 | z-index: -1; /*must have*/ 403 | filter: mask(); /*must have*/ 404 | top: -4px; /*must have*/ 405 | left: -4px; /*must have*/ 406 | width: 200px; /*must have*/ 407 | height: 200px; /*must have*/ 408 | } -------------------------------------------------------------------------------- /demos/movies/resources/css/movies.css: -------------------------------------------------------------------------------- 1 | body 2 | { 3 | background-color: #b9090b; 4 | font-family: Verdana; 5 | font-size: 12px; 6 | } 7 | 8 | #about 9 | { 10 | text-align:center; 11 | margin: auto; 12 | margin-bottom: 5px; 13 | background-color: #F9F5FA; 14 | padding: 3px; 15 | width: 50%; 16 | } 17 | 18 | #pageBody 19 | { 20 | display: block; 21 | clear: both; 22 | position: relative; 23 | margin: auto; 24 | width: 90%; 25 | background-color: #F9F5FA; 26 | padding: 10px 15px 5px 15px; 27 | } 28 | 29 | #genres 30 | { 31 | clear: both; 32 | display: block; 33 | padding: 0; 34 | } 35 | 36 | #genres li 37 | { 38 | list-style: none; 39 | float: left; 40 | border: 1px solid #888; 41 | text-decoration: none; 42 | margin: 0 5px 0 0; 43 | padding: 5px; 44 | cursor: pointer; 45 | background-color: #fff; 46 | } 47 | 48 | #genres li:hover 49 | { 50 | border: 1px solid #003f7e; 51 | } 52 | 53 | #genres li.selected 54 | { 55 | border: 1px solid #003f7e; 56 | color: #042CCA; 57 | font-weight: 700; 58 | background: url(../images/ui-bg_glass_75_dadada_1x400.png) repeat-x 50% 50%; 59 | } 60 | 61 | #pager 62 | { 63 | width: 100%; 64 | float: left; 65 | clear: left; 66 | margin: 0 0 10px; 67 | } 68 | 69 | #pager ul.pages 70 | { 71 | display: block; 72 | border: none; 73 | text-transform: uppercase; 74 | font-size: 10px; 75 | padding: 0; 76 | } 77 | 78 | #pager ul.pages li 79 | { 80 | list-style: none; 81 | float: left; 82 | border: 1px solid #888; 83 | text-decoration: none; 84 | margin: 0 5px 0 0; 85 | padding: 5px; 86 | background-color: #fff; 87 | } 88 | 89 | #pager ul.pages li:hover 90 | { 91 | border: 1px solid #00376f; 92 | } 93 | 94 | #pager ul.pages li.pgEmpty 95 | { 96 | border: 1px solid #ccc; 97 | color: #aaa; 98 | cursor: default; 99 | } 100 | 101 | #pager ul.pages li.pgCurrent 102 | { 103 | border: 1px solid #003f7e; 104 | color: #042CCA; 105 | font-weight: 700; 106 | background: url(../images/ui-bg_glass_75_dadada_1x400.png) #dadada repeat-x 50% 50%; 107 | } 108 | 109 | #movieList 110 | { 111 | display: block; 112 | float: left; 113 | width: 49.7%; 114 | clear: both; 115 | } 116 | 117 | #movieList > div 118 | { 119 | border: 1px solid #00509f; 120 | margin-bottom: 10px; 121 | padding: 8px; 122 | background-color: #fff; 123 | } 124 | 125 | #movieList div div 126 | { 127 | margin-right: 8px; 128 | float: left; 129 | width: 120px; 130 | height: 150px; 131 | } 132 | 133 | #movieList div img 134 | { 135 | height: 140px; 136 | } 137 | 138 | #movieList div br, #pageBody br 139 | { 140 | clear: both; 141 | } 142 | 143 | .buyButton 144 | { 145 | /* background: url(buyButton.png) no-repeat 0px -20px) */ 146 | } 147 | 148 | #bookingsList 149 | { 150 | border-collapse: collapse; 151 | border: 3px double #00509f; 152 | width: 49.7%; 153 | float: right; 154 | background-color: #fff; 155 | margin-bottom: 10px; 156 | } 157 | 158 | #bookingsList tr 159 | { 160 | border: 1px solid #00509f; 161 | padding: 5px 162 | } 163 | 164 | .cart td 165 | { 166 | height: 30px; 167 | border: 3px double #00509f; 168 | background-color: #F9F5FA; 169 | text-align:center; 170 | } 171 | 172 | .cart .cart-true 173 | { 174 | background-color: #E8DAEB; 175 | } 176 | 177 | .cart span.text 178 | { 179 | color: #2F5071; 180 | float:none; 181 | height: 25px; 182 | line-height: 25px; 183 | font-size: 14px; 184 | font-style: italic; 185 | border: none; 186 | } 187 | 188 | #submit, #cancel, #sort 189 | { 190 | color: #2F5071; 191 | font-weight: 700; 192 | float: right; 193 | height: 25px; 194 | line-height: 25px; 195 | font-style: italic; 196 | margin: 0 15px; 197 | } 198 | 199 | #submit, #cancel, #sortBtn 200 | { 201 | text-decoration: underline; 202 | cursor: pointer; 203 | } 204 | 205 | #submit 206 | { 207 | float: left; 208 | } 209 | 210 | .bookingTitle 211 | { 212 | color: #2F5071; 213 | font-weight: bold; 214 | background: url(../images/ui-bg_highlight-hard_100_eeeeee_1x100.png) #e6e6e6 repeat-x 50% 50%; 215 | cursor: pointer; 216 | } 217 | 218 | .bookingTitle:hover, .bookingTitleEdit:hover 219 | { 220 | background: url(../images/ui-bg_glass_75_dadada_1x400.png) #dadada repeat-x 50% 50%; 221 | } 222 | 223 | .bookingTitleEdit 224 | { 225 | color: #042CCA; 226 | font-weight: bold; 227 | background: url(../images/ui-bg_highlight-hard_100_eeeeee_1x100.png) #e6e6e6 repeat-x 50% 50%; 228 | cursor: pointer; 229 | } 230 | 231 | .bookingTitle td 232 | { 233 | padding: 8px; 234 | } 235 | 236 | .bookingTitleEdit td 237 | { 238 | padding: 7px 8px 7px 8px; 239 | } 240 | 241 | .bookingEdit div 242 | { 243 | float: right; 244 | height: 116px; 245 | } 246 | 247 | .bookingEdit .fields 248 | { 249 | float: left; 250 | } 251 | 252 | .bookingEdit .fields span 253 | { 254 | margin: 12px 0 0 8px; 255 | display: inline-block; 256 | width: 100px; 257 | } 258 | 259 | .bookingEdit .fields input 260 | { 261 | margin: 12px 0 0 8px; 262 | width: 250px; 263 | } 264 | 265 | .bookingEdit img 266 | { 267 | height: 100px; 268 | margin: 8px; 269 | } 270 | 271 | .close 272 | { 273 | background-position: -96px -128px; 274 | float: right; 275 | cursor: pointer; 276 | } 277 | 278 | .ui-icon 279 | { 280 | width: 16px; 281 | height: 16px; 282 | background-image: url(../images/ui-icons_cc0000_256x240.png); 283 | } 284 | -------------------------------------------------------------------------------- /demos/movies/resources/images/ui-bg_diagonals-thick_75_f3d8d8_40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BorisMoore/jsdefer/367e2f1aa28e6f0d826db04e16189c4bc6555b4a/demos/movies/resources/images/ui-bg_diagonals-thick_75_f3d8d8_40x40.png -------------------------------------------------------------------------------- /demos/movies/resources/images/ui-bg_dots-small_65_a6a6a6_2x2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BorisMoore/jsdefer/367e2f1aa28e6f0d826db04e16189c4bc6555b4a/demos/movies/resources/images/ui-bg_dots-small_65_a6a6a6_2x2.png -------------------------------------------------------------------------------- /demos/movies/resources/images/ui-bg_flat_0_333333_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BorisMoore/jsdefer/367e2f1aa28e6f0d826db04e16189c4bc6555b4a/demos/movies/resources/images/ui-bg_flat_0_333333_40x100.png -------------------------------------------------------------------------------- /demos/movies/resources/images/ui-bg_flat_65_ffffff_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BorisMoore/jsdefer/367e2f1aa28e6f0d826db04e16189c4bc6555b4a/demos/movies/resources/images/ui-bg_flat_65_ffffff_40x100.png -------------------------------------------------------------------------------- /demos/movies/resources/images/ui-bg_flat_75_ffffff_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BorisMoore/jsdefer/367e2f1aa28e6f0d826db04e16189c4bc6555b4a/demos/movies/resources/images/ui-bg_flat_75_ffffff_40x100.png -------------------------------------------------------------------------------- /demos/movies/resources/images/ui-bg_glass_55_fbf8ee_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BorisMoore/jsdefer/367e2f1aa28e6f0d826db04e16189c4bc6555b4a/demos/movies/resources/images/ui-bg_glass_55_fbf8ee_1x400.png -------------------------------------------------------------------------------- /demos/movies/resources/images/ui-bg_glass_75_dadada_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BorisMoore/jsdefer/367e2f1aa28e6f0d826db04e16189c4bc6555b4a/demos/movies/resources/images/ui-bg_glass_75_dadada_1x400.png -------------------------------------------------------------------------------- /demos/movies/resources/images/ui-bg_highlight-hard_100_eeeeee_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BorisMoore/jsdefer/367e2f1aa28e6f0d826db04e16189c4bc6555b4a/demos/movies/resources/images/ui-bg_highlight-hard_100_eeeeee_1x100.png -------------------------------------------------------------------------------- /demos/movies/resources/images/ui-bg_highlight-hard_100_f6f6f6_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BorisMoore/jsdefer/367e2f1aa28e6f0d826db04e16189c4bc6555b4a/demos/movies/resources/images/ui-bg_highlight-hard_100_f6f6f6_1x100.png -------------------------------------------------------------------------------- /demos/movies/resources/images/ui-bg_highlight-soft_15_cc0000_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BorisMoore/jsdefer/367e2f1aa28e6f0d826db04e16189c4bc6555b4a/demos/movies/resources/images/ui-bg_highlight-soft_15_cc0000_1x100.png -------------------------------------------------------------------------------- /demos/movies/resources/images/ui-icons_004276_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BorisMoore/jsdefer/367e2f1aa28e6f0d826db04e16189c4bc6555b4a/demos/movies/resources/images/ui-icons_004276_256x240.png -------------------------------------------------------------------------------- /demos/movies/resources/images/ui-icons_cc0000_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BorisMoore/jsdefer/367e2f1aa28e6f0d826db04e16189c4bc6555b4a/demos/movies/resources/images/ui-icons_cc0000_256x240.png -------------------------------------------------------------------------------- /demos/movies/resources/images/ui-icons_ffffff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BorisMoore/jsdefer/367e2f1aa28e6f0d826db04e16189c4bc6555b4a/demos/movies/resources/images/ui-icons_ffffff_256x240.png -------------------------------------------------------------------------------- /demos/movies/resources/jqueryplugins/templates/jquery.tmpl.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery Templating Plugin 3 | * Copyright 2010, John Resig 4 | * Dual licensed under the MIT or GPL Version 2 licenses. 5 | */ 6 | ((window.$deferRun || function( run ){ run(); }) ( function( $, options ) { 7 | 8 | var oldManip = jQuery.fn.domManip, tmplItmAtt = "_tmplitem", htmlExpr = /^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /, 9 | newTmplItems = {}, wrappedItems = {}, appendToTmplItems, topTmplItem = { key: 0, data: {} }, itemKey = 0, cloneIndex = 0, stack = []; 10 | 11 | function newTmplItem( options, parentItem, fn, data ) { 12 | // Returns a template item data structure for a new rendered instance of a template (a 'template item'). 13 | // The content field is a hierarchical array of strings and nested items (to be 14 | // removed and replaced by nodes field of dom elements, once inserted in DOM). 15 | var newItem = { 16 | data: data || (parentItem ? parentItem.data : {}), 17 | _wrap: parentItem ? parentItem._wrap : null, 18 | tmpl: null, 19 | parent: parentItem || null, 20 | nodes: [], 21 | calls: tiCalls, 22 | nest: tiNest, 23 | wrap: tiWrap, 24 | html: tiHtml, 25 | update: tiUpdate 26 | }; 27 | if ( options ) { 28 | jQuery.extend( newItem, options, { nodes: [], parent: parentItem } ); 29 | } 30 | if ( fn ) { 31 | // Build the hierarchical content to be used during insertion into DOM 32 | newItem.tmpl = fn; 33 | newItem._ctnt = newItem._ctnt || newItem.tmpl( jQuery, newItem ); 34 | newItem.key = ++itemKey; 35 | // Keep track of new template item, until it is stored as jQuery Data on DOM element 36 | (stack.length ? wrappedItems : newTmplItems)[itemKey] = newItem; 37 | } 38 | return newItem; 39 | } 40 | 41 | // Override appendTo etc., in order to provide support for targeting multiple elements. (This code would disappear if integrated in jquery core). 42 | jQuery.each({ 43 | appendTo: "append", 44 | prependTo: "prepend", 45 | insertBefore: "before", 46 | insertAfter: "after", 47 | replaceAll: "replaceWith" 48 | }, function( name, original ) { 49 | jQuery.fn[ name ] = function( selector ) { 50 | var ret = [], insert = jQuery( selector ), elems, i, l, tmplItems, 51 | parent = this.length === 1 && this[0].parentNode; 52 | 53 | appendToTmplItems = newTmplItems || {}; 54 | if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) { 55 | insert[ original ]( this[0] ); 56 | ret = this; 57 | } else { 58 | for ( i = 0, l = insert.length; i < l; i++ ) { 59 | cloneIndex = i; 60 | elems = (i > 0 ? this.clone(true) : this).get(); 61 | jQuery.fn[ original ].apply( jQuery(insert[i]), elems ); 62 | ret = ret.concat( elems ); 63 | } 64 | cloneIndex = 0; 65 | ret = this.pushStack( ret, name, insert.selector ); 66 | } 67 | tmplItems = appendToTmplItems; 68 | appendToTmplItems = null; 69 | jQuery.tmpl.complete( tmplItems ); 70 | return ret; 71 | }; 72 | }); 73 | 74 | jQuery.fn.extend({ 75 | // Use first wrapped element as template markup. 76 | // Return wrapped set of template items, obtained by rendering template against data. 77 | tmpl: function( data, options, parentItem ) { 78 | return jQuery.tmpl( this[0], data, options, parentItem ); 79 | }, 80 | 81 | // Find which rendered template item the first wrapped DOM element belongs to 82 | tmplItem: function() { 83 | return jQuery.tmplItem( this[0] ); 84 | }, 85 | 86 | // Consider the first wrapped element as a template declaration, and get the compiled template or store it as a named template. 87 | template: function( name ) { 88 | return jQuery.template( name, this[0] ); 89 | }, 90 | 91 | domManip: function( args, table, callback, options ) { 92 | // This appears to be a bug in the appendTo, etc. implementation 93 | // it should be doing .call() instead of .apply(). See #6227 94 | if ( args[0] && args[0].nodeType ) { 95 | var dmArgs = jQuery.makeArray( arguments ), argsLength = args.length, i = 0, tmplItem; 96 | while ( i < argsLength && !(tmplItem = jQuery.data( args[i++], "tmplItem" ))) {} 97 | if ( argsLength > 1 ) { 98 | dmArgs[0] = [jQuery.makeArray( args )]; 99 | } 100 | if ( tmplItem && cloneIndex ) { 101 | dmArgs[2] = function( fragClone ) { 102 | // Handler called by oldManip when rendered template has been inserted into DOM. 103 | jQuery.tmpl.afterManip( this, fragClone, callback ); 104 | }; 105 | } 106 | oldManip.apply( this, dmArgs ); 107 | } else { 108 | oldManip.apply( this, arguments ); 109 | } 110 | cloneIndex = 0; 111 | if ( !appendToTmplItems ) { 112 | jQuery.tmpl.complete( newTmplItems ); 113 | } 114 | return this; 115 | } 116 | }); 117 | 118 | jQuery.extend({ 119 | // Return wrapped set of template items, obtained by rendering template against data. 120 | tmpl: function( tmpl, data, options, parentItem ) { 121 | var ret, topLevel = !parentItem; 122 | if ( topLevel ) { 123 | // This is a top-level tmpl call (not from a nested template using {{tmpl}}) 124 | parentItem = topTmplItem; 125 | tmpl = jQuery.template[tmpl] || jQuery.template( null, tmpl ); 126 | wrappedItems = {}; // Any wrapped items will be rebuilt, since this is top level 127 | } else if ( !tmpl ) { 128 | // The template item is already associated with DOM - this is a refresh. 129 | // Re-evaluate rendered template for the parentItem 130 | tmpl = parentItem.tmpl; 131 | newTmplItems[parentItem.key] = parentItem; 132 | parentItem.nodes = []; 133 | if ( parentItem.wrapped ) { 134 | updateWrapped( parentItem, parentItem.wrapped ); 135 | } 136 | // Rebuild, without creating a new template item 137 | return jQuery( build( parentItem, null, parentItem.tmpl( jQuery, parentItem ) )); 138 | } 139 | if ( !tmpl ) { 140 | return []; // Could throw... 141 | } 142 | if ( typeof data === "function" ) { 143 | data = data.call( parentItem || {} ); 144 | } 145 | if ( options && options.wrapped ) { 146 | updateWrapped( options, options.wrapped ); 147 | } 148 | ret = jQuery.isArray( data ) ? 149 | jQuery.map( data, function( dataItem ) { 150 | return dataItem ? newTmplItem( options, parentItem, tmpl, dataItem ) : null; 151 | }) : 152 | [ newTmplItem( options, parentItem, tmpl, data ) ]; 153 | 154 | return topLevel ? jQuery( build( parentItem, null, ret ) ) : ret; 155 | }, 156 | 157 | // Return rendered template item for an element. 158 | tmplItem: function( elem ) { 159 | var tmplItem; 160 | if ( elem instanceof jQuery ) { 161 | elem = elem[0]; 162 | } 163 | while ( elem && elem.nodeType === 1 && !(tmplItem = jQuery.data( elem, "tmplItem" )) && (elem = elem.parentNode) ) {} 164 | return tmplItem || topTmplItem; 165 | }, 166 | 167 | // Set: 168 | // Use $.template( name, tmpl ) to cache a named template, 169 | // where tmpl is a template string, a script element or a jQuery instance wrapping a script element, etc. 170 | // Use $( "selector" ).template( name ) to provide access by name to a script block template declaration. 171 | 172 | // Get: 173 | // Use $.template( name ) to access a cached template. 174 | // Also $( selectorToScriptBlock ).template(), or $.template( null, templateString ) 175 | // will return the compiled template, without adding a name reference. 176 | // If templateString includes at least one HTML tag, $.template( templateString ) is equivalent 177 | // to $.template( null, templateString ) 178 | template: function( name, tmpl ) { 179 | if (tmpl) { 180 | // Compile template and associate with name 181 | if ( typeof tmpl === "string" ) { 182 | // This is an HTML string being passed directly in. 183 | tmpl = buildTmplFn( tmpl ) 184 | } else if ( tmpl instanceof jQuery ) { 185 | tmpl = tmpl[0] || {}; 186 | } 187 | if ( tmpl.nodeType ) { 188 | // If this is a template block, use cached copy, or generate tmpl function and cache. 189 | tmpl = jQuery.data( tmpl, "tmpl" ) || jQuery.data( tmpl, "tmpl", buildTmplFn( tmpl.innerHTML )); 190 | } 191 | return typeof name === "string" ? (jQuery.template[name] = tmpl) : tmpl; 192 | } 193 | // Return named compiled template 194 | return typeof name !== "string" ? jQuery.template( null, name ): 195 | (jQuery.template[name] || 196 | // If not in map, treat as a selector. (If integrated with core, use quickExpr.exec) 197 | jQuery.template( null, htmlExpr.test( name ) ? name : jQuery( name ))); 198 | }, 199 | 200 | encode: function( text ) { 201 | // Do HTML encoding replacing < > & and ' and " by corresponding entities. 202 | return ("" + text).split("<").join("<").split(">").join(">").split('"').join(""").split("'").join("'"); 203 | } 204 | }); 205 | 206 | jQuery.extend( jQuery.tmpl, { 207 | tag: { 208 | "tmpl": { 209 | _default: { $2: "null" }, 210 | open: "if($notnull_1){_=_.concat($item.nest($1,$2));}" 211 | // tmpl target parameter can be of type function, so use $1, not $1a (so not auto detection of functions) 212 | // This means that {{tmpl foo}} treats foo as a template (which IS a function). 213 | // Explicit parens can be used if foo is a function that returns a template: {{tmpl foo()}}. 214 | }, 215 | "wrap": { 216 | _default: { $2: "null" }, 217 | open: "$item.calls(_,$1,$2);_=[];", 218 | close: "call=$item.calls();_=call._.concat($item.wrap(call,_));" 219 | }, 220 | "each": { 221 | _default: { $2: "$index, $value" }, 222 | open: "if($notnull_1){$.each($1a,function($2){with(this){", 223 | close: "}});}" 224 | }, 225 | "if": { 226 | open: "if(($notnull_1) && $1a){", 227 | close: "}" 228 | }, 229 | "else": { 230 | _default: { $1: "true" }, 231 | open: "}else if(($notnull_1) && $1a){" 232 | }, 233 | "html": { 234 | // Unecoded expression evaluation. 235 | open: "if($notnull_1){_.push($1a);}" 236 | }, 237 | "=": { 238 | // Encoded expression evaluation. Abbreviated form is ${}. 239 | _default: { $1: "$data" }, 240 | open: "if($notnull_1){_.push($.encode($1a));}" 241 | }, 242 | "!": { 243 | // Comment tag. Skipped by parser 244 | open: "" 245 | } 246 | }, 247 | 248 | // This stub can be overridden, e.g. in jquery.tmplplus for providing rendered events 249 | complete: function( items ) { 250 | newTmplItems = {}; 251 | }, 252 | 253 | // Call this from code which overrides domManip, or equivalent 254 | // Manage cloning/storing template items etc. 255 | afterManip: function afterManip( elem, fragClone, callback ) { 256 | // Provides cloned fragment ready for fixup prior to and after insertion into DOM 257 | var content = fragClone.nodeType === 11 ? 258 | jQuery.makeArray(fragClone.childNodes) : 259 | fragClone.nodeType === 1 ? [fragClone] : []; 260 | 261 | // Return fragment to original caller (e.g. append) for DOM insertion 262 | callback.call( elem, fragClone ); 263 | 264 | // Fragment has been inserted:- Add inserted nodes to tmplItem data structure. Replace inserted element annotations by jQuery.data. 265 | storeTmplItems( content ); 266 | cloneIndex++; 267 | } 268 | }); 269 | 270 | //========================== Private helper functions, used by code above ========================== 271 | 272 | function build( tmplItem, nested, content ) { 273 | // Convert hierarchical content into flat string array 274 | // and finally return array of fragments ready for DOM insertion 275 | var frag, ret = content ? jQuery.map( content, function( item ) { 276 | return (typeof item === "string") ? 277 | // Insert template item annotations, to be converted to jQuery.data( "tmplItem" ) when elems are inserted into DOM. 278 | (tmplItem.key ? item.replace( /(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g, "$1 " + tmplItmAtt + "=\"" + tmplItem.key + "\" $2" ) : item) : 279 | // This is a child template item. Build nested template. 280 | build( item, tmplItem, item._ctnt ); 281 | }) : 282 | // If content is not defined, insert tmplItem directly. Not a template item. May be a string, or a string array, e.g. from {{html $item.html()}}. 283 | tmplItem; 284 | if ( nested ) { 285 | return ret; 286 | } 287 | 288 | // top-level template 289 | ret = ret.join(""); 290 | 291 | // Support templates which have initial or final text nodes, or consist only of text 292 | // Also support HTML entities within the HTML markup. 293 | ret.replace( /^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/, function( all, before, middle, after) { 294 | frag = jQuery( middle ).get(); 295 | 296 | storeTmplItems( frag ); 297 | if ( before ) { 298 | frag = unencode( before ).concat(frag); 299 | } 300 | if ( after ) { 301 | frag = frag.concat(unencode( after )); 302 | } 303 | }); 304 | return frag ? frag : unencode( ret ); 305 | } 306 | 307 | function unencode( text ) { 308 | // Use createElement, since createTextNode will not render HTML entities correctly 309 | var el = document.createElement( "div" ); 310 | el.innerHTML = text; 311 | return jQuery.makeArray(el.childNodes); 312 | } 313 | 314 | // Generate a reusable function that will serve to render a template against data 315 | function buildTmplFn( markup ) { 316 | return new Function("jQuery","$item", 317 | "var $=jQuery,call,_=[],$data=$item.data;" + 318 | 319 | // Introduce the data as local variables using with(){} 320 | "with($data){_.push('" + 321 | 322 | // Convert the template into pure JavaScript 323 | jQuery.trim(markup) 324 | .replace( /([\\'])/g, "\\$1" ) 325 | .replace( /[\r\t\n]/g, " " ) 326 | .replace( /\$\{([^\}]*)\}/g, "{{= $1}}" ) 327 | .replace( /\{\{(\/?)(\w+|.)(?:\(((?:.(?!\}\}))*?)?\))?(?:\s+(.*?)?)?(\((.*?)\))?\s*\}\}/g, 328 | function( all, slash, type, fnargs, target, parens, args ) { 329 | var tag = jQuery.tmpl.tag[ type ], def, expr, exprAutoFnDetect; 330 | if ( !tag ) { 331 | throw "Template command not found: " + type; 332 | } 333 | def = tag._default || []; 334 | if ( parens && !/\w$/.test(target)) { 335 | target += parens; 336 | parens = ""; 337 | } 338 | if ( target ) { 339 | target = unescape( target ); 340 | args = args ? ("," + unescape( args ) + ")") : (parens ? ")" : ""); 341 | // Support for target being things like a.toLowerCase(); 342 | // In that case don't call with template item as 'this' pointer. Just evaluate... 343 | expr = parens ? (target.indexOf(".") > -1 ? target + parens : ("(" + target + ").call($item" + args)) : target; 344 | exprAutoFnDetect = parens ? expr : "(typeof(" + target + ")==='function'?(" + target + ").call($item):(" + target + "))"; 345 | } else { 346 | exprAutoFnDetect = expr = def.$1 || "null"; 347 | } 348 | fnargs = unescape( fnargs ); 349 | return "');" + 350 | tag[ slash ? "close" : "open" ] 351 | .split( "$notnull_1" ).join( target ? "typeof(" + target + ")!=='undefined' && (" + target + ")!=null" : "true" ) 352 | .split( "$1a" ).join( exprAutoFnDetect ) 353 | .split( "$1" ).join( expr ) 354 | .split( "$2" ).join( fnargs ? 355 | fnargs.replace( /\s*([^\(]+)\s*(\((.*?)\))?/g, function( all, name, parens, params ) { 356 | params = params ? ("," + params + ")") : (parens ? ")" : ""); 357 | return params ? ("(" + name + ").call($item" + params) : all; 358 | }) 359 | : (def.$2||"") 360 | ) + 361 | "_.push('"; 362 | }) + 363 | "');}return _;" 364 | ); 365 | } 366 | function updateWrapped( options, wrapped ) { 367 | // Build the wrapped content. 368 | options._wrap = build( options, true, 369 | // Suport imperative scenario in which options.wrapped can be set to a selector or an HTML string. 370 | jQuery.isArray( wrapped ) ? wrapped : [htmlExpr.test( wrapped ) ? wrapped : jQuery( wrapped ).html()] 371 | ).join(""); 372 | } 373 | 374 | function unescape( args ) { 375 | return args ? args.replace( /\\'/g, "'").replace(/\\\\/g, "\\" ) : null; 376 | } 377 | function outerHtml( elem ) { 378 | var div = document.createElement("div"); 379 | div.appendChild( elem.cloneNode(true) ); 380 | return div.innerHTML; 381 | } 382 | 383 | // Store template items in jQuery.data(), ensuring a unique tmplItem data data structure for each rendered template instance. 384 | function storeTmplItems( content ) { 385 | var keySuffix = "_" + cloneIndex, elem, elems, newClonedItems = {}, i, l, m; 386 | for ( i = 0, l = content.length; i < l; i++ ) { 387 | if ( (elem = content[i]).nodeType !== 1 ) { 388 | continue; 389 | } 390 | elems = elem.getElementsByTagName("*"); 391 | for ( m = elems.length - 1; m >= 0; m-- ) { 392 | processItemKey( elems[m] ); 393 | } 394 | processItemKey( elem ); 395 | } 396 | function processItemKey( el ) { 397 | var pntKey, pntNode = el, pntItem, tmplItem, key; 398 | // Ensure that each rendered template inserted into the DOM has its own template item, 399 | if ( (key = el.getAttribute( tmplItmAtt ))) { 400 | while ((pntNode = pntNode.parentNode).nodeType === 1 && !(pntKey = pntNode.getAttribute( tmplItmAtt ))) { } 401 | if ( pntKey !== key ) { 402 | // The next ancestor with a _tmplitem expando is on a different key than this one. 403 | // So this is a top-level element within this template item 404 | pntNode = pntNode.nodeType === 11 ? 0 : (pntNode.getAttribute( tmplItmAtt ) || 0); 405 | if ( !(tmplItem = newTmplItems[key]) ) { 406 | // The item is for wrapped content, and was copied from the temporary parent wrappedItem. 407 | tmplItem = wrappedItems[key]; 408 | tmplItem = newTmplItem( tmplItem, newTmplItems[pntNode]||wrappedItems[pntNode], null, true ); 409 | tmplItem.key = ++itemKey; 410 | newTmplItems[itemKey] = tmplItem; 411 | } 412 | if ( cloneIndex ) { 413 | cloneTmplItem( key ); 414 | } 415 | } 416 | el.removeAttribute( tmplItmAtt ); 417 | } else if ( cloneIndex && (tmplItem = jQuery.data( el, "tmplItem" )) ) { 418 | // This was a rendered element, cloned during append or appendTo etc. 419 | // TmplItem stored in jQuery data has already been cloned in cloneCopyEvent. We must replace it with a fresh cloned tmplItem. 420 | cloneTmplItem( tmplItem.key ); 421 | newTmplItems[tmplItem.key] = tmplItem; 422 | pntNode = jQuery.data( el.parentNode, "tmplItem" ); 423 | pntNode = pntNode ? pntNode.key : 0; 424 | } 425 | if ( tmplItem ) { 426 | pntItem = tmplItem; 427 | // Find the template item of the parent element. 428 | // (Using !=, not !==, since pntItem.key is number, and pntNode may be a string) 429 | while ( pntItem && pntItem.key != pntNode ) { 430 | // Add this element as a top-level node for this rendered template item, as well as for any 431 | // ancestor items between this item and the item of its parent element 432 | pntItem.nodes.push( el ); 433 | pntItem = pntItem.parent; 434 | } 435 | // Delete content built during rendering - reduce API surface area and memory use, and avoid exposing of stale data after rendering... 436 | delete tmplItem._ctnt; 437 | delete tmplItem._wrap; 438 | // Store template item as jQuery data on the element 439 | jQuery.data( el, "tmplItem", tmplItem ); 440 | } 441 | function cloneTmplItem( key ) { 442 | key = key + keySuffix; 443 | tmplItem = newClonedItems[key] = 444 | (newClonedItems[key] || newTmplItem( tmplItem, newTmplItems[tmplItem.parent.key + keySuffix] || tmplItem.parent, null, true )); 445 | } 446 | } 447 | } 448 | 449 | //---- Helper functions for template item ---- 450 | 451 | function tiCalls( content, tmpl, data, options ) { 452 | if ( !content ) { 453 | return stack.pop(); 454 | } 455 | stack.push({ _: content, tmpl: tmpl, item:this, data: data, options: options }); 456 | } 457 | 458 | function tiNest( tmpl, data, options ) { 459 | // nested template, using {{tmpl}} tag 460 | return jQuery.tmpl( jQuery.template( tmpl ), data, options, this ); 461 | } 462 | 463 | function tiWrap( call, wrapped ) { 464 | // nested template, using {{wrap}} tag 465 | var options = call.options || {}; 466 | options.wrapped = wrapped; 467 | // Apply the template, which may incorporate wrapped content, 468 | return jQuery.tmpl( jQuery.template( call.tmpl ), call.data, options, call.item ); 469 | } 470 | 471 | function tiHtml( filter, textOnly ) { 472 | var wrapped = this._wrap; 473 | return jQuery.map( 474 | jQuery( jQuery.isArray( wrapped ) ? wrapped.join("") : wrapped ).filter( filter || "*" ), 475 | function(e) { 476 | return textOnly ? 477 | e.innerText || e.textContent : 478 | e.outerHTML || outerHtml(e); 479 | }); 480 | } 481 | 482 | function tiUpdate() { 483 | var coll = this.nodes; 484 | jQuery.tmpl( null, null, null, this).insertBefore( coll[0] ); 485 | jQuery( coll ).remove(); 486 | } 487 | 488 | })); 489 | -------------------------------------------------------------------------------- /demos/movies/resources/jqueryplugins/templates/jquery.tmplplus.js: -------------------------------------------------------------------------------- 1 | (function( jQuery ) { 2 | 3 | var oldComplete = jQuery.tmpl.complete, oldManip = jQuery.fn.domManip; 4 | 5 | // Override jQuery.tmpl.complete in order to provide rendered event. 6 | jQuery.tmpl.complete = function( tmplItems ) { 7 | var tmplItem; 8 | oldComplete( tmplItems); 9 | for ( tmplItem in tmplItems ) { 10 | tmplItem = tmplItems[tmplItem]; 11 | if ( tmplItem.addedTmplItems && jQuery.inArray( tmplItem, tmplItem.addedTmplItems ) === -1 ) { 12 | tmplItem.addedTmplItems.push( tmplItem ); 13 | } 14 | } 15 | for ( tmplItem in tmplItems ) { 16 | tmplItem = tmplItems[tmplItem]; 17 | // Raise rendered event 18 | if ( tmplItem.rendered ) { 19 | tmplItem.rendered( tmplItem ); 20 | } 21 | } 22 | }; 23 | 24 | jQuery.extend({ 25 | tmplCmd: function( command, data, tmplItems ) { 26 | var retTmplItems = [], before; 27 | function find( data, tmplItems ) { 28 | var found = [], tmplItem, ti, tl = tmplItems.length, dataItem, di = 0, dl = data.length; 29 | for ( ; di < dl; ) { 30 | dataItem = data[di++]; 31 | for ( ti = 0; ti < tl; ) { 32 | tmplItem = tmplItems[ti++]; 33 | if ( tmplItem.data === dataItem ) { 34 | found.push( tmplItem ); 35 | } 36 | } 37 | } 38 | return found; 39 | } 40 | 41 | data = jQuery.isArray( data ) ? data : [ data ]; 42 | switch ( command ) { 43 | case "find": 44 | return find( data, tmplItems ); 45 | case "replace": 46 | data.reverse(); 47 | } 48 | jQuery.each( tmplItems ? find( data, tmplItems ) : data, function( i, tmplItem ) { 49 | coll = tmplItem.nodes; 50 | switch ( command ) { 51 | case "update": 52 | tmplItem.update(); 53 | break; 54 | case "remove": 55 | jQuery( coll ).remove(); 56 | if ( tmplItems ) { 57 | tmplItems.splice( jQuery.inArray( tmplItem, tmplItems ), 1 ); 58 | } 59 | break; 60 | case "replace": 61 | before = before ? 62 | jQuery( coll ).insertBefore( before )[0] : 63 | jQuery( coll ).appendTo( coll[0].parentNode )[0]; 64 | retTmplItems.unshift( tmplItem ); 65 | } 66 | }); 67 | return retTmplItems; 68 | } 69 | }); 70 | 71 | jQuery.fn.extend({ 72 | domManip: function (args, table, callback, options) { 73 | var data = args[1], tmpl = args[0], dmArgs; 74 | if ( args.length >= 2 && typeof data === "object" && !data.nodeType && !(data instanceof jQuery)) { 75 | // args[1] is data, for a template. 76 | dmArgs = jQuery.makeArray( arguments ); 77 | 78 | // Eval template to obtain fragment to clone and insert 79 | dmArgs[0] = [ jQuery.tmpl( jQuery.template( tmpl ), data, args[2], args[3] ) ]; 80 | 81 | dmArgs[2] = function( fragClone ) { 82 | // Handler called by oldManip when rendered template has been inserted into DOM. 83 | jQuery.tmpl.afterManip( this, fragClone, callback ); 84 | }; 85 | return oldManip.apply( this, dmArgs ); 86 | } 87 | return oldManip.apply( this, arguments ); 88 | } 89 | }); 90 | 91 | })(jQuery); 92 | -------------------------------------------------------------------------------- /demos/movies/resources/jqueryui/jqueryuidefs.js: -------------------------------------------------------------------------------- 1 | $.deferDef({ 2 | pager: "pager/jquery.pager.js", 3 | datePicker: { 4 | bare: true, 5 | minUrl: "datePicker/datePicker.min.js", 6 | url: "datePicker/datePicker.js" 7 | } 8 | }); 9 | -------------------------------------------------------------------------------- /demos/movies/resources/jqueryui/pager/jquery.pager.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery pager plugin 3 | * Version 1.0 (12/22/2008) 4 | * @requires jQuery v1.2.6 or later 5 | * 6 | * Example at: http://jonpauldavies.github.com/JQuery/Pager/PagerDemo.html 7 | * 8 | * Copyright (c) 2008-2009 Jon Paul Davies 9 | * Dual licensed under the MIT and GPL licenses: 10 | * http://www.opensource.org/licenses/mit-license.php 11 | * http://www.gnu.org/licenses/gpl.html 12 | * 13 | * Read the related blog post and contact the author at http://www.j-dee.com/2008/12/22/jquery-pager-plugin/ 14 | * 15 | * This version is far from perfect and doesn't manage it's own state, therefore contributions are more than welcome! 16 | * 17 | * Usage: .pager({ pagenumber: 1, pagecount: 15, buttonClickCallback: PagerClickTest }); 18 | * 19 | * Where pagenumber is the visible page number 20 | * pagecount is the total number of pages to display 21 | * buttonClickCallback is the method to fire when a pager button is clicked. 22 | * 23 | * buttonClickCallback signiture is PagerClickTest = function(pageclickednumber) 24 | * Where pageclickednumber is the number of the page clicked in the control. 25 | * 26 | * The included Pager.CSS file is a dependancy but can obviously tweaked to your wishes 27 | * Tested in IE6 IE7 Firefox & Safari. Any browser strangeness, please report. 28 | */ 29 | ((window.$deferRun || function( run ){ run(); }) ( function( $, options ) { 30 | 31 | $.fn.pager = function(options) { 32 | 33 | var opts = $.extend({}, $.fn.pager.defaults, options); 34 | 35 | return this.each(function() { 36 | 37 | // empty out the destination element and then render out the pager with the supplied options 38 | $(this).empty().append(renderpager(parseInt(options.pagenumber), parseInt(options.pagecount), options.buttonClickCallback)); 39 | 40 | // specify correct cursor activity 41 | $('.pages li').mouseover(function() { document.body.style.cursor = "pointer"; }).mouseout(function() { document.body.style.cursor = "auto"; }); 42 | }); 43 | }; 44 | 45 | // render and return the pager with the supplied options 46 | function renderpager(pagenumber, pagecount, buttonClickCallback) { 47 | 48 | // setup $pager to hold render 49 | var $pager = $(''); 50 | 51 | // add in the previous and next buttons 52 | $pager.append(renderButton('first', pagenumber, pagecount, buttonClickCallback)).append(renderButton('prev', pagenumber, pagecount, buttonClickCallback)); 53 | 54 | // pager currently only handles 10 viewable pages ( could be easily parameterized, maybe in next version ) so handle edge cases 55 | var startPoint = 1; 56 | var endPoint = 9; 57 | 58 | if (pagenumber > 4) { 59 | startPoint = pagenumber - 4; 60 | endPoint = pagenumber + 4; 61 | } 62 | 63 | if (endPoint > pagecount) { 64 | startPoint = pagecount - 8; 65 | endPoint = pagecount; 66 | } 67 | 68 | if (startPoint < 1) { 69 | startPoint = 1; 70 | } 71 | 72 | // loop thru visible pages and render buttons 73 | for (var page = startPoint; page <= endPoint; page++) { 74 | 75 | var currentButton = $('
  • ' + (page) + '
  • '); 76 | 77 | page == pagenumber ? currentButton.addClass('pgCurrent') : currentButton.click(function() { buttonClickCallback(this.firstChild.data); }); 78 | currentButton.appendTo($pager); 79 | } 80 | 81 | // render in the next and last buttons before returning the whole rendered control back. 82 | $pager.append(renderButton('next', pagenumber, pagecount, buttonClickCallback)).append(renderButton('last', pagenumber, pagecount, buttonClickCallback)); 83 | 84 | return $pager; 85 | } 86 | 87 | // renders and returns a 'specialized' button, ie 'next', 'previous' etc. rather than a page number button 88 | function renderButton(buttonLabel, pagenumber, pagecount, buttonClickCallback) { 89 | 90 | var $Button = $('
  • ' + buttonLabel + '
  • '); 91 | 92 | var destPage = 1; 93 | 94 | // work out destination page for required button type 95 | switch (buttonLabel) { 96 | case "first": 97 | destPage = 1; 98 | break; 99 | case "prev": 100 | destPage = pagenumber - 1; 101 | break; 102 | case "next": 103 | destPage = pagenumber + 1; 104 | break; 105 | case "last": 106 | destPage = pagecount; 107 | break; 108 | } 109 | 110 | // disable and 'grey' out buttons if not needed. 111 | if (buttonLabel == "first" || buttonLabel == "prev") { 112 | pagenumber <= 1 ? $Button.addClass('pgEmpty') : $Button.click(function() { buttonClickCallback(destPage); }); 113 | } 114 | else { 115 | pagenumber >= pagecount ? $Button.addClass('pgEmpty') : $Button.click(function() { buttonClickCallback(destPage); }); 116 | } 117 | 118 | return $Button; 119 | } 120 | 121 | // pager defaults. hardly worth bothering with in this case but used as placeholder for expansion in the next version 122 | $.fn.pager.defaults = { 123 | pagenumber: 1, 124 | pagecount: 1 125 | }; 126 | 127 | })); -------------------------------------------------------------------------------- /demos/movies/resources/movieapp.js: -------------------------------------------------------------------------------- 1 | // This version of the Movies App creates a 'movies' object, to which it adds the passed in movieSettings. 2 | // It returns the app object. 3 | 4 | ((window.$deferRun || function( run ){ run(); }) ( function( $, app ) { 5 | 6 | var pageIndex = app.pageIndex || 1, pageSize = app.pageSize || 3, pageCount = 0, bookingTmplItems = [], selectedBooking; 7 | 8 | return $.extend( app, { 9 | currentGenre: null, 10 | cartTmplItem: null, 11 | cart: { bookings: {}, count: 0, sortBy:0 }, 12 | init: function( data, genre, pageSizeInit ) { 13 | app.currentGenre = genre; 14 | pageSize = app.pageSize = pageSizeInit; 15 | $( "#genres li" ).click( movieApp.selectGenre ); 16 | 17 | $( ".cart" ) 18 | .delegate( "select", "change", app.sort ) 19 | .delegate( "#sortBtn", "click", app.sort ) 20 | .delegate( "#submit", "click", function() { 21 | alert( app.cart.count + " bookings submitted for payment..."); 22 | movieApp.removeBookings(); 23 | }) 24 | .delegate( "#cancel", "click", function() { 25 | app.removeBookings(); 26 | }) 27 | .empty() 28 | .append( "#cartTmpl", app.cart ); 29 | 30 | app.cartTmplItem = $( ".cart td" ).tmplItem(); 31 | app.showMovies( data ); 32 | }, 33 | selectGenre: function() { 34 | $( "#genres li" ).removeClass( "selected" ); 35 | $( this ).addClass( "selected" ); 36 | 37 | pageIndex = 1; 38 | app.currentGenre = encodeURI( $(this).text() ); 39 | getMoviesData( app.currentGenre, pageSize, pageIndex ).done( app.showMovies ); 40 | }, 41 | sort: function() { 42 | var compare = compareName, reverse = false, data = []; 43 | app.cart.sortBy = $( "#sort select" ).val(); 44 | switch ( $( "#sort select" ).val() ) { 45 | case "1": 46 | reverse = true; 47 | break; 48 | case "2": 49 | compare = compareDate; 50 | break; 51 | } 52 | 53 | for ( var item in app.cart.bookings ) { 54 | data.push( app.cart.bookings[item] ); 55 | } 56 | data = data.sort( compare ); 57 | 58 | bookingTmplItems = $.tmplCmd( "replace", data, bookingTmplItems ); 59 | 60 | function compareName( a, b ) { 61 | return a == b ? 0 : (((a.movie.Name > b.movie.Name) !== reverse) ? 1 : -1); 62 | } 63 | function compareDate( a, b ) { 64 | return a.date - b.date; 65 | } 66 | }, 67 | showMovies: function( data ) { 68 | pageCount = Math.ceil( data.d.__count/pageSize ), 69 | movies = data.d.results; 70 | 71 | $( "#pager" ).pager({ pagenumber: pageIndex, pagecount: pageCount, buttonClickCallback: app.getMoreMovies }); 72 | 73 | $( "#movieList" ) 74 | .empty() 75 | 76 | // Render movies using the movieTemplate, and display rendered movies in the movieList container 77 | .append( "#movieTmpl", movies, { rendered: app.onMovieRendered } ) 78 | 79 | .fadeIn( "medium" ); 80 | }, 81 | getMoreMovies: function( index ) { 82 | pageIndex = index; 83 | getMoviesData( app.currentGenre, pageSize, pageIndex ).done( app.showMovies ); 84 | }, 85 | buyTickets: function( movie ) { 86 | // Add item to cart 87 | var booking = app.cart.bookings[movie.Id]; 88 | if ( booking ) { 89 | booking.quantity++; 90 | } else { 91 | app.cart.count++; 92 | app.cartTmplItem.update(); 93 | booking = { movie: movie, date: new Date(), quantity: 1, movieTheater: "" }; 94 | } 95 | app.selectBooking( booking ); 96 | }, 97 | selectBooking: function( booking ) { 98 | if ( selectedBooking ) { 99 | if ( selectedBooking === booking ) { 100 | app.updateBooking( app.bookingItem( selectedBooking )); 101 | return; 102 | } 103 | // Collapse previously selected booking, and switch to non-edit view 104 | var oldSelected = selectedBooking; 105 | $( "div", app.bookingItem( oldSelected ).nodes ).animate( { height: 0 }, 500, function() { 106 | app.switchView( oldSelected ); 107 | }); 108 | } 109 | selectedBooking = booking; 110 | if ( !booking ) { 111 | return; 112 | } 113 | if ( app.cart.bookings[booking.movie.Id] ) { 114 | app.switchView( booking, true ); 115 | } else { 116 | app.cart.bookings[booking.movie.Id] = booking; 117 | 118 | // Render the booking for the chosen movie using the bookingEditTemplate, and append the rendered booking to the bookings list 119 | $( "#bookingsList" ).append( "#bookingEditTmpl", booking, { 120 | animate: true, 121 | rendered: app.onBookingEditRendered, 122 | addedTmplItems: bookingTmplItems 123 | }); 124 | } 125 | }, 126 | switchView: function( booking, edit ) { 127 | if ( !booking ) { 128 | return; 129 | } 130 | var item = app.bookingItem( booking ), 131 | rendered = edit ? app.onBookingEditRendered : app.onBookingRendered; 132 | if ( item.rendered !== rendered) { 133 | item.tmpl = $( edit ? "#bookingEditTmpl" : "#bookingTitleTmpl" ).template(); 134 | item.rendered = rendered; 135 | item.update(); 136 | } 137 | }, 138 | onMovieRendered: function( item ) { 139 | $( "div", item.nodes ).fadeIn( 4000 ); 140 | $( ".buyButton", item.nodes ).click( function() { 141 | app.buyTickets( item.data ); 142 | }); 143 | }, 144 | onBookingRendered: function( item ) { 145 | $( item.nodes ).click( function() { 146 | app.selectBooking( item.data ); 147 | }); 148 | $( ".close", item.nodes ).click( app.removeBooking ); 149 | }, 150 | onBookingEditRendered: function( item ) { 151 | var data = item.data, nodes = item.nodes; 152 | 153 | $( nodes[0] ).click( function() { 154 | app.selectBooking(); 155 | }); 156 | 157 | $( ".close", nodes ).click( app.removeBooking ); 158 | 159 | $( ".date", nodes ).change( function() { 160 | data.date = $(this).datepicker( "getDate" ); 161 | app.updateBooking( item ); 162 | }) 163 | .datepicker({ dateFormat: "DD, d MM, yy" }); 164 | 165 | $( ".quantity", nodes ).change( function() { 166 | data.quantity = $(this).val(); 167 | app.updateBooking( item ); 168 | }); 169 | 170 | $( ".theater", nodes ).change( function() { 171 | data.movieTheater = $(this).val(); 172 | app.updateBooking( item ); 173 | }); 174 | 175 | if ( item.animate ) { 176 | $( "div", nodes ).css( "height", 0 ).animate( { height: 116 }, 500 ); 177 | } 178 | }, 179 | updateBooking: function( item ) { 180 | item.animate = false; 181 | item.update(); 182 | item.animate = true; 183 | }, 184 | removeBooking: function() { 185 | var booking = $.tmplItem(this).data; 186 | if ( booking === selectedBooking ) { 187 | selectedBooking = null; 188 | } 189 | delete app.cart.bookings[booking.movie.Id]; 190 | app.cart.count--; 191 | app.cartTmplItem.update(); 192 | $.tmplCmd( "remove", booking, bookingTmplItems ); 193 | return false; 194 | }, 195 | removeBookings: function() { 196 | $.tmplCmd( "remove", bookingTmplItems ); 197 | bookingTmplItems = []; 198 | app.cart.count = 0; 199 | app.cart.bookings = {}; 200 | selectedBooking = null; 201 | app.cartTmplItem.update(); 202 | }, 203 | formatDate: function( date ) { 204 | return date.toLocaleDateString(); 205 | }, 206 | bookingItem: function( booking ) { 207 | return $.tmplCmd( "find", booking, bookingTmplItems)[0]; 208 | } 209 | }); 210 | 211 | })); -------------------------------------------------------------------------------- /demos/movies/resources/movieappdefs.js: -------------------------------------------------------------------------------- 1 | $.deferDef({ 2 | jQuery: { 3 | bare: true, 4 | url: "http://code.jquery.com/jquery.js", 5 | loaded: "window.jQuery" 6 | }, 7 | tmpl: { 8 | url: "jQueryPlugins/templates/jquery.tmpl.js", 9 | depends: "jQuery" 10 | }, 11 | tmplplus: { 12 | bare: true, 13 | url: "jQueryPlugins/templates/jquery.tmplplus.js", 14 | depends: "tmpl" 15 | }, 16 | moviePlugin: { 17 | url: "moviePlugin.js", 18 | depends: "tmplplus" 19 | }, 20 | movieApp: { 21 | url: "movieApp.js", 22 | depends: "tmplplus" 23 | } 24 | }); 25 | -------------------------------------------------------------------------------- /demos/movies/resources/movieplugin.js: -------------------------------------------------------------------------------- 1 | // This version of the Movies App creates a 'movies' jQuery plugin 2 | 3 | ((window.$deferRun || function( run ){ run(); }) ( function( $, options ) { 4 | 5 | $.movies = function( app ) { 6 | var genre="Cartoons", pageIndex = app.pageIndex || 1, pageSize = app.pageSize || 3, pageCount = 0, bookingTmplItems = [], selectedBooking; 7 | 8 | $.extend( app, { 9 | cartTmplItem: null, 10 | cart: { bookings: {}, count: 0, sortBy:0 }, 11 | init: function() { 12 | $( "#genres li" ).click( movieApp.selectGenre ); 13 | 14 | $( ".cart" ) 15 | .delegate( "select", "change", app.sort ) 16 | .delegate( "#sortBtn", "click", app.sort ) 17 | .delegate( "#submit", "click", function() { 18 | alert( app.cart.count + " bookings submitted for payment..."); 19 | movieApp.removeBookings(); 20 | }) 21 | .delegate( "#cancel", "click", function() { 22 | app.removeBookings(); 23 | }) 24 | .empty() 25 | .append( "#cartTmpl", app.cart ); 26 | 27 | app.cartTmplItem = $( ".cart td" ).tmplItem(); 28 | app.getMovies().done( app.showMovies ); 29 | }, 30 | selectGenre: function() { 31 | $( "#genres li" ).removeClass( "selected" ); 32 | $( this ).addClass( "selected" ); 33 | 34 | pageIndex = 1; 35 | genre = encodeURI( $(this).text() ); 36 | app.getMovies( pageIndex ).done( app.showMovies ); 37 | }, 38 | sort: function() { 39 | var compare = compareName, reverse = false, data = []; 40 | app.cart.sortBy = $( "#sort select" ).val(); 41 | switch ( $( "#sort select" ).val() ) { 42 | case "1": 43 | reverse = true; 44 | break; 45 | case "2": 46 | compare = compareDate; 47 | break; 48 | } 49 | 50 | for ( var item in app.cart.bookings ) { 51 | data.push( app.cart.bookings[item] ); 52 | } 53 | data = data.sort( compare ); 54 | 55 | bookingTmplItems = $.tmplCmd( "replace", data, bookingTmplItems ); 56 | 57 | function compareName( a, b ) { 58 | return a == b ? 0 : (((a.movie.Name > b.movie.Name) !== reverse) ? 1 : -1); 59 | } 60 | function compareDate( a, b ) { 61 | return a.date - b.date; 62 | } 63 | }, 64 | getMovies: function( index ) { 65 | index = index || 1; 66 | var query = "http://odata.netflix.com/Catalog/Genres('" + genre + "')/Titles" + 67 | "?$format=json" + 68 | "&$inlinecount=allpages" + // get total number of records 69 | "&$skip=" + (index-1) * pageSize + // skip to first record of page 70 | "&$top=" + pageSize; // page size 71 | 72 | pageIndex = index; 73 | 74 | return $.ajax({ 75 | dataType: "jsonp", 76 | url: query, 77 | jsonp: "$callback" 78 | }); 79 | }, 80 | showMovies: function( data ) { 81 | pageCount = Math.ceil( data.d.__count/pageSize ), 82 | movies = data.d.results; 83 | 84 | $( "#pager" ).pager({ pagenumber: pageIndex, pagecount: pageCount, buttonClickCallback: app.getMoreMovies }); 85 | 86 | $( "#movieList" ) 87 | .empty() 88 | 89 | // Render movies using the movieTemplate, and display rendered movies in the movieList container 90 | .append( "#movieTmpl", movies, { rendered: app.onMovieRendered } ); 91 | }, 92 | getMoreMovies: function( index ) { 93 | app.getMovies( index ).done( app.showMovies ); 94 | }, 95 | buyTickets: function( movie ) { 96 | // Add item to cart 97 | var booking = app.cart.bookings[movie.Id]; 98 | if ( booking ) { 99 | booking.quantity++; 100 | } else { 101 | app.cart.count++; 102 | app.cartTmplItem.update(); 103 | booking = { movie: movie, date: new Date(), quantity: 1, movieTheater: "" }; 104 | } 105 | app.selectBooking( booking ); 106 | }, 107 | selectBooking: function( booking ) { 108 | if ( selectedBooking ) { 109 | if ( selectedBooking === booking ) { 110 | app.updateBooking( app.bookingItem( selectedBooking )); 111 | return; 112 | } 113 | // Collapse previously selected booking, and switch to non-edit view 114 | var oldSelected = selectedBooking; 115 | $( "div", app.bookingItem( oldSelected ).nodes ).animate( { height: 0 }, 500, function() { 116 | app.switchView( oldSelected ); 117 | }); 118 | } 119 | selectedBooking = booking; 120 | if ( !booking ) { 121 | return; 122 | } 123 | if ( app.cart.bookings[booking.movie.Id] ) { 124 | app.switchView( booking, true ); 125 | } else { 126 | app.cart.bookings[booking.movie.Id] = booking; 127 | 128 | // Render the booking for the chosen movie using the bookingEditTemplate, and append the rendered booking to the bookings list 129 | $( "#bookingsList" ).append( "#bookingEditTmpl", booking, { 130 | animate: true, 131 | rendered: app.onBookingEditRendered, 132 | addedTmplItems: bookingTmplItems 133 | }); 134 | } 135 | }, 136 | switchView: function( booking, edit ) { 137 | if ( !booking ) { 138 | return; 139 | } 140 | var item = app.bookingItem( booking ), 141 | rendered = edit ? app.onBookingEditRendered : app.onBookingRendered; 142 | if ( item.rendered !== rendered) { 143 | item.tmpl = $( edit ? "#bookingEditTmpl" : "#bookingTitleTmpl" ).template(); 144 | item.rendered = rendered; 145 | item.update(); 146 | } 147 | }, 148 | onMovieRendered: function( item ) { 149 | $( ".buyButton", item.nodes ).click( function() { 150 | app.buyTickets( item.data ); 151 | }); 152 | }, 153 | onBookingRendered: function( item ) { 154 | $( item.nodes ).click( function() { 155 | app.selectBooking( item.data ); 156 | }); 157 | $( ".close", item.nodes ).click( app.removeBooking ); 158 | }, 159 | onBookingEditRendered: function( item ) { 160 | var data = item.data, nodes = item.nodes; 161 | 162 | $( nodes[0] ).click( function() { 163 | app.selectBooking(); 164 | }); 165 | 166 | $( ".close", nodes ).click( app.removeBooking ); 167 | 168 | $( ".date", nodes ).change( function() { 169 | data.date = $(this).datepicker( "getDate" ); 170 | app.updateBooking( item ); 171 | }) 172 | .datepicker({ dateFormat: "DD, d MM, yy" }); 173 | 174 | $( ".quantity", nodes ).change( function() { 175 | data.quantity = $(this).val(); 176 | app.updateBooking( item ); 177 | }); 178 | 179 | $( ".theater", nodes ).change( function() { 180 | data.movieTheater = $(this).val(); 181 | app.updateBooking( item ); 182 | }); 183 | 184 | if ( item.animate ) { 185 | $( "div", nodes ).css( "height", 0 ).animate( { height: 116 }, 500 ); 186 | } 187 | }, 188 | updateBooking: function( item ) { 189 | item.animate = false; 190 | item.update(); 191 | item.animate = true; 192 | }, 193 | removeBooking: function() { 194 | var booking = $.tmplItem(this).data; 195 | if ( booking === selectedBooking ) { 196 | selectedBooking = null; 197 | } 198 | delete app.cart.bookings[booking.movie.Id]; 199 | app.cart.count--; 200 | app.cartTmplItem.update(); 201 | $.tmplCmd( "remove", booking, bookingTmplItems ); 202 | return false; 203 | }, 204 | removeBookings: function() { 205 | $.tmplCmd( "remove", bookingTmplItems ); 206 | bookingTmplItems = []; 207 | app.cart.count = 0; 208 | app.cart.bookings = {}; 209 | selectedBooking = null; 210 | app.cartTmplItem.update(); 211 | }, 212 | formatDate: function( date ) { 213 | return date.toLocaleDateString(); 214 | }, 215 | bookingItem: function( booking ) { 216 | return $.tmplCmd( "find", booking, bookingTmplItems)[0]; 217 | }}); 218 | 219 | app.init(); 220 | }; 221 | 222 | 223 | })); -------------------------------------------------------------------------------- /jquery.defer.js: -------------------------------------------------------------------------------- 1 | /*! JsDefer v1.0.0-alpha: http://github.com/BorisMoore/jsdefer and http://jsviews.com/jsviews */ 2 | /* 3 | * Script loader, using the 'Deferred' pattern for async operations 4 | * Two versions: 5 | * - jquery.defer.js (this file): the jQuery plugin version of JsDefer 6 | * - jsdefer.js: the jQuery-independent version of JsDefer 7 | * Copyright 2013, Boris Moore 8 | * Released under the MIT License. 9 | */ 10 | 11 | // This is jquery.defer.js: the jQuery plugin version of JsDefer 12 | 13 | jQuery.defer || (function( $, window, undefined ) { 14 | 15 | var document = window.document, 16 | anchor = document.createElement("a"), 17 | deferSettings, defer, ready, readyDefer, 18 | scriptByUrl = {}, 19 | loadingScripts = [], 20 | loadingSubScripts; 21 | 22 | function absUrl( basePath, url ) { 23 | if ( url.indexOf( "//" ) === -1 ) { 24 | url = basePath + url; 25 | } 26 | return anchor.href = url; 27 | // For IE without DOCTYPE - need use recursive regex along lines: parts = url.split( "/../" ); parts[0] = parts[0].slice( 0, parts[0].lastIndexOf("/") + 1 ); Use recursive regex; return parts.join("").toLowerCase(); 28 | } 29 | 30 | function getBasePath( url ) { 31 | return url.slice( 0, url.lastIndexOf("/") + 1 ); 32 | } 33 | 34 | function makeArray( items ) { 35 | return typeof items === "string" ? [ items ] : items; 36 | } 37 | 38 | function normalize( items, basePath ) { 39 | if ( !items ) { 40 | return 0; 41 | } 42 | items = makeArray( items ); 43 | var name, i = items.length; 44 | while ( i-- ) { 45 | name = items[ i ]; 46 | if ( !defer[ name ] ) { 47 | items[ i ] = absUrl( basePath, name ); 48 | } 49 | } 50 | return items; 51 | } 52 | 53 | function getScriptDef( name, thisUrl ) { 54 | var thisUrlKey, 55 | scriptDef = defer[ name ]; 56 | 57 | if ( scriptDef ) { 58 | return scriptDef; 59 | } 60 | 61 | thisUrl = absUrl( getBasePath( thisUrl || "" ), name ); 62 | thisUrlKey = thisUrl.toLowerCase(); 63 | return scriptByUrl[ thisUrlKey ] || (scriptByUrl[ thisUrlKey ] = { url: thisUrl }); 64 | } 65 | 66 | $.extend({ 67 | defer: function( scriptName, options, basePath ) { 68 | options = options || {}; 69 | 70 | var i, readyName, asyncLoad, result, prevPromise, 71 | runWait = 0, 72 | delayDomReady = options.delayDomReady || deferSettings.delayDomReady, 73 | min = options.min || deferSettings.min, 74 | scriptDef = getScriptDef( scriptName, basePath ), 75 | url = scriptDef.url, 76 | loadUrl = ( min && scriptDef.minUrl ) || scriptDef.url, 77 | 78 | settings = $.extend( scriptDef, options ), 79 | bare = settings.bare, 80 | contains = settings.contains, 81 | loaded = settings.loaded, 82 | depends = settings.depends, 83 | multiple = settings.multiple, 84 | 85 | parentPromise = scriptDef.prntPrms, 86 | promise = scriptDef.promise, 87 | runCb, thisPromise, hasRun, hasRunPromise; 88 | 89 | function run() { 90 | var i, thisRunCb = runCb || scriptDef.runCb; // For multiple or composite scripts, callback was passed via scriptDef 91 | 92 | if ( !(runWait--) ) { 93 | if ( asyncLoad.state() !== "rejected" ) { 94 | if ( parentPromise ) { 95 | asyncLoad.resolve( 96 | result || 97 | (scriptDef.result = result = thisRunCb.call( promise, $, options )) 98 | ); 99 | } else if ( contains ) { 100 | loadingSubScripts = []; 101 | 102 | thisRunCb.call( promise, $, options ); 103 | 104 | i = contains.length; 105 | 106 | // The following lines could be in debug build only... 107 | //if ( loadingSubScripts.length !== i ) { 108 | // throw url; //script definition error - number of contained scripts not equal to contains array length. 109 | //} 110 | while ( i-- ) { 111 | getScriptDef( contains[ i ], url ).runCb = loadingSubScripts[ i ].run; 112 | } 113 | loadingSubScripts = 0; 114 | 115 | hasRun.resolve(); 116 | 117 | loadDependencies( contains, [], function() { 118 | i = contains.length; 119 | result = []; 120 | while ( i-- ) { 121 | result.push( getScriptDef( contains[ i ], url ).result ); 122 | } 123 | asyncLoad.resolve( result ); 124 | }); 125 | } else { 126 | asyncLoad.resolve( 127 | result || 128 | (scriptDef.result = result = bare ? "bare" : thisRunCb.call( promise, $, options )) 129 | ); 130 | } 131 | result = multiple ? 0 : result; 132 | } 133 | if ( delayDomReady ) { 134 | ready( true ); 135 | } 136 | } 137 | } 138 | 139 | function reject() { 140 | asyncLoad.reject( "fail", url ); 141 | } 142 | 143 | function loadDependencies( newDepends, promises, cb ) { 144 | promises = promises || []; 145 | var i = newDepends && newDepends.length; 146 | while ( i-- ) { 147 | promises.push( defer( newDepends[ i ], options, url )); 148 | } 149 | $.when.apply( $, promises ).fail( reject ).done( cb || run ); 150 | } 151 | 152 | function getScript() { 153 | return $.ajax({ 154 | url: loadUrl, 155 | dataType: "script", 156 | timeout: settings.timeout, 157 | cache: !settings.noCache, 158 | crossDomain: true // Force regular script insertion, rather than XMLHTTP plus script insertion in document, for easier debugging. 159 | }) 160 | 161 | .fail( reject ) 162 | 163 | // readyStateChange complete has happened 164 | .done( function() { 165 | 166 | var deferRunSettings = bare ? 0 : loadingScripts.shift(); 167 | 168 | if ( !deferRunSettings ) { 169 | if ( !bare ) { 170 | // 404 or similar - no script got loaded for this url. 171 | // This only works for IE. For Chrome and FF, neither done nor fail cb of $.ajax get called for 404. 172 | // Set timeout to get error for all browsers. 173 | reject(); 174 | } 175 | // Non-wrapped script 176 | run(); 177 | return; 178 | } 179 | 180 | runCb = scriptDef.runCb = deferRunSettings.run; 181 | 182 | if ( deferRunSettings.def ) { 183 | $.deferDef( deferRunSettings.def, url ); 184 | } 185 | 186 | depends = makeArray( deferRunSettings.depends ) || []; 187 | prepareSubDefs( !contains && deferRunSettings.contains ) 188 | 189 | if ( depends.length ) { 190 | runWait++; 191 | loadDependencies( depends ); 192 | } 193 | }); 194 | } 195 | 196 | function prepareSubDefs( containNames ) { 197 | if ( containNames ) { 198 | hasRun = $.Deferred(); 199 | hasRunPromise = [ hasRun.promise() ]; 200 | contains = makeArray( containNames ); 201 | i = contains.length; 202 | while ( i-- ) { 203 | getScriptDef( contains[ i ], url ).prntPrms = hasRunPromise; 204 | } 205 | } 206 | } 207 | 208 | if ( multiple || !promise ) { 209 | asyncLoad = $.Deferred(); 210 | 211 | if ( loaded && eval( loaded ) ) { 212 | return asyncLoad.resolve().promise(); 213 | } 214 | 215 | if ( delayDomReady ) { 216 | $.readyWait++; 217 | } 218 | 219 | prevPromise = promise; 220 | asyncLoad = $.Deferred(); 221 | promise = scriptDef.promise = asyncLoad.promise(); 222 | 223 | if ( bare ) { 224 | loadDependencies( depends, 0, getScript ); 225 | } else if ( prevPromise ) { 226 | // This is a subsequent call, with multiple = true; 227 | loadDependencies( 0, [ prevPromise ]); 228 | } else if ( parentPromise ) { 229 | loadDependencies( depends, parentPromise ); 230 | } else { 231 | prepareSubDefs( contains ); 232 | 233 | loadDependencies( depends, [ getScript().promise() ] ); 234 | } 235 | } 236 | if ( readyName = options.readyName || scriptDef.name ) { 237 | ready[ readyName ] = promise; 238 | } 239 | return promise; 240 | }, 241 | 242 | deferDef: function( scriptDefs, thisUrl ) { 243 | var scriptName, basePath, scriptDef, 244 | scriptEl = document.getElementsByTagName( "script" ); 245 | 246 | function defineScript( name, newScriptDef ) { 247 | // Autogenerate methods on defer for registered scripts. 248 | if ( typeof newScriptDef === "string" ) { 249 | newScriptDef = { url: newScriptDef }; 250 | } 251 | 252 | var minUrl = newScriptDef.minUrl, 253 | url = absUrl( basePath, newScriptDef.url ), 254 | 255 | // May be some issues in Chrome. Investigate: 256 | // scriptDef = scriptByUrl[ url ]; 257 | // // Autogenerate methods on defer for registered scripts. 258 | // if ( !scriptDef ) { 259 | // scriptDef = function() { 260 | // var args = array.prototype.slice.call( arguments, 0 ); 261 | // args.unshift( name ); 262 | // return defer.apply( $, args ); 263 | // } 264 | // } 265 | 266 | // Autogenerate methods on defer for registered scripts. 267 | scriptDef = scriptByUrl[ url ] || function() { 268 | var args = Array.prototype.slice.call( arguments, 0 ); 269 | args.unshift( name ); 270 | return defer.apply( $, args ); 271 | }; 272 | 273 | newScriptDef.url = url; 274 | if ( minUrl ) { 275 | newScriptDef.minUrl = absUrl( basePath, minUrl ); 276 | } 277 | 278 | $.extend( scriptDef, newScriptDef ); 279 | 280 | scriptByUrl[ url ] = defer[ name ] = scriptDef; 281 | scriptDef.name = name; 282 | } 283 | 284 | // This if fine for static scripts and inline script, but will not find the correct script element, in the case of dynamically loaded scripts. 285 | // So we require define to be loaded statically or in the page. 286 | // But can pass a definition to run, in dynamically loaded pages - and use thisUrl. 287 | 288 | scriptEl = scriptEl[ scriptEl.length-1 ]; 289 | basePath = getBasePath( thisUrl || scriptEl.src ); 290 | 291 | if ( typeof scriptDefs === "string" ) { 292 | // Calling $.deferDef( nameOrAbsoluteUrlOrRelativeUrl) will return the scriptDef object 293 | return defer[scriptDefs ] || scriptByUrl[ absUrl( basePath, scriptDefs )]; 294 | } 295 | 296 | for ( scriptName in scriptDefs ) { 297 | defineScript( scriptName, scriptDefs[ scriptName ] ); 298 | } 299 | for ( scriptName in scriptDefs ) { 300 | scriptDef = getScriptDef( scriptName ); 301 | scriptDef.depends = normalize( scriptDef.depends, basePath ); 302 | scriptDef.contains = normalize( scriptDef.contains, basePath ); 303 | } 304 | }, 305 | 306 | deferSettings: { 307 | delayDomReady: false, 308 | min: true 309 | } 310 | }); 311 | 312 | window.$deferRun = function( run, settings ) { 313 | settings = makeArray( settings ); 314 | settings = settings && settings.length ? { depends: settings } : settings || {}; 315 | settings.run = run; 316 | 317 | ( loadingSubScripts || loadingScripts ).push( settings ); 318 | }; 319 | 320 | deferSettings = $.deferSettings; 321 | defer = $.defer; 322 | ready = $.ready; 323 | 324 | })( jQuery, window ); 325 | 326 | 327 | // TODO Add CSS loader support 328 | // 329 | //function loadStyles( src ) { 330 | // var styles = document.createElement("link"); 331 | // styles.href = src.indexOf("http") === 0 ? src : basePath + src; 332 | // styles.rel = "stylesheet"; 333 | // styles.type = "text/css"; 334 | // head.appendChild( styles ); 335 | //} 336 | -------------------------------------------------------------------------------- /jquery.defer.min.js: -------------------------------------------------------------------------------- 1 | /*! JsDefer v1.0.0-alpha: http://github.com/BorisMoore/jsdefer and http://jsviews.com/jsviews */ 2 | jQuery.defer||function(n,t){function u(n,t){return t.indexOf("//")===-1&&(t=n+t),y.href=t}function a(n){return n.slice(0,n.lastIndexOf("/")+1)}function o(n){return typeof n=="string"?[n]:n}function v(n,t){if(!n)return 0;n=o(n);for(var r,f=n.length;f--;)r=n[f],i[r]||(n[f]=u(t,r));return n}function f(n,t){var f,e=i[n];return e?e:(t=u(a(t||""),n),f=t.toLowerCase(),r[f]||(r[f]={url:t}))}var c=t.document,y=c.createElement("a"),s,i,h,r={},l=[],e;n.extend({defer:function(scriptName,options,basePath){function run(){var t,i=runCb||scriptDef.runCb;if(!runWait--){if(asyncLoad.state()!=="rejected"){if(parentPromise)asyncLoad.resolve(result||(scriptDef.result=result=i.call(promise,n,options)));else if(contains){for(e=[],i.call(promise,n,options),t=contains.length;t--;)f(contains[t],url).runCb=e[t].run;e=0,hasRun.resolve(),loadDependencies(contains,[],function(){for(t=contains.length,result=[];t--;)result.push(f(contains[t],url).result);asyncLoad.resolve(result)})}else asyncLoad.resolve(result||(scriptDef.result=result=bare?"bare":i.call(promise,n,options)));result=multiple?0:result}delayDomReady&&h(!0)}}function reject(){asyncLoad.reject("fail",url)}function loadDependencies(t,r,u){r=r||[];for(var f=t&&t.length;f--;)r.push(i(t[f],options,url));n.when.apply(n,r).fail(reject).done(u||run)}function getScript(){return n.ajax({url:loadUrl,dataType:"script",timeout:settings.timeout,cache:!settings.noCache,crossDomain:!0}).fail(reject).done(function(){var t=bare?0:l.shift();if(!t){bare||reject(),run();return}runCb=scriptDef.runCb=t.run,t.def&&n.deferDef(t.def,url),depends=o(t.depends)||[],prepareSubDefs(!contains&&t.contains),depends.length&&(runWait++,loadDependencies(depends))})}function prepareSubDefs(t){if(t)for(hasRun=n.Deferred(),hasRunPromise=[hasRun.promise()],contains=o(t),i=contains.length;i--;)f(contains[i],url).prntPrms=hasRunPromise}options=options||{};var i,readyName,asyncLoad,result,prevPromise,runWait=0,delayDomReady=options.delayDomReady||s.delayDomReady,min=options.min||s.min,scriptDef=f(scriptName,basePath),url=scriptDef.url,loadUrl=min&&scriptDef.minUrl||scriptDef.url,settings=n.extend(scriptDef,options),bare=settings.bare,contains=settings.contains,loaded=settings.loaded,depends=settings.depends,multiple=settings.multiple,parentPromise=scriptDef.prntPrms,promise=scriptDef.promise,runCb,thisPromise,hasRun,hasRunPromise;if(multiple||!promise){if(asyncLoad=n.Deferred(),loaded&&eval(loaded))return asyncLoad.resolve().promise();delayDomReady&&n.readyWait++,prevPromise=promise,asyncLoad=n.Deferred(),promise=scriptDef.promise=asyncLoad.promise(),bare?loadDependencies(depends,0,getScript):prevPromise?loadDependencies(0,[prevPromise]):parentPromise?loadDependencies(depends,parentPromise):(prepareSubDefs(contains),loadDependencies(depends,[getScript().promise()]))}return(readyName=options.readyName||scriptDef.name)&&(h[readyName]=promise),promise},deferDef:function(t,e){function y(t,f){typeof f=="string"&&(f={url:f});var h=f.minUrl,e=u(o,f.url),s=r[e]||function(){var r=Array.prototype.slice.call(arguments,0);return r.unshift(t),i.apply(n,r)};f.url=e,h&&(f.minUrl=u(o,h)),n.extend(s,f),r[e]=i[t]=s,s.name=t}var s,o,h,l=c.getElementsByTagName("script");if(l=l[l.length-1],o=a(e||l.src),typeof t=="string")return i[t]||r[u(o,t)];for(s in t)y(s,t[s]);for(s in t)h=f(s),h.depends=v(h.depends,o),h.contains=v(h.contains,o)},deferSettings:{delayDomReady:!1,min:!0}}),t.$deferRun=function(n,t){t=o(t),t=t&&t.length?{depends:t}:t||{},t.run=n,(e||l).push(t)},s=n.deferSettings,i=n.defer,h=n.ready}(jQuery,window); 3 | //@ sourceMappingURL=jquery.defer.min.js.map -------------------------------------------------------------------------------- /jquery.defer.min.js.map: -------------------------------------------------------------------------------- 1 | { 2 | "version":3, 3 | "file":"jquery.defer.min.js", 4 | "lineCount":2, 5 | "mappings":";AAYAA,MAAMC,MAAO,EAAI,QAAQ,CAAEC,CAAC,CAAEC,CAAL,CAAyB,CASlDC,SAASA,CAAM,CAAEC,CAAQ,CAAEC,CAAZ,CAAkB,CAIhC,OAHKA,CAAGC,QAAQ,CAAE,IAAF,CAAS,GAAI,E,GAC5BD,CAAI,CAAED,CAAS,CAAEC,EAAG,CAEdE,CAAMC,KAAM,CAAEH,CAJW,CAQjCI,SAASA,CAAW,CAAEJ,CAAF,CAAQ,CAC3B,OAAOA,CAAGK,MAAM,CAAE,CAAC,CAAEL,CAAGM,YAAY,CAAC,GAAD,CAAM,CAAE,CAA5B,CADW,CAI5BC,SAASA,CAAS,CAAEC,CAAF,CAAU,CAC3B,OAAO,OAAOA,CAAM,EAAI,QAAS,CAAE,CAAEA,CAAF,CAAU,CAAEA,CADpB,CAI5BC,SAASA,CAAS,CAAED,CAAK,CAAET,CAAT,CAAoB,CACrC,GAAK,CAACS,EACL,OAAO,CACR,CACAA,CAAM,CAAED,CAAS,CAAEC,CAAF,CAAS,C,IAC1B,IAAIE,EAAMC,EAAIH,CAAKI,O,CACXD,CAAC,E,C,CACRD,CAAK,CAAEF,CAAO,CAAAG,CAAA,CAAG,CACXhB,CAAO,CAAAe,CAAA,C,GACZF,CAAO,CAAAG,CAAA,CAAI,CAAEb,CAAM,CAAEC,CAAQ,CAAEW,CAAZ,EAErB,CACA,OAAOF,CAZ8B,CAetCK,SAASA,CAAY,CAAEH,CAAI,CAAEI,CAAR,CAAkB,CACtC,IAAIC,EACHC,EAAYrB,CAAO,CAAAe,CAAA,CAAM,CAQ1B,OANKM,C,CACGA,C,EAGRF,CAAQ,CAAEhB,CAAM,CAAEM,CAAW,CAAEU,CAAQ,EAAG,EAAb,CAAiB,CAAEJ,CAAhC,CAAsC,CACtDK,CAAW,CAAED,CAAOG,YAAY,CAAA,CAAE,CAC3BC,CAAa,CAAAH,CAAA,CAAa,EAAG,CAACG,CAAa,CAAAH,CAAA,CAAa,CAAE,CAAE,GAAG,CAAED,CAAP,CAA7B,EAVE,CAtCvC,IAAIK,EAAWtB,CAAMsB,UACpBjB,EAASiB,CAAQC,cAAc,CAAC,GAAD,EAC/BC,EAAe1B,EAAO2B,EACtBJ,EAAc,CAAA,EACdK,EAAiB,CAAA,EACjBC,CAAiB,CA8ClB5B,CAAC6B,OAAO,CAAC,CACR,KAAK,CAAE9B,QAAQ,CAAE+B,UAAU,CAAEC,OAAO,CAAE5B,QAAvB,CAAkC,CAsBhD6B,SAASA,GAAG,CAAA,CAAG,CACd,IAAIjB,EAAGkB,EAAYC,KAAM,EAAGd,SAASc,MAAM,CAE3C,GAAK,CAAEC,OAAO,GAAM,CACnB,GAAKC,SAASC,MAAM,CAAA,CAAG,GAAI,WAAa,CACvC,GAAKC,cACJF,SAASG,QAAQ,CAChBC,MAAO,EACP,CAACpB,SAASoB,OAAQ,CAAEA,MAAO,CAAEP,CAASQ,KAAK,CAAEC,OAAO,CAAE1C,CAAC,CAAE+B,OAAd,CAA3C,CAFgB,CAGhB,CACA,KAAK,GAAKY,SAAW,C,IACtBf,CAAkB,CAAE,CAAA,CAAE,CAEtBK,CAASQ,KAAK,CAAEC,OAAO,CAAE1C,CAAC,CAAE+B,OAAd,CAAuB,CAErChB,CAAE,CAAE4B,QAAQ3B,O,CAMHD,CAAC,E,C,CACTE,CAAY,CAAE0B,QAAU,CAAA5B,CAAA,CAAG,CAAEX,GAAjB,CAAsB8B,MAAO,CAAEN,CAAmB,CAAAb,CAAA,CAAGiB,IAClE,CACAJ,CAAkB,CAAE,CAAC,CAErBgB,MAAML,QAAQ,CAAA,CAAE,CAEhBM,gBAAgB,CAAEF,QAAQ,CAAE,CAAA,CAAE,CAAE,QAAQ,CAAA,CAAG,C,IAC1C5B,CAAE,CAAE4B,QAAQ3B,OAAO,CAClBwB,MAAO,CAAE,CAAA,C,CACFzB,CAAC,E,C,CACRyB,MAAMM,KAAK,CAAE7B,CAAY,CAAE0B,QAAU,CAAA5B,CAAA,CAAG,CAAEX,GAAjB,CAAsBoC,OAApC,CACZ,CACAJ,SAASG,QAAQ,CAAEC,MAAF,CANyB,CAA3B,CAlBM,CA0BrB,KACDJ,SAASG,QAAQ,CAChBC,MAAO,EACP,CAACpB,SAASoB,OAAQ,CAAEA,MAAO,CAAEO,IAAK,CAAE,MAAO,CAAEd,CAASQ,KAAK,CAAEC,OAAO,CAAE1C,CAAC,CAAE+B,OAAd,CAA3D,CAFgB,CAIlB,CACAS,MAAO,CAAEQ,QAAS,CAAE,CAAE,CAAER,MAtCe,CAwCnCS,a,EACJvB,CAAK,CAAE,CAAA,CAAF,CA1Ca,CAHN,CAkDfwB,SAASA,MAAM,CAAA,CAAG,CACjBd,SAASc,OAAO,CAAE,MAAM,CAAE9C,GAAV,CADC,CAIlByC,SAASA,gBAAgB,CAAEM,CAAU,CAAEC,CAAQ,CAAEC,CAAxB,CAA6B,CACrDD,CAAS,CAAEA,CAAS,EAAG,CAAA,CAAE,C,IACzB,IAAIrC,EAAIoC,CAAW,EAAGA,CAAUnC,O,CACxBD,CAAC,E,C,CACRqC,CAAQN,KAAK,CAAE/C,CAAK,CAAEoD,CAAY,CAAApC,CAAA,CAAG,CAAEgB,OAAO,CAAE3B,GAA5B,CAAP,CACd,CACAJ,CAACsD,KAAKC,MAAM,CAAEvD,CAAC,CAAEoD,CAAL,CAAeI,KAAK,CAAEN,MAAF,CAAUO,KAAK,CAAEJ,CAAG,EAAGrB,GAAR,CANM,CAStD0B,SAASA,SAAS,CAAA,CAAG,CACpB,OAAO1D,CAAC2D,KAAK,CAAC,CACZ,GAAG,CAAEC,OAAO,CACZ,QAAQ,CAAE,QAAQ,CAClB,OAAO,CAAEC,QAAQC,QAAQ,CACzB,KAAK,CAAE,CAACD,QAAQE,QAAQ,CACxB,WAAW,CAAE,CAAA,CALD,CAAD,CAQZP,KAAK,CAAEN,MAAF,CAGLO,KAAK,CAAE,QAAQ,CAAA,CAAG,CAEjB,IAAIO,EAAmBjB,IAAK,CAAE,CAAE,CAAEpB,CAAcsC,MAAM,CAAA,CAAE,CAExD,GAAK,CAACD,EAAmB,CAClBjB,I,EAILG,MAAM,CAAA,CAAE,CAGTlB,GAAG,CAAA,CAAE,CACL,MATwB,CAYzBE,KAAM,CAAEd,SAASc,MAAO,CAAE8B,CAAgBhC,IAAI,CAEzCgC,CAAgBE,I,EACpBlE,CAACmE,SAAS,CAAEH,CAAgBE,IAAI,CAAE9D,GAAxB,CAA6B,CAGxCgE,OAAQ,CAAEzD,CAAS,CAAEqD,CAAgBI,QAAlB,CAA6B,EAAG,CAAA,CAAE,CACrDC,cAAc,CAAE,CAAC1B,QAAS,EAAGqB,CAAgBrB,SAA/B,C,CAETyB,OAAOpD,O,GACXmB,OAAO,EAAE,CACTU,gBAAgB,CAAEuB,OAAF,EA3BA,CAAb,CAZc,CA4CrBC,SAASA,cAAc,CAAEC,CAAF,CAAiB,CACvC,GAAKA,E,IACJ1B,MAAO,CAAE5C,CAACuE,SAAS,CAAA,CAAE,CACrBC,aAAc,CAAE,CAAE5B,MAAMF,QAAQ,CAAA,CAAhB,CAAoB,CACpCC,QAAS,CAAEhC,CAAS,CAAE2D,CAAF,CAAgB,CACpCvD,CAAE,CAAE4B,QAAQ3B,O,CACJD,CAAC,E,C,CACRE,CAAY,CAAE0B,QAAU,CAAA5B,CAAA,CAAG,CAAEX,GAAjB,CAAsBqE,SAAU,CAAED,aAPT,CAhIxCzC,OAAQ,CAAEA,OAAQ,EAAG,CAAA,CAAE,CAEvB,IAAIhB,EAAG2D,UAAWtC,UAAWI,OAAQmC,YACpCxC,QAAU,EACVc,cAAgBlB,OAAOkB,cAAe,EAAGxB,CAAawB,eACtD2B,IAAM7C,OAAO6C,IAAK,EAAGnD,CAAamD,KAClCxD,UAAYH,CAAY,CAAEa,UAAU,CAAE3B,QAAd,EACxBC,IAAMgB,SAAShB,KACfwD,QAAYgB,GAAI,EAAGxD,SAASyD,OAAU,EAAGzD,SAAShB,KAElDyD,SAAW7D,CAAC6B,OAAO,CAAET,SAAS,CAAEW,OAAb,EACnBgB,KAAOc,QAAQd,MACfJ,SAAWkB,QAAQlB,UACnBmC,OAASjB,QAAQiB,QACjBV,QAAUP,QAAQO,SAClBpB,SAAWa,QAAQb,UAEnBV,cAAgBlB,SAASqD,UACzB/B,QAAUtB,SAASsB,SACnBR,MAAO6C,YAAanC,OAAQ4B,aAAa,CAyH1C,GAAKxB,QAAS,EAAG,CAACN,QAAU,CAG3B,GAFAN,SAAU,CAAEpC,CAACuE,SAAS,CAAA,CAAE,CAEnBO,MAAO,EAAGE,IAAI,CAAEF,MAAF,EAClB,OAAO1C,SAASG,QAAQ,CAAA,CAAEG,QAAQ,CAAA,CACnC,CAEKO,a,EACJjD,CAACiF,UAAU,EAAE,CAGdN,WAAY,CAAEjC,OAAO,CACrBN,SAAU,CAAEpC,CAACuE,SAAS,CAAA,CAAE,CACxB7B,OAAQ,CAAEtB,SAASsB,QAAS,CAAEN,SAASM,QAAQ,CAAA,CAAE,CAE5CK,IAAL,CACCF,gBAAgB,CAAEuB,OAAO,CAAE,CAAC,CAAEV,SAAd,CADjB,CAEYiB,WAAL,CAEN9B,gBAAgB,CAAE,CAAC,CAAE,CAAE8B,WAAF,CAAL,CAFV,CAGKrC,aAAL,CACNO,gBAAgB,CAAEuB,OAAO,CAAE9B,aAAX,CADV,EAGN+B,cAAc,CAAE1B,QAAF,CAAY,CAE1BE,gBAAgB,CAAEuB,OAAO,CAAE,CAAEV,SAAS,CAAA,CAAEhB,QAAQ,CAAA,CAArB,CAAX,EAzBU,CA+B5B,OAHKgC,SAAU,CAAE3C,OAAO2C,UAAW,EAAGtD,SAASN,M,GAC9CY,CAAO,CAAAgD,SAAA,CAAY,CAAEhC,QAAO,CAEtBA,OA5KyC,CA6KhD,CAED,QAAQ,CAAEyB,QAAQ,CAAEe,CAAU,CAAEhE,CAAd,CAAwB,CAIzCiE,SAASA,CAAY,CAAErE,CAAI,CAAEsE,CAAR,CAAuB,CAEtC,OAAOA,CAAa,EAAI,Q,GAC5BA,CAAa,CAAE,CAAE,GAAG,CAAEA,CAAP,EAAqB,CAGrC,IAAIP,EAASO,CAAYP,QACxBzE,EAAMF,CAAM,CAAEC,CAAQ,CAAEiF,CAAYhF,IAAxB,EAcZgB,EAAYE,CAAa,CAAAlB,CAAA,CAAM,EAAGgB,QAAQ,CAAA,CAAG,CAC5C,IAAIiE,EAAOC,KAAKC,UAAU9E,MAAMgC,KAAK,CAAE+C,SAAS,CAAE,CAAb,CAAgB,CAErD,OADAH,CAAII,QAAQ,CAAE3E,CAAF,CAAQ,CACbf,CAAKwD,MAAM,CAAEvD,CAAC,CAAEqF,CAAL,CAH0B,CAI5C,CAEFD,CAAYhF,IAAK,CAAEA,CAAG,CACjByE,C,GACJO,CAAYP,OAAQ,CAAE3E,CAAM,CAAEC,CAAQ,CAAE0E,CAAZ,EAAoB,CAGjD7E,CAAC6B,OAAO,CAAET,CAAS,CAAEgE,CAAb,CAA2B,CAEnC9D,CAAa,CAAAlB,CAAA,CAAM,CAAEL,CAAO,CAAAe,CAAA,CAAO,CAAEM,CAAS,CAC9CA,CAASN,KAAM,CAAEA,CAnC0B,CAH5C,IAAIgB,EAAY3B,EAAUiB,EACzBsE,EAAWnE,CAAQoE,qBAAqB,CAAE,QAAF,CAAY,CA+CrD,GAHAD,CAAS,CAAEA,CAAU,CAAAA,CAAQ1E,OAAO,CAAC,CAAhB,CAAmB,CACxCb,CAAS,CAAEK,CAAW,CAAEU,CAAQ,EAAGwE,CAAQE,IAArB,CAA2B,CAE5C,OAAOV,CAAW,EAAI,SAE1B,OAAOnF,CAAM,CAAAmF,CAAA,CAAa,EAAG5D,CAAa,CAAApB,CAAM,CAAEC,CAAQ,CAAE+E,CAAZ,CAAN,CAC3C,CAEA,IAAMpD,EAAW,GAAGoD,CAApB,CACCC,CAAY,CAAErD,CAAU,CAAEoD,CAAY,CAAApD,CAAA,CAA1B,CACb,CACA,IAAMA,EAAW,GAAGoD,CAApB,CACC9D,CAAU,CAAEH,CAAY,CAAEa,CAAF,CAAc,CACtCV,CAASgD,QAAS,CAAEvD,CAAS,CAAEO,CAASgD,QAAQ,CAAEjE,CAArB,CAA+B,CAC5DiB,CAASuB,SAAU,CAAE9B,CAAS,CAAEO,CAASuB,SAAS,CAAExC,CAAtB,CA5DU,CA8DzC,CAED,aAAa,CAAE,CACd,aAAa,CAAE,CAAA,CAAK,CACpB,GAAG,CAAE,CAAA,CAFS,CAhPP,CAAD,CAoPN,CAEFF,CAAM4F,UAAW,CAAEC,QAAQ,CAAE9D,CAAG,CAAE6B,CAAP,CAAkB,CAC5CA,CAAS,CAAElD,CAAS,CAAEkD,CAAF,CAAY,CAChCA,CAAS,CAAEA,CAAS,EAAGA,CAAQ7C,OAAQ,CAAE,CAAE,OAAO,CAAE6C,CAAX,CAAsB,CAAEA,CAAS,EAAG,CAAA,CAAE,CAC/EA,CAAQ7B,IAAK,CAAEA,CAAG,CAElB,CAAEJ,CAAkB,EAAGD,CAAvB,CAAuCmB,KAAK,CAAEe,CAAF,CALA,CAM5C,CAEDpC,CAAc,CAAEzB,CAACyB,cAAc,CAC/B1B,CAAM,CAAEC,CAACD,MAAM,CACf2B,CAAM,CAAE1B,CAAC0B,MArTyC,CAuThD,CAAE5B,MAAM,CAAEG,MAAV,CAAkB", 6 | "sources":["jquery.defer.js"], 7 | "names":["jQuery","defer","$","window","absUrl","basePath","url","indexOf","anchor","href","getBasePath","slice","lastIndexOf","makeArray","items","normalize","name","i","length","getScriptDef","thisUrl","thisUrlKey","scriptDef","toLowerCase","scriptByUrl","document","createElement","deferSettings","ready","loadingScripts","loadingSubScripts","extend","scriptName","options","run","thisRunCb","runCb","runWait","asyncLoad","state","parentPromise","resolve","result","call","promise","contains","hasRun","loadDependencies","push","bare","multiple","delayDomReady","reject","newDepends","promises","cb","when","apply","fail","done","getScript","ajax","loadUrl","settings","timeout","noCache","deferRunSettings","shift","def","deferDef","depends","prepareSubDefs","containNames","Deferred","hasRunPromise","prntPrms","readyName","prevPromise","min","minUrl","loaded","thisPromise","eval","readyWait","scriptDefs","defineScript","newScriptDef","args","Array","prototype","arguments","unshift","scriptEl","getElementsByTagName","src","$deferRun","window.$deferRun"] 8 | } 9 | -------------------------------------------------------------------------------- /jsdefer.js: -------------------------------------------------------------------------------- 1 | /*! JsDefer v1.0.0-alpha: http://github.com/BorisMoore/jsdefer and http://jsviews.com/jsviews */ 2 | /* 3 | * Script loader, using the 'Deferred' pattern for async operations 4 | * Two versions: 5 | * - jsdefer.js (this file): the jQuery-independent version of JsDefer 6 | * - jquery.defer.js: the jQuery plugin version of JsDefer 7 | * Copyright 2013, Boris Moore 8 | * Released under the MIT License. 9 | */ 10 | 11 | // This is jsdefer.js: the jQuery-independent version of JsDefer 12 | 13 | window.jsDefer || window.jQuery && jQuery.defer || (function( window, undefined ) { 14 | 15 | var $, document = window.document, 16 | anchor = document.createElement("a"), 17 | deferSettings, defer, deferDef, ready, readyList, 18 | scriptByUrl = {}, 19 | loadingScripts = [], 20 | loadingSubScripts, 21 | promiseMethods = "then done fail state promise".split( " " ), 22 | slice = [].slice; 23 | 24 | if ( window.jQuery ) { 25 | //////////////////////////////////////////////////////////////////////////////////////////////// 26 | // jQuery is loaded, so make $ the jQuery object 27 | $ = jQuery; 28 | 29 | // Workaround, to expose domReady promise. (Only needed because the Dom Ready promise is not exposed by core). 30 | $( function() { 31 | readyList.resolveWith( document , [ $ ] ); 32 | }); 33 | 34 | } else { 35 | //////////////////////////////////////////////////////////////////////////////////////////////// 36 | // jQuery is not loaded. Make $ the jsDefer object 37 | 38 | // Use a 'clone' of the implementation of Deferred from jQuery-1.10.0.js 39 | // to provide identical Deferred APIs and behavior to jQuery. 40 | 41 | // Also provide simplified support for $.extend, DomReady and AJAX x-domain requests, 42 | // since we can't use jQuery implementations of those... 43 | 44 | window.jsDefer = window.$ = $ = function( cb ) { 45 | return readyList.done( cb ); 46 | }; 47 | 48 | $.extend = function( target, source ) { 49 | if ( source === undefined ) { 50 | source = target; 51 | target = $; 52 | } 53 | for ( var name in source ) { 54 | target[ name ] = source[ name ]; 55 | } 56 | return target; 57 | }; 58 | 59 | $.extend({ 60 | readyWait: 1, 61 | 62 | ready: function( wait ) { 63 | // A third-party is pushing the ready event forwards 64 | if ( wait === true ) { 65 | $.readyWait--; 66 | } 67 | if ( !$.readyWait || (wait !== true && !$.isReady) ) { 68 | readyList.resolveWith( document , [ $ ] ); 69 | } 70 | }, 71 | 72 | isFunction: function( elem ) { 73 | return typeof elem === "function"; 74 | }, 75 | 76 | // Create a simple deferred (one callbacks list) 77 | _Deferred: function() { 78 | var // callbacks list 79 | callbacks = [], 80 | // stored [ context , args ] 81 | fired, 82 | // to avoid firing when already doing so 83 | firing, 84 | // flag to know if the deferred has been cancelled 85 | cancelled, 86 | // the deferred itself 87 | deferred = { 88 | 89 | // done( f1, f2, ...) 90 | done: function() { 91 | if ( !cancelled ) { 92 | var args = arguments, 93 | i, 94 | length, 95 | elem, 96 | type, 97 | _fired; 98 | if ( fired ) { 99 | _fired = fired; 100 | fired = 0; 101 | } 102 | for ( i = 0, length = args.length; i < length; i++ ) { 103 | elem = args[ i ]; 104 | if ( elem instanceof Array ) { 105 | deferred.done.apply( deferred, elem ); 106 | } else if ( $.isFunction( elem )) { 107 | callbacks.push( elem ); 108 | } 109 | } 110 | if ( _fired ) { 111 | deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); 112 | } 113 | } 114 | return this; 115 | }, 116 | 117 | // resolve with given context and args 118 | resolveWith: function( context, args ) { 119 | if ( !cancelled && !fired && !firing ) { 120 | // make sure args are available (#8421) 121 | args = args || []; 122 | firing = 1; 123 | try { 124 | while( callbacks[ 0 ] ) { 125 | callbacks.shift().apply( context, args ); 126 | } 127 | } 128 | finally { 129 | fired = [ context, args ]; 130 | firing = 0; 131 | } 132 | } 133 | return this; 134 | }, 135 | 136 | // resolve with this as context and given arguments 137 | resolve: function() { 138 | deferred.resolveWith( this, arguments ); 139 | return this; 140 | }, 141 | 142 | // Has this deferred been resolved? 143 | isResolved: function() { 144 | return !!( firing || fired ); 145 | }, 146 | 147 | // Cancel 148 | cancel: function() { 149 | cancelled = 1; 150 | callbacks = []; 151 | return this; 152 | } 153 | }; 154 | 155 | return deferred; 156 | }, 157 | 158 | // Full fledged deferred (two callbacks list) 159 | Deferred: function( func ) { 160 | var deferred = $._Deferred(), 161 | failDeferred = $._Deferred(), 162 | promise; 163 | // Add errorDeferred methods, then and promise 164 | $.extend( deferred, { 165 | then: function( doneCallbacks, failCallbacks ) { 166 | deferred.done( doneCallbacks ).fail( failCallbacks ); 167 | return this; 168 | }, 169 | fail: failDeferred.done, 170 | rejectWith: failDeferred.resolveWith, 171 | reject: failDeferred.resolve, 172 | isRejected: failDeferred.isResolved, 173 | // Get a promise for this deferred 174 | // If obj is provided, the promise aspect is added to the object 175 | promise: function( obj , i /* internal */ ) { 176 | if ( obj == null ) { 177 | if ( promise ) { 178 | return promise; 179 | } 180 | promise = obj = {}; 181 | } 182 | i = promiseMethods.length; 183 | while( i-- ) { 184 | obj[ promiseMethods[ i ] ] = deferred[ promiseMethods[ i ] ]; 185 | } 186 | return obj; 187 | } 188 | } ); 189 | // Make sure only one callback list will be used 190 | deferred.done( failDeferred.cancel ).fail( deferred.cancel ); 191 | // Unexpose cancel 192 | delete deferred.cancel; 193 | // Call given func if any 194 | if ( func ) { 195 | func.call( deferred, deferred ); 196 | } 197 | return deferred; 198 | }, 199 | 200 | // Deferred helper 201 | when: function( firstParam ) { 202 | var args = arguments, 203 | i = 0, 204 | length = args.length, 205 | count = length, 206 | deferred = length <= 1 && firstParam && $.isFunction( firstParam.promise ) ? 207 | firstParam : 208 | $.Deferred(); 209 | function resolveFunc( i ) { 210 | return function( value ) { 211 | args[ i ] = arguments.length > 1 ? slice.call( arguments, 0 ) : value; 212 | if ( !( --count ) ) { 213 | // Strange bug in FF4: 214 | // Values changed onto the arguments object sometimes end up as undefined values 215 | // outside the $.when method. Cloning the object into a fresh array solves the issue 216 | deferred.resolveWith( deferred, slice.call( args, 0 ) ); 217 | } 218 | }; 219 | } 220 | if ( length > 1 ) { 221 | for( ; i < length; i++ ) { 222 | if ( args[ i ] && $.isFunction( args[ i ].promise ) ) { 223 | args[ i ].promise().then( resolveFunc(i), deferred.reject ); 224 | } else { 225 | --count; 226 | } 227 | } 228 | if ( !count ) { 229 | deferred.resolveWith( deferred, args ); 230 | } 231 | } else if ( deferred !== firstParam ) { 232 | deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); 233 | } 234 | return deferred.promise(); 235 | } 236 | }); 237 | 238 | function getAjax( options ) { 239 | var deferred = $.Deferred(), 240 | head = document.getElementsByTagName( "head" )[ 0 ] || document.documentElement, 241 | script = document.createElement( "script" ); 242 | 243 | script.src = options.url; 244 | 245 | // TODO? Add support for timeout and cache 246 | 247 | script.onload = script.onreadystatechange = function() { 248 | if ( !script.readyState || /loaded|complete/.test( script.readyState ) ) { 249 | // Handle memory leak in IE 250 | script.onload = script.onreadystatechange = null; 251 | if ( head && script.parentNode ) { 252 | head.removeChild( script ); 253 | } 254 | 255 | // Dereference the script 256 | script = undefined; 257 | 258 | deferred.resolve(); 259 | } 260 | }; 261 | head.insertBefore( script, head.firstChild ); 262 | return deferred; 263 | }; 264 | } 265 | 266 | 267 | //////////////////////////////////////////////////////////////////////////////////////////////// 268 | // The following code is identical to the corresponding code in jquery.defer.js 269 | 270 | function absUrl( basePath, url ) { 271 | if ( url.indexOf( "://" ) === -1 ) { 272 | url = basePath + url; 273 | } 274 | return anchor.href = url; 275 | // For IE without DOCTYPE - need use recursive regex along lines: parts = url.split( "/../" ); parts[0] = parts[0].slice( 0, parts[0].lastIndexOf("/") + 1 ); Use recursive regex; return parts.join("").toLowerCase(); 276 | } 277 | 278 | function getBasePath( url ) { 279 | return url.slice( 0, url.lastIndexOf("/") + 1 ); 280 | } 281 | 282 | function makeArray( items ) { 283 | return typeof items === "string" ? [ items ] : items; 284 | } 285 | 286 | function normalize( items, basePath ) { 287 | if ( !items ) { 288 | return 0; 289 | } 290 | items = makeArray( items ); 291 | var name, i = items.length; 292 | while ( i-- ) { 293 | name = items[ i ]; 294 | if ( !defer[ name ] ) { 295 | items[ i ] = absUrl( basePath, name ); 296 | } 297 | } 298 | return items; 299 | } 300 | 301 | function getScriptDef( name, thisUrl ) { 302 | var thisUrlKey, 303 | scriptDef = defer[ name ]; 304 | 305 | if ( scriptDef ) { 306 | return scriptDef; 307 | } 308 | 309 | thisUrl = absUrl( getBasePath( thisUrl || "" ), name ); 310 | thisUrlKey = thisUrl.toLowerCase(); 311 | return scriptByUrl[ thisUrlKey ] || (scriptByUrl[ thisUrlKey ] = { url: thisUrl }); 312 | } 313 | 314 | $.extend({ 315 | defer: function( scriptName, options, basePath ) { 316 | options = options || {}; 317 | 318 | var i, readyName, asyncLoad, result, prevPromise, 319 | runWait = 0, 320 | delayDomReady = options.delayDomReady || deferSettings.delayDomReady, 321 | min = options.min || deferSettings.min, 322 | scriptDef = getScriptDef( scriptName, basePath ), 323 | url = scriptDef.url, 324 | loadUrl = ( min && scriptDef.minUrl ) || scriptDef.url, 325 | 326 | settings = $.extend( scriptDef, options ), 327 | bare = settings.bare, 328 | contains = settings.contains, 329 | loaded = settings.loaded, 330 | depends = settings.depends, 331 | multiple = settings.multiple, 332 | 333 | parentPromise = scriptDef.prntPrms, 334 | promise = scriptDef.promise, 335 | runCb, thisPromise, hasRun, hasRunPromise; 336 | 337 | function run() { 338 | var i, thisRunCb = runCb || scriptDef.runCb; // For multiple or composite scripts, callback was passed via scriptDef 339 | 340 | if ( !(runWait--) ) { 341 | if ( !asyncLoad.isRejected() ) { 342 | if ( parentPromise ) { 343 | asyncLoad.resolve( 344 | result || 345 | (scriptDef.result = result = thisRunCb.call( promise, $, options )) 346 | ); 347 | } else if ( contains ) { 348 | loadingSubScripts = []; 349 | 350 | thisRunCb.call( promise, $, options ); 351 | 352 | i = contains.length; 353 | 354 | // The following lines could be in debug build only... 355 | //if ( loadingSubScripts.length !== i ) { 356 | // throw url; //script definition error - number of contained scripts not equal to contains array length. 357 | //} 358 | while ( i-- ) { 359 | getScriptDef( contains[ i ], url ).runCb = loadingSubScripts[ i ].run; 360 | } 361 | loadingSubScripts = 0; 362 | 363 | hasRun.resolve(); 364 | 365 | loadDependencies( contains, [], function() { 366 | i = contains.length; 367 | result = []; 368 | while ( i-- ) { 369 | result.push( getScriptDef( contains[ i ], url ).result ); 370 | } 371 | asyncLoad.resolve( result ); 372 | }); 373 | } else { 374 | asyncLoad.resolve( 375 | result || 376 | (scriptDef.result = result = bare ? "bare" : thisRunCb.call( promise, $, options )) 377 | ); 378 | } 379 | result = multiple ? 0 : result; 380 | } 381 | if ( delayDomReady ) { 382 | ready( true ); 383 | } 384 | } 385 | } 386 | 387 | function reject() { 388 | asyncLoad.reject( "fail", url ); 389 | } 390 | 391 | function loadDependencies( newDepends, promises, cb ) { 392 | promises = promises || []; 393 | var i = newDepends && newDepends.length; 394 | while ( i-- ) { 395 | promises.push( defer( newDepends[ i ], options, url )); 396 | } 397 | $.when.apply( $, promises ).fail( reject ).done( cb || run ); 398 | } 399 | 400 | function getScript() { 401 | // Use $.ajax if jQuery is loaded. Otherwised use our stripped down getAjax call. 402 | return ($.ajax || getAjax)({ 403 | url: loadUrl, 404 | dataType: "script", 405 | timeout: options.timeout, 406 | cache: !options.noCache, 407 | crossDomain: true // Force regular script insertion, rather than XMLHTTP plus script insertion in document, for easier debugging. 408 | }) 409 | 410 | .fail( reject ) 411 | 412 | // readyStateChange complete has happened 413 | .done( function() { 414 | 415 | var deferRunSettings = bare ? 0 : loadingScripts.shift(); 416 | 417 | if ( !deferRunSettings ) { 418 | if ( !bare ) { 419 | // 404 or similar - no script got loaded for this url. 420 | // This only works for IE. For Chrome and FF, neither done nor fail cb of $.ajax get called for 404. 421 | // Set timeout to get error for all browsers. 422 | reject(); 423 | } 424 | // Non-wrapped script 425 | if ( window.jQuery && $ !== jQuery ) { 426 | // Special case: jQuery has been loaded dynamically by JsDefer, so switch to plugin version of JsDefer 427 | $ = jQuery.extend({ 428 | defer: defer, 429 | deferSettings: deferSettings, 430 | deferDef: deferDef 431 | }); 432 | } 433 | run(); 434 | return; 435 | } 436 | 437 | runCb = scriptDef.runCb = deferRunSettings.run; 438 | 439 | if ( deferRunSettings.def ) { 440 | deferDef( deferRunSettings.def, url ); 441 | } 442 | 443 | depends = makeArray( deferRunSettings.depends ) || []; 444 | prepareSubDefs( !contains && deferRunSettings.contains ) 445 | 446 | if ( depends.length ) { 447 | runWait++; 448 | loadDependencies( depends ); 449 | } 450 | }); 451 | } 452 | 453 | function prepareSubDefs( containNames ) { 454 | if ( containNames ) { 455 | hasRun = $.Deferred(); 456 | hasRunPromise = [ hasRun.promise() ]; 457 | contains = makeArray( containNames ); 458 | i = contains.length; 459 | while ( i-- ) { 460 | getScriptDef( contains[ i ], url ).prntPrms = hasRunPromise; 461 | } 462 | } 463 | } 464 | 465 | if ( multiple || !promise ) { 466 | asyncLoad = $.Deferred(); 467 | 468 | if ( loaded && eval( loaded )) { 469 | return asyncLoad.resolve().promise(); 470 | } 471 | 472 | if ( delayDomReady ) { 473 | $.readyWait++; 474 | } 475 | 476 | prevPromise = promise; 477 | asyncLoad = $.Deferred(); 478 | promise = scriptDef.promise = asyncLoad.promise(); 479 | 480 | if ( bare ) { 481 | loadDependencies( depends, 0, getScript ); 482 | } else if ( prevPromise ) { 483 | // This is a subsequent call, with multiple = true; 484 | loadDependencies( depends, [ prevPromise ]); 485 | } else if ( parentPromise ) { 486 | loadDependencies( depends, parentPromise ); 487 | } else { 488 | prepareSubDefs( contains ); 489 | 490 | loadDependencies( depends, [ getScript().promise() ] ); 491 | } 492 | } 493 | if ( readyName = options.readyName || scriptDef.name ) { 494 | ready[ readyName ] = promise; 495 | } 496 | return promise; 497 | }, 498 | 499 | deferDef: function( scriptDefs, thisUrl ) { 500 | var scriptName, basePath, scriptDef, 501 | scriptEl = document.getElementsByTagName( "script" ); 502 | 503 | function defineScript( name, newScriptDef ) { 504 | // Autogenerate methods on defer for registered scripts. 505 | if ( typeof newScriptDef === "string" ) { 506 | newScriptDef = { url: newScriptDef }; 507 | } 508 | 509 | var minUrl = newScriptDef.minUrl, 510 | url = absUrl( basePath, newScriptDef.url ), 511 | 512 | // May be some issues in Chrome. Investigate: 513 | // scriptDef = scriptByUrl[ url ]; 514 | // // Autogenerate methods on defer for registered scripts. 515 | // if ( !scriptDef ) { 516 | // scriptDef = function() { 517 | // var args = array.prototype.slice.call( arguments, 0 ); 518 | // args.unshift( name ); 519 | // return defer.apply( $, args ); 520 | // } 521 | // } 522 | 523 | // Autogenerate methods on defer for registered scripts. 524 | scriptDef = scriptByUrl[ url ] || function() { 525 | var args = slice.call( arguments, 0 ); 526 | args.unshift( name ); 527 | return defer.apply( $, args ); 528 | }; 529 | 530 | newScriptDef.url = url; 531 | if ( minUrl ) { 532 | newScriptDef.minUrl = absUrl( basePath, minUrl ); 533 | } 534 | 535 | $.extend( scriptDef, newScriptDef ); 536 | 537 | scriptByUrl[ url ] = defer[ name ] = scriptDef; 538 | scriptDef.name = name; 539 | } 540 | 541 | // This if fine for static scripts and inline script, but will not find the correct script element, in the case of dynamically loaded scripts. 542 | // So we require define to be loaded statically or in the page. 543 | // But can pass a definition to run, in dynamically loaded pages - and use thisUrl. 544 | 545 | scriptEl = scriptEl[ scriptEl.length-1 ]; 546 | basePath = getBasePath( thisUrl || scriptEl.src ); 547 | 548 | if ( typeof scriptDefs === "string" ) { 549 | // Calling $.deferDef( nameOrAbsoluteUrlOrRelativeUrl) will return the scriptDef object 550 | return defer[scriptDefs ] || scriptByUrl[ absUrl( basePath, scriptDefs )]; 551 | } 552 | 553 | for ( scriptName in scriptDefs ) { 554 | defineScript( scriptName, scriptDefs[ scriptName ] ); 555 | } 556 | for ( scriptName in scriptDefs ) { 557 | scriptDef = getScriptDef( scriptName ); 558 | scriptDef.depends = normalize( scriptDef.depends, basePath ); 559 | scriptDef.contains = normalize( scriptDef.contains, basePath ); 560 | } 561 | }, 562 | 563 | deferSettings: { 564 | delayDomReady: false, 565 | min: true 566 | } 567 | }); 568 | 569 | window.$deferRun = function( run, settings ) { 570 | settings = makeArray( settings ); 571 | settings = settings && settings.length ? { depends: settings } : settings || {}; 572 | settings.run = run; 573 | 574 | ( loadingSubScripts || loadingScripts ).push( settings ); 575 | }; 576 | 577 | deferSettings = $.deferSettings; 578 | defer = $.defer; 579 | deferDef = $.deferDef; 580 | ready = $.ready; 581 | 582 | readyList = $.Deferred(); 583 | readyList.promise( ready ); 584 | 585 | if ( !window.jQuery ) { 586 | function domReady() { 587 | if ( !document.body ) { 588 | return setTimeout( function() { 589 | domReady(); 590 | }, 1 ); 591 | } 592 | $.isReady = true; 593 | $.ready( true ); 594 | } 595 | domReady(); 596 | } 597 | })( window ); 598 | -------------------------------------------------------------------------------- /jsdefer.min.js: -------------------------------------------------------------------------------- 1 | /*! JsDefer v1.0.0-alpha: http://github.com/BorisMoore/jsdefer and http://jsviews.com/jsviews */ 2 | window.jsDefer||window.jQuery&&jQuery.defer||function(n,t){function o(n,t){return t.indexOf("://")===-1&&(t=n+t),g.href=t}function b(n){return n.slice(0,n.lastIndexOf("/")+1)}function a(n){return typeof n=="string"?[n]:n}function k(n,t){if(!n)return 0;n=a(n);for(var i,r=n.length;r--;)i=n[r],u[i]||(n[r]=o(t,i));return n}function s(n,t){var i,r=u[n];return r?r:(t=o(b(t||""),n),i=t.toLowerCase(),e[i]||(e[i]={url:t}))}var i,r=n.document,g=r.createElement("a"),h,u,v,c,f,e={},w=[],l,y="then done fail state promise".split(" "),p=[].slice;if(n.jQuery)i=jQuery,i(function(){f.resolveWith(r,[i])});else{n.jsDefer=n.$=i=function(n){return f.done(n)},i.extend=function(n,r){r===t&&(r=n,n=i);for(var u in r)n[u]=r[u];return n},i.extend({readyWait:1,ready:function(n){n===!0&&i.readyWait--,i.readyWait&&(n===!0||i.isReady)||f.resolveWith(r,[i])},isFunction:function(n){return typeof n=="function"},_Deferred:function(){var r=[],n,u,f,t={done:function(){if(!f){var s=arguments,e,h,u,o;for(n&&(o=n,n=0),e=0,h=s.length;e1?p.call(arguments,0):i,--e||t.resolveWith(t,p.call(r,0))}}var r=arguments,u=0,f=r.length,e=f,t=f<=1&&n&&i.isFunction(n.promise)?n:i.Deferred();if(f>1){for(;u