middleman-wizard-template 1.0.0.pre.1 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (21) hide show
  1. data/.gitignore +4 -4
  2. data/lib/middleman-wizard-template/template.rb +1 -0
  3. data/lib/middleman-wizard-template/template/README.tt +25 -0
  4. data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/closurebuilder.py +256 -0
  5. data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/depstree.py +189 -0
  6. data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/depstree.pyc +0 -0
  7. data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/depstree_test.py +127 -0
  8. data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/depswriter.py +202 -0
  9. data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/jscompiler.py +71 -0
  10. data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/jscompiler.pyc +0 -0
  11. data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/source.py +114 -0
  12. data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/source.pyc +0 -0
  13. data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/source_test.py +121 -0
  14. data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/treescan.py +78 -0
  15. data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/treescan.pyc +0 -0
  16. data/lib/middleman-wizard-template/template/config.tt +66 -0
  17. data/lib/middleman-wizard-template/template/shared/Gemfile.tt +2 -1
  18. data/lib/middleman-wizard-template/template/source/javascripts/app.js +3 -5
  19. data/lib/middleman-wizard-template/version.rb +1 -1
  20. metadata +21 -6
  21. data/lib/middleman-wizard-template/template/source/javascripts/_lib/asset_loader.js +0 -492
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env python
2
+ #
3
+ # Copyright 2010 The Closure Library Authors. All Rights Reserved.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS-IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+
18
+ """Unit test for source."""
19
+
20
+ __author__ = 'nnaze@google.com (Nathan Naze)'
21
+
22
+
23
+ import unittest
24
+
25
+ import source
26
+
27
+
28
+ class SourceTestCase(unittest.TestCase):
29
+ """Unit test for source. Tests the parser on a known source input."""
30
+
31
+ def testSourceScan(self):
32
+ test_source = source.Source(_TEST_SOURCE)
33
+
34
+ self.assertEqual(set(['foo', 'foo.test']),
35
+ test_source.provides)
36
+ self.assertEqual(set(['goog.dom', 'goog.events.EventType']),
37
+ test_source.requires)
38
+
39
+ def testSourceScanBase(self):
40
+ test_source = source.Source(_TEST_BASE_SOURCE)
41
+
42
+ self.assertEqual(set(['goog']),
43
+ test_source.provides)
44
+ self.assertEqual(test_source.requires, set())
45
+
46
+ def testSourceScanBadBase(self):
47
+
48
+ def MakeSource():
49
+ source.Source(_TEST_BAD_BASE_SOURCE)
50
+
51
+ self.assertRaises(Exception, MakeSource)
52
+
53
+ def testStripComments(self):
54
+ self.assertEquals(
55
+ '\nvar foo = function() {}',
56
+ source.Source._StripComments((
57
+ '/* This is\n'
58
+ ' a comment split\n'
59
+ ' over multiple lines\n'
60
+ '*/\n'
61
+ 'var foo = function() {}')))
62
+
63
+ def testGoogStatementsInComments(self):
64
+ test_source = source.Source(_TEST_COMMENT_SOURCE)
65
+
66
+ self.assertEqual(set(['foo']),
67
+ test_source.provides)
68
+ self.assertEqual(set(['goog.events.EventType']),
69
+ test_source.requires)
70
+
71
+
72
+ _TEST_SOURCE = """// Fake copyright notice
73
+
74
+ /** Very important comment. */
75
+
76
+ goog.provide('foo');
77
+ goog.provide('foo.test');
78
+
79
+ goog.require('goog.dom');
80
+ goog.require('goog.events.EventType');
81
+
82
+ function foo() {
83
+ // Set bar to seventeen to increase performance.
84
+ this.bar = 17;
85
+ }
86
+ """
87
+
88
+ _TEST_COMMENT_SOURCE = """// Fake copyright notice
89
+
90
+ goog.provide('foo');
91
+
92
+ /*
93
+ goog.provide('foo.test');
94
+ */
95
+
96
+ /*
97
+ goog.require('goog.dom');
98
+ */
99
+
100
+ // goog.require('goog.dom');
101
+
102
+ goog.require('goog.events.EventType');
103
+
104
+ function bar() {
105
+ this.baz = 55;
106
+ }
107
+ """
108
+
109
+ _TEST_BASE_SOURCE = """
110
+ var goog = goog || {}; // Identifies this file as the Closure base.
111
+ """
112
+
113
+ _TEST_BAD_BASE_SOURCE = """
114
+ goog.provide('goog');
115
+
116
+ var goog = goog || {}; // Identifies this file as the Closure base.
117
+ """
118
+
119
+
120
+ if __name__ == '__main__':
121
+ unittest.main()
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env python
2
+ #
3
+ # Copyright 2010 The Closure Library Authors. All Rights Reserved.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS-IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+
18
+ """Shared utility functions for scanning directory trees."""
19
+
20
+ import os
21
+ import re
22
+
23
+
24
+ __author__ = 'nnaze@google.com (Nathan Naze)'
25
+
26
+
27
+ # Matches a .js file path.
28
+ _JS_FILE_REGEX = re.compile(r'^.+\.js$')
29
+
30
+
31
+ def ScanTreeForJsFiles(root):
32
+ """Scans a directory tree for JavaScript files.
33
+
34
+ Args:
35
+ root: str, Path to a root directory.
36
+
37
+ Returns:
38
+ An iterable of paths to JS files, relative to cwd.
39
+ """
40
+ return ScanTree(root, path_filter=_JS_FILE_REGEX)
41
+
42
+
43
+ def ScanTree(root, path_filter=None, ignore_hidden=True):
44
+ """Scans a directory tree for files.
45
+
46
+ Args:
47
+ root: str, Path to a root directory.
48
+ path_filter: A regular expression filter. If set, only paths matching
49
+ the path_filter are returned.
50
+ ignore_hidden: If True, do not follow or return hidden directories or files
51
+ (those starting with a '.' character).
52
+
53
+ Yields:
54
+ A string path to files, relative to cwd.
55
+ """
56
+
57
+ def OnError(os_error):
58
+ raise os_error
59
+
60
+ for dirpath, dirnames, filenames in os.walk(root, onerror=OnError):
61
+ # os.walk allows us to modify dirnames to prevent decent into particular
62
+ # directories. Avoid hidden directories.
63
+ for dirname in dirnames:
64
+ if ignore_hidden and dirname.startswith('.'):
65
+ dirnames.remove(dirname)
66
+
67
+ for filename in filenames:
68
+
69
+ # nothing that starts with '.'
70
+ if ignore_hidden and filename.startswith('.'):
71
+ continue
72
+
73
+ fullpath = os.path.join(dirpath, filename)
74
+
75
+ if path_filter and not path_filter.match(fullpath):
76
+ continue
77
+
78
+ yield os.path.normpath(fullpath)
@@ -0,0 +1,66 @@
1
+ use Rack::Static, :urls => ["/closure"]
2
+
3
+ set :haml, :attr_wrapper => '"'
4
+
5
+ ready do
6
+ ::Sprockets.unregister_postprocessor 'application/javascript', ::Sprockets::SafetyColons
7
+ end
8
+
9
+ # Preview Server
10
+ configure :development do
11
+ activate :relative_assets
12
+ end
13
+
14
+ # Closure Compiler Testing
15
+ configure :build do
16
+ after_build do |builder|
17
+ builder.say "Linting"
18
+ system %Q{gjslint -r source/javascripts/ --exclude_files="source/javascripts/modernizr.js"}
19
+
20
+ # Create Goro-ready css file
21
+ orig_css = File.read("build/stylesheets/site.css")
22
+ orig_css.gsub!(%Q{@charset "UTF-8";}, "")
23
+ builder.create_file "build/stylesheets/site.css" do
24
+ orig_css
25
+ end
26
+ end
27
+
28
+ # Goro deploy
29
+ if ENV['GORO']
30
+ set :layout, false
31
+ # set :http_prefix, "../../"
32
+
33
+ compass_config do |compass|
34
+ compass.line_comments = false
35
+ end
36
+
37
+ after_build do |builder|
38
+ builder.say "Optimizing Images (may take a while)"
39
+ image_optim = ImageOptim.new(:pngout => false)
40
+ image_optim.optimize_images!(Dir['build/images/**/*.*']) do |unoptimized, optimized|
41
+ puts unoptimized
42
+ end
43
+ end
44
+ else
45
+ activate :relative_assets
46
+
47
+ compass_config do |compass|
48
+ compass.line_comments = false
49
+ end
50
+
51
+ after_build do |builder|
52
+ builder.say "Compiling to a single file"
53
+ builder.create_file "build/javascripts/app.min.js" do
54
+ `closure/library/closure/bin/build/closurebuilder.py --root=closure/library/ --root=build/javascripts/ --namespace="site_name" --output_mode=compiled --compiler_flags="--debug=true" --compiler_jar=closure/compiler/compiler.jar --compiler_flags="--compilation_level=ADVANCED_OPTIMIZATIONS"`
55
+ end
56
+
57
+ orig_file = File.read("build/index.html")
58
+
59
+ # Remove goog.base
60
+ orig_file.gsub!(%Q{<script src="/closure/library/closure/goog/base.js"></script>}, "")
61
+ builder.create_file "build/index.html" do
62
+ orig_file
63
+ end
64
+ end
65
+ end
66
+ end
@@ -1,3 +1,4 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem "middleman", "~> <%= Middleman::VERSION %>"
3
+ gem "middleman", "~> <%= Middleman::VERSION %>"
4
+ gem "image_optim"
@@ -1,20 +1,18 @@
1
1
  //= require "_lib/util"
