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.
- data/.gitignore +4 -4
- data/lib/middleman-wizard-template/template.rb +1 -0
- data/lib/middleman-wizard-template/template/README.tt +25 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/closurebuilder.py +256 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/depstree.py +189 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/depstree.pyc +0 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/depstree_test.py +127 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/depswriter.py +202 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/jscompiler.py +71 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/jscompiler.pyc +0 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/source.py +114 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/source.pyc +0 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/source_test.py +121 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/treescan.py +78 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/treescan.pyc +0 -0
- data/lib/middleman-wizard-template/template/config.tt +66 -0
- data/lib/middleman-wizard-template/template/shared/Gemfile.tt +2 -1
- data/lib/middleman-wizard-template/template/source/javascripts/app.js +3 -5
- data/lib/middleman-wizard-template/version.rb +1 -1
- metadata +21 -6
- data/lib/middleman-wizard-template/template/source/javascripts/_lib/asset_loader.js +0 -492
Binary file
|
@@ -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)
|
Binary file
|
@@ -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,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.
|
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.
|
5
|
-
prerelease:
|
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:
|
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:
|
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);
|