" +
15 | "
Bower components for the demo seem to be missing. Install them first:
" +
16 | "
" +
17 | "- Open a command prompt in the demo directory of the project.
" +
18 | "- Run
bower install " +
19 | "
" +
20 | "
If this is a false positive and the packages are in fact in place, " +
21 | "disable the check by removing bower-check.js at the top of the <body>.
" +
22 | "
";
23 |
24 | getJSON( "/demo/bower.json", false, function ( data ) {
25 |
26 | var i, j, depNames,
27 | exists = false,
28 | files = [
29 | 'bower.json', 'package.json',
30 | 'readme.md', 'Readme.md', 'README.md', 'README',
31 | 'license.txt', 'LICENSE.txt', 'LICENSE',
32 | 'Gruntfile.js',
33 | 'composer.json', 'component.json'
34 | ];
35 |
36 | if ( data && data.dependencies ) {
37 |
38 | depNames = Object.keys( data.dependencies );
39 |
40 | // Bower packages don't necessarily have a bower.json. file. The only file guaranteed to be there after
41 | // install is `.bower.json` (note the leading dot), but it is hidden and won't be served over http.
42 | //
43 | // So instead, we are looking for a bunch of files which are very likely to be there. If none of them is,
44 | // for none of the projects, the dependencies are most likely not installed.
45 | for ( i = 0; i < depNames.length; i++ ) {
46 | for ( j = 0; j < files.length; j++ ) {
47 |
48 | get(
49 | BOWER_DEMO_COMPONENTS_DIR + "/" + depNames[i] + "/" + files[j], false,
50 | function ( data ) {
51 | exists = !!data;
52 | }
53 | );
54 |
55 | if ( exists ) return;
56 |
57 | }
58 | }
59 |
60 | window.document.write( msg );
61 | }
62 |
63 | } );
64 |
65 |
66 | // Helper functions in the absence of a library like jQuery (not loaded at this point)
67 | function get ( url, async, cb, cbError ) {
68 | var data,
69 | request = new XMLHttpRequest;
70 |
71 | request.open( 'GET', url, async );
72 |
73 | request.onload = function () {
74 | if ( this.status >= 200 && this.status < 400 ) {
75 | // Success!
76 | data = this.response;
77 | } else {
78 | // We reached our target server, but it returned an error. Most likely, the bower.json file is missing.
79 | // We just return undefined here.
80 | data = undefined;
81 | }
82 | cb( data );
83 | };
84 |
85 | request.onerror = function ( err ) {
86 | // There was a connection error of some sort.
87 | if ( cbError ) cbError( err );
88 | };
89 |
90 | request.send();
91 | }
92 |
93 | function getJSON ( url, async, cb, cbError ) {
94 | get( url, async, function ( data ) {
95 |
96 | if ( data ) data = JSON.parse( data );
97 | cb( data );
98 |
99 | }, cbError );
100 | }
101 |
102 | }( window ));
--------------------------------------------------------------------------------
/demo/amd/require-config.js:
--------------------------------------------------------------------------------
1 | requirejs.config( {
2 |
3 | baseUrl: '../../',
4 |
5 | paths: {
6 | "jquery-legacy-v1": "bower_components/jquery-legacy-v1/dist/jquery",
7 | "jquery-legacy-v2": "bower_components/jquery-legacy-v2/dist/jquery",
8 | "jquery-modern": "bower_components/jquery/dist/jquery",
9 |
10 | "underscore": "bower_components/underscore/underscore",
11 | "backbone": "bower_components/backbone/backbone",
12 | "backbone.radio": "bower_components/backbone.radio/build/backbone.radio",
13 | "marionette-modern": "bower_components/marionette/lib/backbone.marionette",
14 | "marionette-legacy": "bower_components/marionette-legacy/lib/backbone.marionette",
15 |
16 | "handlebars-modern": "bower_components/handlebars/handlebars",
17 | "handlebars-legacy-v2": "bower_components/handlebars-legacy-v2/handlebars",
18 | "handlebars-legacy-v3": "bower_components/handlebars-legacy-v3/handlebars",
19 |
20 | "backbone.declarative.views": "demo/bower_demo_components/backbone.declarative.views/dist/backbone.declarative.views",
21 | "marionette.handlebars": "dist/marionette.handlebars",
22 |
23 | // Pulling in precompiled templates. The templates are compiled with the '--amd' switch, e.g. with
24 | //
25 | // handlebars --amd precompiled.handlebars -f precompiled.js
26 | //
27 | // A potential gotcha when compiling: If the file extension is `.handlebars`, the extension is dropped from the
28 | // template ID in the Handlebars cache (foo.bar.handlebars becomes "foo.bar"). That does _not_ happen if the
29 | // extension is `.hbs`: foo.bar.hbs becomes "foo.bar.hbs".
30 | //
31 | // For more on using precompiled templates, see http://goo.gl/rgNG2Y
32 | //
33 | // ATTN:
34 | //
35 | // Only the templates defined here, which are loaded by Require.js, are compiled with the '--amd' switch.
36 | // Compiled templates which are lazy-loaded later on, by the client code in main.js, must be compiled without it!
37 | //
38 | // A lazy loader implementation for Marionette.Handlebars must be synchronous. Hence, A(synchronous)MD does not
39 | // work for it. Granted, the template code could still be injected synchronously, with a synchronous AJAX call
40 | // (ok so far). But the actual template would be wrapped in a `define` function, which executes async - too late
41 | // for the loader.
42 | //
43 | // Compiling them without the '--amd' switch gets rid of the `define` wrapper. But it creates another problem:
44 | // Now the templates depend on a `Handlebars` global. Because Handlebars is loaded by Require.js, that global is
45 | // missing. The client code (in main.js) must expose Handlebars before compiled templates are lazy-loaded. A
46 | // simple `window.Handlebars = Handlebars;` statement does the trick.
47 |
48 | "precompiled.templates-legacy": "demo/amd/templates/precompiled/legacy/amd/precompiled",
49 | "precompiled.templates-modern": "demo/amd/templates/precompiled/modern/amd/precompiled",
50 |
51 | "local.main": "demo/amd/main"
52 | },
53 |
54 | map: {
55 | "*": {
56 | // Picking the versions of jQuery and Marionette.
57 | "jquery": "jquery-modern",
58 | "marionette": "marionette-modern",
59 |
60 | // Picking the Handlebars version. ATTN:
61 | // - The handlebars.runtime mapping, below, must point to the same version.
62 | // - The templates mapping, also below, must be changed accordingly, too.
63 | "handlebars": "handlebars-modern",
64 |
65 | // Templates precompiled with the --amd switch require 'handlebars.runtime' rather than 'handlebars'. As we
66 | // don't use the runtime here, we need to map 'handlebars' to a 'handlebars.runtime' alias.
67 | "handlebars.runtime": "handlebars-modern",
68 |
69 | // Legacy templates, "precompiled.templates-legacy", work for Handlebars <=3. For Handlebars 4, map to
70 | // "precompiled.templates-modern".
71 | "precompiled.templates": "precompiled.templates-modern"
72 | }
73 | },
74 |
75 | shim: {
76 | "jquery-legacy-v1": {
77 | exports: "jQuery"
78 | },
79 | "jquery-legacy-v2": {
80 | exports: "jQuery"
81 | },
82 | "jquery-modern": {
83 | exports: "jQuery"
84 | },
85 | "handlebars-legacy-v2": {
86 | exports: "Handlebars"
87 | },
88 | "handlebars-legacy-v3": {
89 | exports: "Handlebars"
90 | },
91 | "handlebars-modern": {
92 | exports: "Handlebars"
93 | },
94 |
95 | "marionette": ["backbone.declarative.views"]
96 | }
97 |
98 | } );
99 |
--------------------------------------------------------------------------------
/demo/amd/main.js:
--------------------------------------------------------------------------------
1 | // main.js
2 |
3 | require( [
4 |
5 | 'jquery',
6 | 'underscore',
7 | 'backbone',
8 | 'handlebars',
9 | 'marionette',
10 | 'backbone.declarative.views',
11 | 'precompiled.templates',
12 | 'marionette.handlebars'
13 |
14 | ], function ( $, _, Backbone, Handlebars ) {
15 |
16 | var domView, precompiledView, lazyLoadedView, lazyLoadedPrecompiledView,
17 |
18 | Marionette = Backbone.Marionette,
19 | $container = $( ".content" ),
20 |
21 | MarionetteView = Marionette.ItemView || Marionette.View,
22 | BaseView = MarionetteView.extend( {
23 | tagName: "p"
24 | } );
25 |
26 | // Allow lazy loading of compiled templates
27 | Backbone.Marionette.TemplateCache.allowCompiledTemplatesOverHttp = true;
28 |
29 | // Expose Handlebars as a browser global. Makes lazy-loading of *compiled* templates possible.
30 | //
31 | // See explanation in require-config.js. By contrast, raw HTML templates (ie strings, not code) can be lazy-loaded
32 | // without a global.
33 | window.Handlebars = Handlebars;
34 |
35 | // Implement a lazy template loader.
36 | _.extend( Backbone.Marionette.TemplateCache.prototype, {
37 |
38 | isPrecompiled: function ( templateId ) {
39 | return templateId.substr( -3 ) === ".js";
40 | },
41 |
42 | getTemplateUrl: function ( templateId, options ) {
43 | var isPrecompiled = this.isPrecompiled( templateId ),
44 | versionInfix = isLegacyHandlebars() ? "legacy" : "modern",
45 | prefix = isPrecompiled ? "templates/precompiled/" + versionInfix + "/non-amd/" : "templates/raw/",
46 | suffix = isPrecompiled ? "" : ".hbs";
47 |
48 | return prefix + templateId + suffix;
49 | },
50 |
51 | lazyLoadTemplate: function ( templateId, options ) {
52 | var templateHtml, compiledTemplate,
53 | isPrecompiled = this.isPrecompiled( templateId ),
54 | templateUrl = this.getTemplateUrl( templateId, options );
55 |
56 | if ( isPrecompiled ) {
57 |
58 | this.loadResource( { url: templateUrl, isJavascript: true } );
59 |
60 | // The $.ajax call returns a precompiled template as a string, not as Javascript code. We simply throw
61 | // the string away.
62 | //
63 | // But the code has also been executed, which means that it has been added to the Handlebars cache. We
64 | // must read it from the cache now.
65 | //
66 | // Our template IDs for precompiled templates end in ".js" because we needed to fetch the actual files.
67 | // In the Handlebars cache, the ".js" file extension not part of the ID. We need to remove it before
68 | // querying the cache.
69 | templateId = templateId.slice( 0, -3 );
70 | compiledTemplate = this.getPrecompiledTemplate( templateId );
71 |
72 | } else {
73 |
74 | // Loading a raw HTML template (ie, a string).
75 | templateHtml = this.loadResource( { url: templateUrl, isJavascript: false } );
76 |
77 | }
78 |
79 | return templateHtml || compiledTemplate;
80 | },
81 |
82 | loadResource: function ( config ) {
83 | var content;
84 |
85 | Backbone.$.ajax( {
86 | url: config.url,
87 | success: function ( data ) { content = data; },
88 |
89 | async: false,
90 | cache: true,
91 | dataType: config.isJavascript ? "script" : "text"
92 | } );
93 |
94 | return content;
95 | }
96 |
97 | } );
98 |
99 | // Load templates in various ways
100 |
101 | // Load a template from the DOM.
102 | //
103 | // The el is defined by the template in this case, using Backbone.Declarative.Views. Hence, we use a plain ItemView
104 | // (or View, in Marionette 3), rather than the local BaseView which also defines the el.
105 | domView = new MarionetteView( {
106 | model: new Backbone.Model( { origin: "DOM-based" } ),
107 | template: "#dom-template"
108 | } );
109 |
110 | // Load a precompiled template
111 | precompiledView = new BaseView( {
112 | model: new Backbone.Model( { origin: "precompiled" } ),
113 | template: "precompiled"
114 | } );
115 |
116 | // Lazy-load a template
117 | lazyLoadedView= new BaseView( {
118 | model: new Backbone.Model( { origin: "lazy-loaded" } ),
119 | template: "lazy-loaded"
120 | } );
121 |
122 | // Lazy-load a template asynchronously
123 | createViewWithAsyncTemplate( {
124 | ViewClass: BaseView,
125 | model: new Backbone.Model( { origin: "lazy-loaded" } ),
126 | templateId: "lazy-loaded-async"
127 | } );
128 |
129 | // Lazy-load a precompiled template
130 | lazyLoadedPrecompiledView = new BaseView( {
131 | model: new Backbone.Model( { origin: "lazy-loaded" } ),
132 | template: "lazy-loaded-precompiled.js"
133 | } );
134 |
135 | // Lazy-load a precompiled template async
136 | createViewWithAsyncTemplate( {
137 | ViewClass: BaseView,
138 | model: new Backbone.Model( { origin: "lazy-loaded" } ),
139 | templateId: "lazy-loaded-precompiled-async.js"
140 | } );
141 |
142 | // Show the synchronous views (the async ones have been handled inside createViewWithAsyncTemplate()).
143 | addHeadline( "Preloaded" );
144 | show( domView );
145 | show( precompiledView );
146 | addHeadline( "Lazy-loaded" );
147 | show( lazyLoadedView );
148 | show( lazyLoadedPrecompiledView );
149 | addHeadline( "Async lazy-loaded" );
150 |
151 | function addHeadline ( text ) {
152 | $( "