2
- //= require "_lib/asset_loader"
3
2
  //= require "_lib/raf"
4
3
  //= require "_lib/Transform"
5
4
  //= require "_lib/Tween"
6
- //= require "_lib/router"
7
5
 
8
6
  goog.provide('site_name');
9
- goog.require('goog.History');
7
+ // goog.require('goog.History');
10
8
  goog.require('goog.dom');
11
9
  goog.require('goog.dom.classes');
12
10
  goog.require('goog.dom.dataset');
13
11
  goog.require('goog.dom.query');
14
12
  goog.require('goog.events');
15
- goog.require('goog.net.XhrIo');
13
+ // goog.require('goog.net.XhrIo');
16
14
  goog.require('goog.style');
17
- goog.require('goog.userAgent');
15
+ // goog.require('goog.userAgent');
18
16
 
19
17
  /**
20
18
  * Initialize the app.
@@ -1,5 +1,5 @@
1
1
  module Middleman
2
2
  module WizardTemplate
3
- VERSION = "1.0.0.pre.1"
3
+ VERSION = "1.0.1"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,8 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: middleman-wizard-template
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre.1
5
- prerelease: 6
4
+ version: 1.0.1
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Thomas Reynolds
@@ -41,11 +41,24 @@ files:
41
41
  - Rakefile
42
42
  - lib/middleman-wizard-template.rb
43
43
  - lib/middleman-wizard-template/template.rb
44
+ - lib/middleman-wizard-template/template/README.tt
44
45
  - lib/middleman-wizard-template/template/closure/compiler/COPYING
45
46
  - lib/middleman-wizard-template/template/closure/compiler/README
46
47
  - lib/middleman-wizard-template/template/closure/compiler/compiler.jar
47
48
  - lib/middleman-wizard-template/template/closure/library/all_tests.html
48
49
  - lib/middleman-wizard-template/template/closure/library/alltests.js
50
+ - lib/middleman-wizard-template/template/closure/library/closure/bin/build/closurebuilder.py
51
+ - lib/middleman-wizard-template/template/closure/library/closure/bin/build/depstree.py
52
+ - lib/middleman-wizard-template/template/closure/library/closure/bin/build/depstree.pyc
53
+ - lib/middleman-wizard-template/template/closure/library/closure/bin/build/depstree_test.py
54
+ - lib/middleman-wizard-template/template/closure/library/closure/bin/build/depswriter.py
55
+ - lib/middleman-wizard-template/template/closure/library/closure/bin/build/jscompiler.py
56
+ - lib/middleman-wizard-template/template/closure/library/closure/bin/build/jscompiler.pyc
57
+ - lib/middleman-wizard-template/template/closure/library/closure/bin/build/source.py
58
+ - lib/middleman-wizard-template/template/closure/library/closure/bin/build/source.pyc
59
+ - lib/middleman-wizard-template/template/closure/library/closure/bin/build/source_test.py
60
+ - lib/middleman-wizard-template/template/closure/library/closure/bin/build/treescan.py
61
+ - lib/middleman-wizard-template/template/closure/library/closure/bin/build/treescan.pyc
49
62
  - lib/middleman-wizard-template/template/closure/library/closure/bin/calcdeps.py
50
63
  - lib/middleman-wizard-template/template/closure/library/closure/bin/scopify.py
51
64
  - lib/middleman-wizard-template/template/closure/library/closure/css/inlay/g-base.css
@@ -1763,7 +1776,6 @@ files:
1763
1776
  - lib/middleman-wizard-template/template/source/index.html.erb
1764
1777
  - lib/middleman-wizard-template/template/source/javascripts/_lib/Transform.js
1765
1778
  - lib/middleman-wizard-template/template/source/javascripts/_lib/Tween.js
1766
- - lib/middleman-wizard-template/template/source/javascripts/_lib/asset_loader.js
1767
1779
  - lib/middleman-wizard-template/template/source/javascripts/_lib/raf.js
1768
1780
  - lib/middleman-wizard-template/template/source/javascripts/_lib/router.js
1769
1781
  - lib/middleman-wizard-template/template/source/javascripts/_lib/util.js
@@ -1788,13 +1800,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
1788
1800
  version: '0'
1789
1801
  segments:
1790
1802
  - 0
1791
- hash: -4398009891192626344
1803
+ hash: 282265817994922857
1792
1804
  required_rubygems_version: !ruby/object:Gem::Requirement
1793
1805
  none: false
1794
1806
  requirements:
1795
- - - ! '>'
1807
+ - - ! '>='
1796
1808
  - !ruby/object:Gem::Version
1797
- version: 1.3.1
1809
+ version: '0'
1810
+ segments:
1811
+ - 0
1812
+ hash: 282265817994922857
1798
1813
  requirements: []
1799
1814
  rubyforge_project: middleman-wizard-template
1800
1815
  rubygems_version: 1.8.23
@@ -1,492 +0,0 @@
1
- /**
2
- * Loads resources while providing progress updates.
3
- * @constructor
4
- * @param {Object} settings Config vars.
5
- */
6
- ww.Loader = function Loader(settings) {
7
-
8
- // merge settings with defaults
9
- settings = settings || {};
10
-
11
- // how frequently we poll resources for progress
12
- if (settings.statusInterval == null) {
13
- settings.statusInterval = 5000; // every 5 seconds by default
14
- }
15
-
16
- // delay before logging since last progress change
17
- if (settings.loggingDelay == null) {
18
- settings.loggingDelay = 20 * 1000; // log stragglers after 20 secs
19
- }
20
-
21
- // stop waiting if no progress has been made in the moving time window
22
- if (settings.noProgressTimeout == null) {
23
- settings.noProgressTimeout = Infinity; // do not stop waiting by default
24
- }
25
-
26
- var entries = [],
27
- // holds resources to be loaded with their status
28
- progressListeners = [],
29
- timeStarted, progressChanged = +new Date();
30
-
31
- /**
32
- * The status of a resource
33
- * @enum {number}
34
- */
35
- var ResourceState = {
36
- QUEUED: 0,
37
- WAITING: 1,
38
- LOADED: 2,
39
- ERROR: 3,
40
- TIMEOUT: 4
41
- };
42
-
43
- // places non-array values into an array.
44
- var ensureArray = function(val) {
45
- if (val == null) {
46
- return [];
47
- }
48
-
49
- if (Array.isArray(val)) {
50
- return val;
51
- }
52
-
53
- return [val];
54
- };
55
-
56
- // add an entry to the list of resources to be loaded
57
- this.add = function(resource) {
58
-
59
- // ensure tags are in an object
60
- resource.tags = new ww.LoaderTags(resource.tags);
61
-
62
- // ensure priority is set
63
- if (resource.priority == null) {
64
- resource.priority = Infinity;
65
- }
66
-
67
- entries.push({
68
- resource: resource,
69
- status: ResourceState.QUEUED
70
- });
71
- };
72
-
73
- this.addProgressListener = function(callback, tags) {
74
- progressListeners.push({
75
- callback: callback,
76
- tags: new ww.LoaderTags(tags)
77
- });
78
- };
79
-
80
- this.addCompletionListener = function(callback, tags) {
81
- progressListeners.push({
82
- tags: new ww.LoaderTags(tags),
83
- callback: function(e) {
84
- if (e.completedCount === e.totalCount) {
85
- callback();
86
- }
87
- }
88
- });
89
- };
90
-
91
- // creates a comparison function for resources
92
- var getResourceSort = function(orderedTags) {
93
-
94
- // helper to get the top tag's order for a resource
95
- orderedTags = ensureArray(orderedTags);
96
- var getTagOrder = function(entry) {
97
- var resource = entry.resource,
98
- bestIndex = Infinity;
99
- for (var i = 0; i < resource.tags.length; i++) {
100
- for (var j = 0; j < Math.min(orderedTags.length, bestIndex); j++) {
101
- if (resource.tags[i] == orderedTags[j] && j < bestIndex) {
102
- bestIndex = j;
103
- if (bestIndex === 0) break;
104
- }
105
- if (bestIndex === 0) break;
106
- }
107
- }
108
- return bestIndex;
109
- };
110
- return function(a, b) {
111
- // check tag order first
112
- var aOrder = getTagOrder(a),
113
- bOrder = getTagOrder(b);
114
- if (aOrder < bOrder) return -1;
115
- if (aOrder > bOrder) return 1;
116
-
117
- // now check priority
118
- if (a.priority < b.priority) return -1;
119
- if (a.priority > b.priority) return 1;
120
- return 0;
121
- }
122
- };
123
-
124
- this.start = function(orderedTags) {
125
- timeStarted = +new Date;
126
-
127
- // first order the resources
128
- var compareResources = getResourceSort(orderedTags);
129
- entries.sort(compareResources);
130
-
131
- // trigger requests for each resource
132
- for (var i = 0, len = entries.length; i < len; i++) {
133
- var entry = entries[i];
134
- entry.status = ResourceState.WAITING;
135
- entry.resource.start(this);
136
- }
137
-
138
- // do an initial status check soon since items may be loaded from the cache
139
- setTimeout(statusCheck, 100);
140
- };
141
-
142
- var statusCheck = function() {
143
- var checkAgain = false,
144
- noProgressTime = (+new Date()) - progressChanged,
145
- timedOut = (noProgressTime >= settings.noProgressTimeout),
146
- shouldLog = (noProgressTime >= settings.loggingDelay);
147
-
148
- for (var i = 0, len = entries.length; i < len; i++) {
149
- var entry = entries[i];
150
- if (entry.status !== ResourceState.WAITING) {
151
- continue;
152
- }
153
-
154
- // see if the resource has loaded
155
- if (entry.resource.checkStatus) {
156
- entry.resource.checkStatus();
157
- }
158
-
159
- // if still waiting, mark as timed out or make sure we check again
160
- if (entry.status === ResourceState.WAITING) {
161
- if (timedOut) {
162
- entry.resource.onTimeout();
163
- } else {
164
- checkAgain = true;
165
- }
166
- }
167
- }
168
-
169
- // log any resources that are still pending
170
- if (shouldLog && checkAgain) {
171
- log();
172
- }
173
-
174
- if (checkAgain) {
175
- setTimeout(statusCheck, settings.statusInterval);
176
- }
177
- };
178
-
179
- this.isBusy = function() {
180
- for (var i = 0, len = entries.length; i < len; i++) {
181
- if ((entries[i].status === ResourceState.QUEUED) ||
182
- (entries[i].status === ResourceState.WAITING)) {
183
- return true;
184
- }
185
- }
186
- return false;
187
- };
188
-
189
- var onProgress = function(resource, statusType) {
190
- // find the entry for the resource
191
- var entry = null;
192
- for (var i = 0, len = entries.length; i < len; i++) {
193
- if (entries[i].resource === resource) {
194
- entry = entries[i];
195
- break;
196
- }
197
- }
198
-
199
- // we have already updated the status of the resource
200
- if (entry == null || entry.status !== ResourceState.WAITING) {
201
- return;
202
- }
203
- entry.status = statusType;
204
- progressChanged = +new Date();
205
-
206
- var numResourceTags = resource.tags.length;
207
-
208
- // fire callbacks for interested listeners
209
- var numListeners = progressListeners.length;
210
- for (var i = 0; i < numListeners; i++) {
211
- var listener = progressListeners[i],
212
- shouldCall;
213
-
214
- if (listener.tags.length === 0) {
215
- // no tags specified so always tell the listener
216
- shouldCall = true;
217
- } else {
218
- // listener only wants to hear about certain tags
219
- shouldCall = resource.tags.contains(listener.tags);
220
- }
221
-
222
- if (shouldCall) {
223
- sendProgress(entry, listener);
224
- }
225
- }
226
- };
227
-
228
- this.onLoad = function(resource) {
229
- onProgress(resource, ResourceState.LOADED);
230
- };
231
- this.onError = function(resource) {
232
- onProgress(resource, ResourceState.ERROR);
233
- };
234
- this.onTimeout = function(resource) {
235
- onProgress(resource, ResourceState.TIMEOUT);
236
- };
237
-
238
- // sends a progress report to a listener
239
- var sendProgress = function(updatedEntry, listener) {
240
- // find stats for all the resources the caller is interested in
241
- var completed = 0,
242
- total = 0;
243
- for (var i = 0, len = entries.length; i < len; i++) {
244
- var entry = entries[i],
245
- includeResource = false;
246
-
247
- if (listener.tags.length === 0) {
248
- // no tags specified so always tell the listener
249
- includeResource = true;
250
- } else {
251
- includeResource = entry.resource.tags.contains(listener.tags);
252
- }
253
-
254
- if (includeResource) {
255
- total++;
256
- if ((entry.status === ResourceState.LOADED) ||
257
- (entry.status === ResourceState.ERROR) ||
258
- (entry.status === ResourceState.TIMEOUT)) {
259
- completed++;
260
- }
261
- }
262
- }
263
-
264
- listener.callback({
265
- // info about the resource that changed
266
- resource: updatedEntry.resource,
267
-
268
- // should we expose StatusType instead?
269
- loaded: (updatedEntry.status === ResourceState.LOADED),
270
- error: (updatedEntry.status === ResourceState.ERROR),
271
- timeout: (updatedEntry.status === ResourceState.TIMEOUT),
272
-
273
- // updated stats for all resources
274
- completedCount: completed,
275
- totalCount: total
276
- });
277
- };
278
-
279
- // prints the status of each resource to the console
280
- var log = this.log = function(showAll) {
281
- if (!window.console) {
282
- return;
283
- }
284
-
285
- var elapsedSeconds = Math.round((+new Date() - timeStarted) / 1000);
286
- window.console.log('ww.Loader elapsed: ' + elapsedSeconds + ' sec');
287
-
288
- for (var i = 0, len = entries.length; i < len; i++) {
289
- var entry = entries[i];
290
- if (!showAll && entry.status !== ResourceState.WAITING) {
291
- continue;
292
- }
293
-
294
- var message = 'ww.Loader: #' + i + ' ' + entry.resource.getName();
295
- switch (entry.status) {
296
- case ResourceState.QUEUED:
297
- message += ' (Not Started)';
298
- break;
299
- case ResourceState.WAITING:
300
- message += ' (Waiting)';
301
- break;
302
- case ResourceState.LOADED:
303
- message += ' (Loaded)';
304
- break;
305
- case ResourceState.ERROR:
306
- message += ' (Error)';
307
- break;
308
- case ResourceState.TIMEOUT:
309
- message += ' (Timeout)';
310
- break;
311
- }
312
-
313
- if (entry.resource.tags.length > 0) {
314
- message += ' Tags: [' + entry.resource.tags.join(',') + ']';
315
- }
316
-
317
- window.console.log(message);
318
- }
319
- };
320
- };
321
-
322
- goog.exportSymbol('ww.Loader', ww.Loader);
323
-
324
- // Tag object to handle tag intersection; once created not meant to be changed
325
- // Performance rationale: http://jsperf.com/lists-indexof-vs-in-operator/3
326
- /**
327
- * Tags.
328
- * @constructor
329
- * @param {Object} values Tag values.
330
- */
331
- ww.LoaderTags = function LoaderTags(values) {
332
-
333
- this.array = [];
334
- this.object = {};
335
- this.value = null; // single value
336
- this.length = 0;
337
-
338
- if (values !== null && values !== undefined) {
339
- if (Array.isArray(values)) {
340
- this.array = values;
341
- } else if (typeof values === 'object') {
342
- for (var key in values) {
343
- this.array.push(key);
344
- }
345
- } else {
346
- this.array.push(values);
347
- this.value = values;
348
- }
349
-
350
- this.length = this.array.length;
351
-
352
- // convert array values to object with truthy values, used by contains
353
- // function below
354
- for (var i = 0; i < this.length; i++) {
355
- this.object[this.array[i]] = true;
356
- }
357
- }
358
-
359
- // compare this object with another; return true if they share at least
360
- // one value
361
- this.contains = function(other) {
362
- if (this.length === 0 || other.length === 0) {
363
- return false;
364
- } else if (this.length === 1 && this.value !== null) {
365
- if (other.length === 1) {
366
- return this.value === other.value;
367
- } else {
368
- return other.object.hasOwnProperty(this.value);
369
- }
370
- } else if (other.length < this.length) {
371
- return other.contains(this); // better to loop through the smaller object
372
- } else {
373
- for (var key in this.object) {
374
- if (other.object[key]) {
375
- return true;
376
- }
377
- }
378
- return false;
379
- }
380
- };
381
- };
382
-
383
- // shims to ensure we have newer Array utility methods
384
- if (!Array.isArray) {
385
- /**
386
- * Polyfill for isArray
387
- * @param {Array} arg The array.
388
- * @return {Boolean} Whether it is an array.
389
- */
390
- Array.isArray = function(arg) {
391
- return Object.prototype.toString.call(arg) == '[object Array]';
392
- };
393
- }
394
-
395
- goog.exportSymbol('ww.LoaderTags', ww.LoaderTags);
396
-
397
- /**
398
- * Loader plugin to load images.
399
- * @constructor
400
- * @param {String} url Url of the Swiffy.
401
- * @param {Array} tags Array of tag names.
402
- * @param {Number} priority Load order.
403
- */
404
- ww.LoaderImage = function LoaderImage(url, tags, priority) {
405
- var self = this,
406
- loader = null;
407
-
408
- this.img = new Image();
409
- this.tags = tags;
410
- this.priority = priority;
411
-
412
- var onReadyStateChange = function() {
413
- if (self.img.readyState == 'complete') {
414
- removeEventHandlers();
415
- loader.onLoad(self);
416
- }
417
- };
418
-
419
- var onLoad = function() {
420
- removeEventHandlers();
421
- loader.onLoad(self);
422
- };
423
-
424
- var onError = function() {
425
- removeEventHandlers();
426
- loader.onError(self);
427
- };
428
-
429
- var removeEventHandlers = function() {
430
- self.unbind('load', onLoad);
431
- self.unbind('readystatechange', onReadyStateChange);
432
- self.unbind('error', onError);
433
- };
434
-
435
- this.start = function(pxloader) {
436
- // we need the loader ref so we can notify upon completion
437
- loader = pxloader;
438
-
439
- // NOTE: Must add event listeners before the src is set. We
440
- // also need to use the readystatechange because sometimes
441
- // load doesn't fire when an image is in the cache.
442
- self.bind('load', onLoad);
443
- self.bind('readystatechange', onReadyStateChange);
444
- self.bind('error', onError);
445
-
446
- self.img.src = url;
447
- };
448
-
449
- // called by ww.Loader to check status of image (fallback in case
450
- // the event listeners are not triggered).
451
- this.checkStatus = function() {
452
- if (self.img.complete) {
453
- removeEventHandlers();
454
- loader.onLoad(self);
455
- }
456
- };
457
-
458
- // called by ww.Loader when it is no longer waiting
459
- this.onTimeout = function() {
460
- removeEventHandlers();
461
- if (self.img.complete) {
462
- loader.onLoad(self);
463
- } else {
464
- loader.onTimeout(self);
465
- }
466
- };
467
-
468
- // returns a name for the resource that can be used in logging
469
- this.getName = function() {
470
- return url;
471
- };
472
-
473
- // cross-browser event binding
474
- this.bind = function(eventName, eventHandler) {
475
- if (self.img.addEventListener) {
476
- self.img.addEventListener(eventName, eventHandler, false);
477
- } else if (self.img.attachEvent) {
478
- self.img.attachEvent('on' + eventName, eventHandler);
479
- }
480
- };
481
-
482
- // cross-browser event un-binding
483
- this.unbind = function(eventName, eventHandler) {
484
- if (self.img.removeEventListener) {
485
- self.img.removeEventListener(eventName, eventHandler, false);
486
- } else if (self.img.detachEvent) {
487
- self.img.detachEvent('on' + eventName, eventHandler);
488
- }
489
- };
490
- };
491
-
492
- goog.exportSymbol('ww.LoaderImage', ww.LoaderImage);