middleman-wizard-template 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (25) hide show
  1. checksums.yaml +7 -0
  2. data/lib/middleman-wizard-template/template/source/index.html.erb +1 -89
  3. data/lib/middleman-wizard-template/template/source/javascripts/_lib/ww/Matrix.js +449 -0
  4. data/lib/middleman-wizard-template/template/source/javascripts/_lib/ww/PxLoader/PxLoader.js +395 -0
  5. data/lib/middleman-wizard-template/template/source/javascripts/_lib/ww/PxLoader/PxLoaderImage.js +96 -0
  6. data/lib/middleman-wizard-template/template/source/javascripts/_lib/ww/PxLoader/PxLoaderSwiffy.js +68 -0
  7. data/lib/middleman-wizard-template/template/source/javascripts/_lib/ww/RouteRecognizer.js +506 -0
  8. data/lib/middleman-wizard-template/template/source/javascripts/_lib/ww/Slides.js +846 -0
  9. data/lib/middleman-wizard-template/template/source/javascripts/_lib/ww/Transform.js +312 -0
  10. data/lib/middleman-wizard-template/template/source/javascripts/_lib/{Tween.js → ww/Tween.js} +26 -11
  11. data/lib/middleman-wizard-template/template/source/javascripts/_lib/ww/base.js +8 -0
  12. data/lib/middleman-wizard-template/template/source/javascripts/_lib/ww/raf.js +131 -0
  13. data/lib/middleman-wizard-template/template/source/javascripts/_lib/ww/statemachine.js +1024 -0
  14. data/lib/middleman-wizard-template/template/source/javascripts/_lib/ww/useragent.js +1244 -0
  15. data/lib/middleman-wizard-template/template/source/javascripts/_lib/{util.js → ww/util.js} +48 -50
  16. data/lib/middleman-wizard-template/template/source/javascripts/_lib/ww/viewport.js +89 -0
  17. data/lib/middleman-wizard-template/template/source/javascripts/{app.js → site.js} +5 -5
  18. data/lib/middleman-wizard-template/template/source/layouts/layout.erb +85 -0
  19. data/lib/middleman-wizard-template/template/source/stylesheets/default.css +2 -1
  20. data/lib/middleman-wizard-template/template/source/stylesheets/site.css.scss +11 -3
  21. data/lib/middleman-wizard-template/version.rb +1 -1
  22. metadata +23 -23
  23. data/lib/middleman-wizard-template/template/source/javascripts/_lib/Transform.js +0 -401
  24. data/lib/middleman-wizard-template/template/source/javascripts/_lib/raf.js +0 -26
  25. data/lib/middleman-wizard-template/template/source/javascripts/_lib/router.js +0 -679
@@ -0,0 +1,395 @@
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);
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Loader plugin to load images.
3
+ * @constructor
4
+ * @param {String} url Url of the Swiffy.
5
+ * @param {Array} tags Array of tag names.
6
+ * @param {Number} priority Load order.
7
+ */
8
+ ww.LoaderImage = function LoaderImage(url, tags, priority) {
9
+ var self = this,
10
+ loader = null;
11
+
12
+ this.img = new Image();
13
+ this.tags = tags;
14
+ this.priority = priority;
15
+
16
+ var onReadyStateChange = function() {
17
+ if (self.img.readyState == 'complete') {
18
+ removeEventHandlers();
19
+ loader.onLoad(self);
20
+ }
21
+ };
22
+
23
+ var onLoad = function() {
24
+ removeEventHandlers();
25
+ loader.onLoad(self);
26
+ };
27
+
28
+ var onError = function() {
29
+ removeEventHandlers();
30
+ loader.onError(self);
31
+ };
32
+
33
+ var removeEventHandlers = function() {
34
+ self.unbind('load', onLoad);
35
+ self.unbind('readystatechange', onReadyStateChange);
36
+ self.unbind('error', onError);
37
+ };
38
+
39
+ this.start = function(pxloader) {
40
+ // we need the loader ref so we can notify upon completion
41
+ loader = pxloader;
42
+
43
+ // NOTE: Must add event listeners before the src is set. We
44
+ // also need to use the readystatechange because sometimes
45
+ // load doesn't fire when an image is in the cache.
46
+ self.bind('load', onLoad);
47
+ self.bind('readystatechange', onReadyStateChange);
48
+ self.bind('error', onError);
49
+
50
+ self.img.src = url;
51
+ };
52
+
53
+ // called by ww.Loader to check status of image (fallback in case
54
+ // the event listeners are not triggered).
55
+ this.checkStatus = function() {
56
+ if (self.img.complete) {
57
+ removeEventHandlers();
58
+ loader.onLoad(self);
59
+ }
60
+ };
61
+
62
+ // called by ww.Loader when it is no longer waiting
63
+ this.onTimeout = function() {
64
+ removeEventHandlers();
65
+ if (self.img.complete) {
66
+ loader.onLoad(self);
67
+ } else {
68
+ loader.onTimeout(self);
69
+ }
70
+ };
71
+
72
+ // returns a name for the resource that can be used in logging
73
+ this.getName = function() {
74
+ return url;
75
+ };
76
+
77
+ // cross-browser event binding
78
+ this.bind = function(eventName, eventHandler) {
79
+ if (self.img.addEventListener) {
80
+ self.img.addEventListener(eventName, eventHandler, false);
81
+ } else if (self.img.attachEvent) {
82
+ self.img.attachEvent('on' + eventName, eventHandler);
83
+ }
84
+ };
85
+
86
+ // cross-browser event un-binding
87
+ this.unbind = function(eventName, eventHandler) {
88
+ if (self.img.removeEventListener) {
89
+ self.img.removeEventListener(eventName, eventHandler, false);
90
+ } else if (self.img.detachEvent) {
91
+ self.img.detachEvent('on' + eventName, eventHandler);
92
+ }
93
+ };
94
+ };
95
+
96
+ goog.exportSymbol('ww.LoaderImage', ww.LoaderImage);