kojac 0.9.0
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.
- checksums.yaml +15 -0
- data/.gitignore +7 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +158 -0
- data/MIT-LICENSE +20 -0
- data/README.md +69 -0
- data/Rakefile +27 -0
- data/app/assets/javascripts/can_extensions.js +45 -0
- data/app/assets/javascripts/kojac.js +1230 -0
- data/app/assets/javascripts/kojac_canjs.js +191 -0
- data/app/assets/javascripts/kojac_ember.js +463 -0
- data/app/controllers/kojac_controller.rb +70 -0
- data/app/serializers/default_kojac_serializer.rb +10 -0
- data/diagram.odg +0 -0
- data/kojac.gemspec +36 -0
- data/lib/kojac/app_serialize.rb +29 -0
- data/lib/kojac/kojac_rails.rb +432 -0
- data/lib/kojac/ring_strong_parameters.rb +195 -0
- data/lib/kojac/version.rb +3 -0
- data/lib/kojac.rb +8 -0
- data/lib/tasks/kojac_tasks.rake +4 -0
- data/notes.txt +48 -0
- data/spec/.DS_Store +0 -0
- data/spec/can_cache_spec.js +87 -0
- data/spec/can_factory_spec.js +144 -0
- data/spec/can_model_spec.js +127 -0
- data/spec/demo/README.rdoc +261 -0
- data/spec/demo/Rakefile +7 -0
- data/spec/demo/app/assets/javascripts/application.js +15 -0
- data/spec/demo/app/assets/stylesheets/application.css +13 -0
- data/spec/demo/app/controllers/application_controller.rb +3 -0
- data/spec/demo/app/helpers/application_helper.rb +2 -0
- data/spec/demo/app/mailers/.gitkeep +0 -0
- data/spec/demo/app/models/.gitkeep +0 -0
- data/spec/demo/app/views/layouts/application.html.erb +14 -0
- data/spec/demo/config/application.rb +65 -0
- data/spec/demo/config/boot.rb +10 -0
- data/spec/demo/config/database.yml +25 -0
- data/spec/demo/config/environment.rb +5 -0
- data/spec/demo/config/environments/development.rb +37 -0
- data/spec/demo/config/environments/production.rb +67 -0
- data/spec/demo/config/environments/test.rb +37 -0
- data/spec/demo/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/demo/config/initializers/inflections.rb +15 -0
- data/spec/demo/config/initializers/mime_types.rb +5 -0
- data/spec/demo/config/initializers/secret_token.rb +7 -0
- data/spec/demo/config/initializers/session_store.rb +8 -0
- data/spec/demo/config/initializers/wrap_parameters.rb +14 -0
- data/spec/demo/config/locales/en.yml +5 -0
- data/spec/demo/config/routes.rb +58 -0
- data/spec/demo/config.ru +4 -0
- data/spec/demo/lib/assets/.gitkeep +0 -0
- data/spec/demo/log/.gitkeep +0 -0
- data/spec/demo/public/404.html +26 -0
- data/spec/demo/public/422.html +26 -0
- data/spec/demo/public/500.html +25 -0
- data/spec/demo/public/favicon.ico +0 -0
- data/spec/demo/script/rails +6 -0
- data/spec/ember_factory_spec.js +157 -0
- data/spec/ember_model_spec.js +179 -0
- data/spec/external/.DS_Store +0 -0
- data/spec/external/ember/.DS_Store +0 -0
- data/spec/external/ember/ember-1.0.0-rc.6.js +30970 -0
- data/spec/external/ember/handlebars-1.0.0-rc.4.js +2239 -0
- data/spec/external/jasmine/MIT.LICENSE +20 -0
- data/spec/external/jasmine/jasmine-html.js +616 -0
- data/spec/external/jasmine/jasmine.css +81 -0
- data/spec/external/jasmine/jasmine.js +2529 -0
- data/spec/external/jasmine.async.js +51 -0
- data/spec/external/jquery/jquery-1.7.2.js +9404 -0
- data/spec/external/jquery/jquery-1.7.2.min.js +4 -0
- data/spec/external/jquery/jquery-1.9.1.js +9597 -0
- data/spec/external/json2.js +480 -0
- data/spec/external/steal/steal-121115.js +2747 -0
- data/spec/external/steal/steal-3.2.3.js +2098 -0
- data/spec/external/steal/steal-3.2.3.min.js +27 -0
- data/spec/external/steal/steal.js +2466 -0
- data/spec/external/steal/steal.min.js +32 -0
- data/spec/external/steal/stealconfig.js +19 -0
- data/spec/external/underscore.js +1223 -0
- data/spec/external/underscore_plus.js +261 -0
- data/spec/external.zip +0 -0
- data/spec/handler_stack_spec.js +143 -0
- data/spec/helpers/SpecHelper.js +10 -0
- data/spec/kojac_caching_spec.js +105 -0
- data/spec/kojac_mock_spec.js +230 -0
- data/spec/kojac_model_spec.js +126 -0
- data/spec/kojac_object_spec.js +171 -0
- data/spec/kojac_operations_spec.js +41 -0
- data/spec/mockjson/order_item.js +37 -0
- data/spec/mockjson/order_item__49.js +15 -0
- data/spec/mockjson/order_item__50.js +15 -0
- data/spec/mockjson/order_item__51.js +15 -0
- data/spec/mockjson/product.js +82 -0
- data/spec/mockjson/product__3.js +22 -0
- data/spec/model_ring_spec.rb +52 -0
- data/spec/operation_include_spec.js +77 -0
- data/spec/run.html +81 -0
- data/spec/spec.js +2 -0
- data/spec/support/jasmine.yml +86 -0
- metadata +380 -0
|
@@ -0,0 +1,2466 @@
|
|
|
1
|
+
// steal is a resource loader for JavaScript. It is broken into the following parts:
|
|
2
|
+
//
|
|
3
|
+
// - Helpers - basic utility methods used internally
|
|
4
|
+
// - AOP - aspect oriented code helpers
|
|
5
|
+
// - Deferred - a minimal deferred implementation
|
|
6
|
+
// - Uri - methods for dealing with urls
|
|
7
|
+
// - Api - steal's API
|
|
8
|
+
// - Resource - an object that represents a resource that is loaded and run and has dependencies.
|
|
9
|
+
// - Type - a type systems used to load and run different types of resources
|
|
10
|
+
// - Packages - used to define packages
|
|
11
|
+
// - Extensions - makes steal pre-load a type based on an extension (ex: .coffee)
|
|
12
|
+
// - Mapping - configures steal to load resources in a different location
|
|
13
|
+
// - Startup - startup code
|
|
14
|
+
// - jQuery - code to make jQuery's readWait work
|
|
15
|
+
// - Error Handling - detect scripts failing to load
|
|
16
|
+
// - Has option - used to specify that one resources contains multiple other resources
|
|
17
|
+
// - Window Load - API for knowing when the window has loaded and all scripts have loaded
|
|
18
|
+
// - Interactive - Code for IE
|
|
19
|
+
// - Options -
|
|
20
|
+
(function( win, undefined ) {
|
|
21
|
+
|
|
22
|
+
// ## Helpers ##
|
|
23
|
+
// The following are a list of helper methods used internally to steal
|
|
24
|
+
var
|
|
25
|
+
// check that we have a document
|
|
26
|
+
doc = win.document,
|
|
27
|
+
docEl = doc && doc.documentElement,
|
|
28
|
+
// a jQuery-like $.each
|
|
29
|
+
each = function( o, cb ) {
|
|
30
|
+
var i, len;
|
|
31
|
+
|
|
32
|
+
// weak array detection, but we only use this internally so don't
|
|
33
|
+
// pass it weird stuff
|
|
34
|
+
if ( typeof o.length == 'number' ) {
|
|
35
|
+
for ( i = 0, len = o.length; i < len; i++ ) {
|
|
36
|
+
cb.call(o[i], i, o[i], o)
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
for ( i in o ) {
|
|
40
|
+
cb.call(o[i], i, o[i], o)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return o;
|
|
44
|
+
},
|
|
45
|
+
// adds the item to the array only if it doesn't currently exist
|
|
46
|
+
uniquePush = function(arr, item){
|
|
47
|
+
for(var i=0; i < arr.length; i++){
|
|
48
|
+
if(arr[i] == item){
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
arr.push(item)
|
|
53
|
+
},
|
|
54
|
+
// if o is a string
|
|
55
|
+
isString = function( o ) {
|
|
56
|
+
return typeof o == "string";
|
|
57
|
+
},
|
|
58
|
+
// if o is a function
|
|
59
|
+
isFn = function( o ) {
|
|
60
|
+
return typeof o == "function";
|
|
61
|
+
},
|
|
62
|
+
// dummy function
|
|
63
|
+
noop = function() {},
|
|
64
|
+
// creates an element
|
|
65
|
+
createElement = function( nodeName ) {
|
|
66
|
+
return doc.createElement(nodeName)
|
|
67
|
+
},
|
|
68
|
+
// creates a script tag
|
|
69
|
+
scriptTag = function() {
|
|
70
|
+
var start = createElement("script");
|
|
71
|
+
start.type = "text/javascript";
|
|
72
|
+
return start;
|
|
73
|
+
},
|
|
74
|
+
// minify-able verstion of getElementsByTagName
|
|
75
|
+
getElementsByTagName = function( tag ) {
|
|
76
|
+
return doc.getElementsByTagName(tag);
|
|
77
|
+
},
|
|
78
|
+
// A function that returns the head element
|
|
79
|
+
// creates and caches the lookup for faster
|
|
80
|
+
// performance.
|
|
81
|
+
head = function() {
|
|
82
|
+
var hd = getElementsByTagName("head")[0];
|
|
83
|
+
if (!hd ) {
|
|
84
|
+
hd = createElement("head");
|
|
85
|
+
docEl.insertBefore(hd, docEl.firstChild);
|
|
86
|
+
}
|
|
87
|
+
// replace head so it runs fast next time.
|
|
88
|
+
head = function() {
|
|
89
|
+
return hd;
|
|
90
|
+
}
|
|
91
|
+
return hd;
|
|
92
|
+
},
|
|
93
|
+
// extends one object with another
|
|
94
|
+
extend = function( d, s ) {
|
|
95
|
+
// only extend if we have something to extend
|
|
96
|
+
s && each(s, function( k ) {
|
|
97
|
+
d[k] = s[k];
|
|
98
|
+
});
|
|
99
|
+
return d;
|
|
100
|
+
},
|
|
101
|
+
// makes an array of things, or a mapping of things
|
|
102
|
+
map = function( args, cb ) {
|
|
103
|
+
var arr = [];
|
|
104
|
+
each(args, function( i, str ) {
|
|
105
|
+
arr.push(cb ? (isString(cb) ? str[cb] : cb.call(str, str)) : str)
|
|
106
|
+
});
|
|
107
|
+
return arr;
|
|
108
|
+
},
|
|
109
|
+
// testing support for various browser behaviors
|
|
110
|
+
support = {
|
|
111
|
+
// does onerror work in script tags?
|
|
112
|
+
error: doc && (function() {
|
|
113
|
+
var script = scriptTag();
|
|
114
|
+
script.onerror = noop;
|
|
115
|
+
return isFn(script.onerror) || "onerror" in script
|
|
116
|
+
})(),
|
|
117
|
+
// If scripts support interactive ready state.
|
|
118
|
+
// This is tested later.
|
|
119
|
+
interactive: false,
|
|
120
|
+
// use attachEvent for event listening (IE)
|
|
121
|
+
attachEvent: doc && scriptTag().attachEvent
|
|
122
|
+
},
|
|
123
|
+
// a startup function that will be called when steal is ready
|
|
124
|
+
startup = noop,
|
|
125
|
+
// if oldsteal is an object
|
|
126
|
+
// we use it as options to configure steal
|
|
127
|
+
opts = typeof win.steal == "object" ? win.steal : {},
|
|
128
|
+
// adds a suffix to the url for cache busting
|
|
129
|
+
addSuffix = function( str ) {
|
|
130
|
+
if ( opts.suffix ) {
|
|
131
|
+
str = (str + '').indexOf('?') > -1 ? str + "&" + opts.suffix : str + "?" + opts.suffix;
|
|
132
|
+
}
|
|
133
|
+
return str;
|
|
134
|
+
},
|
|
135
|
+
endsInSlashRegex = /\/$/;
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
// ## AOP ##
|
|
139
|
+
// Aspect oriented programming helper methods are used to
|
|
140
|
+
// weave in functionality into steal's API.
|
|
141
|
+
// calls `before` before `f` is called.
|
|
142
|
+
// steal.complete = before(steal.complete, f)
|
|
143
|
+
// `changeArgs=true` makes before return the same args
|
|
144
|
+
function before(f, before, changeArgs) {
|
|
145
|
+
return changeArgs ?
|
|
146
|
+
function before_changeArgs() {
|
|
147
|
+
return f.apply(this, before.apply(this, arguments));
|
|
148
|
+
} : function before_args() {
|
|
149
|
+
before.apply(this, arguments);
|
|
150
|
+
return f.apply(this, arguments);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// returns a function that calls `after`
|
|
154
|
+
// after `f`
|
|
155
|
+
function after(f, after, changeRet) {
|
|
156
|
+
return changeRet ?
|
|
157
|
+
function after_CRet() {
|
|
158
|
+
return after.apply(this, [f.apply(this, arguments)].concat(map(arguments)));
|
|
159
|
+
} : function after_Ret() {
|
|
160
|
+
var ret = f.apply(this, arguments);
|
|
161
|
+
after.apply(this, arguments);
|
|
162
|
+
return ret;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
// ## Deferred .63
|
|
168
|
+
var Deferred = function( func ) {
|
|
169
|
+
if (!(this instanceof Deferred)) return new Deferred();
|
|
170
|
+
|
|
171
|
+
this.doneFuncs = [];
|
|
172
|
+
this.failFuncs = [];
|
|
173
|
+
this.resultArgs = null;
|
|
174
|
+
this.status = "";
|
|
175
|
+
|
|
176
|
+
// check for option function: call it with this as context and as first
|
|
177
|
+
// parameter, as specified in jQuery api
|
|
178
|
+
func && func.call(this, this);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
Deferred.when = function() {
|
|
182
|
+
var args = map(arguments);
|
|
183
|
+
if ( args.length < 2 ) {
|
|
184
|
+
var obj = args[0];
|
|
185
|
+
if ( obj && (isFn(obj.isResolved) && isFn(obj.isRejected)) ) {
|
|
186
|
+
return obj;
|
|
187
|
+
} else {
|
|
188
|
+
return Deferred().resolve(obj);
|
|
189
|
+
}
|
|
190
|
+
} else {
|
|
191
|
+
|
|
192
|
+
var df = Deferred(),
|
|
193
|
+
done = 0,
|
|
194
|
+
// resolve params: params of each resolve, we need to track down
|
|
195
|
+
// them to be able to pass them in the correct order if the master
|
|
196
|
+
// needs to be resolved
|
|
197
|
+
rp = [];
|
|
198
|
+
|
|
199
|
+
each(args, function( j, arg ) {
|
|
200
|
+
arg.done(function() {
|
|
201
|
+
rp[j] = (arguments.length < 2) ? arguments[0] : arguments;
|
|
202
|
+
if (++done == args.length ) {
|
|
203
|
+
df.resolve.apply(df, rp);
|
|
204
|
+
}
|
|
205
|
+
}).fail(function() {
|
|
206
|
+
df.reject(arguments);
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
return df;
|
|
211
|
+
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
var resolveFunc = function( type, status ) {
|
|
216
|
+
return function( context ) {
|
|
217
|
+
var args = this.resultArgs = (arguments.length > 1) ? arguments[1] : [];
|
|
218
|
+
return this.exec(context, this[type], args, status);
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
doneFunc = function( type, status ) {
|
|
222
|
+
return function() {
|
|
223
|
+
var self = this;
|
|
224
|
+
each(arguments, function( i, v, args ) {
|
|
225
|
+
if (!v ) return;
|
|
226
|
+
if ( v.constructor === Array ) {
|
|
227
|
+
args.callee.apply(self, v)
|
|
228
|
+
} else {
|
|
229
|
+
// immediately call the function if the deferred has been resolved
|
|
230
|
+
if ( self.status === status ) v.apply(this, self.resultArgs || []);
|
|
231
|
+
|
|
232
|
+
self[type].push(v);
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
return this;
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
extend(Deferred.prototype, {
|
|
240
|
+
resolveWith: resolveFunc("doneFuncs", "rs"),
|
|
241
|
+
rejectWith: resolveFunc("failFuncs", "rj"),
|
|
242
|
+
done: doneFunc("doneFuncs", "rs"),
|
|
243
|
+
fail: doneFunc("failFuncs", "rj"),
|
|
244
|
+
always: function() {
|
|
245
|
+
var args = map(arguments);
|
|
246
|
+
if ( args.length && args[0] ) this.done(args[0]).fail(args[0]);
|
|
247
|
+
|
|
248
|
+
return this;
|
|
249
|
+
},
|
|
250
|
+
then: function() {
|
|
251
|
+
var args = map(arguments);
|
|
252
|
+
// fail function(s)
|
|
253
|
+
if ( args.length > 1 && args[1] ) this.fail(args[1]);
|
|
254
|
+
|
|
255
|
+
// done function(s)
|
|
256
|
+
if ( args.length && args[0] ) this.done(args[0]);
|
|
257
|
+
|
|
258
|
+
return this;
|
|
259
|
+
},
|
|
260
|
+
isResolved: function() {
|
|
261
|
+
return this.status === "rs";
|
|
262
|
+
},
|
|
263
|
+
isRejected: function() {
|
|
264
|
+
return this.status === "rj";
|
|
265
|
+
},
|
|
266
|
+
reject: function() {
|
|
267
|
+
return this.rejectWith(this, arguments);
|
|
268
|
+
},
|
|
269
|
+
resolve: function() {
|
|
270
|
+
return this.resolveWith(this, arguments);
|
|
271
|
+
},
|
|
272
|
+
exec: function( context, dst, args, st ) {
|
|
273
|
+
if ( this.status !== "" ) return this;
|
|
274
|
+
|
|
275
|
+
this.status = st;
|
|
276
|
+
|
|
277
|
+
each(dst, function( i, d ) {
|
|
278
|
+
d.apply(context, args);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
return this;
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
// ## HELPER METHODS FOR DEFERREDS
|
|
285
|
+
// Used to call a method on an object or resolve a
|
|
286
|
+
// deferred on it when a group of deferreds is resolved.
|
|
287
|
+
//
|
|
288
|
+
// whenEach(resources,"complete",resource,"execute")
|
|
289
|
+
var whenEach = function( arr, func, obj, func2 ) {
|
|
290
|
+
|
|
291
|
+
var deferreds = map(arr, func)
|
|
292
|
+
return Deferred.when.apply(Deferred, deferreds).then(function() {
|
|
293
|
+
if ( isFn(obj[func2]) ) {
|
|
294
|
+
obj[func2]()
|
|
295
|
+
} else {
|
|
296
|
+
obj[func2].resolve();
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
});
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
// ## URI ##
|
|
303
|
+
/**
|
|
304
|
+
* @class steal.URI
|
|
305
|
+
* A URL / URI helper for getting information from a URL.
|
|
306
|
+
*
|
|
307
|
+
* var uri = URI( "http://stealjs.com/index.html" )
|
|
308
|
+
* uri.path //-> "/index.html"
|
|
309
|
+
*/
|
|
310
|
+
var URI = function( url ) {
|
|
311
|
+
if ( this.constructor !== URI ) {
|
|
312
|
+
return new URI(url);
|
|
313
|
+
}
|
|
314
|
+
extend(this, URI.parse("" + url));
|
|
315
|
+
};
|
|
316
|
+
// the current url (relative to root, which is relative from page)
|
|
317
|
+
// normalize joins from this
|
|
318
|
+
//
|
|
319
|
+
extend(URI, {
|
|
320
|
+
// parses a URI into it's basic parts
|
|
321
|
+
parse: function( string ) {
|
|
322
|
+
var uriParts = string.split("?"),
|
|
323
|
+
uri = uriParts.shift(),
|
|
324
|
+
queryParts = uriParts.join("").split("#"),
|
|
325
|
+
protoParts = uri.split("://"),
|
|
326
|
+
parts = {
|
|
327
|
+
query: queryParts.shift(),
|
|
328
|
+
fragment: queryParts.join("#")
|
|
329
|
+
},
|
|
330
|
+
pathParts;
|
|
331
|
+
|
|
332
|
+
if ( protoParts[1] ) {
|
|
333
|
+
parts.protocol = protoParts.shift();
|
|
334
|
+
pathParts = protoParts[0].split("/");
|
|
335
|
+
parts.host = pathParts.shift();
|
|
336
|
+
parts.path = "/" + pathParts.join("/");
|
|
337
|
+
} else {
|
|
338
|
+
parts.path = protoParts[0];
|
|
339
|
+
}
|
|
340
|
+
return parts;
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
/**
|
|
344
|
+
* @attribute page
|
|
345
|
+
* The location of the page as a URI.
|
|
346
|
+
*
|
|
347
|
+
* steal.URI.page.protocol //-> "http"
|
|
348
|
+
*/
|
|
349
|
+
URI.page = URI(win.location && location.href);
|
|
350
|
+
/**
|
|
351
|
+
* @attribute cur
|
|
352
|
+
*
|
|
353
|
+
* The current working directory / path. Anything
|
|
354
|
+
* loaded relative will be loaded relative to this.
|
|
355
|
+
*/
|
|
356
|
+
URI.cur = URI();
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* @prototype
|
|
360
|
+
*/
|
|
361
|
+
extend(URI.prototype, {
|
|
362
|
+
dir: function() {
|
|
363
|
+
var parts = this.path.split("/");
|
|
364
|
+
parts.pop();
|
|
365
|
+
return URI(this.domain() + parts.join("/"))
|
|
366
|
+
},
|
|
367
|
+
filename: function() {
|
|
368
|
+
return this.path.split("/").pop();
|
|
369
|
+
},
|
|
370
|
+
ext: function() {
|
|
371
|
+
var filename = this.filename();
|
|
372
|
+
return~filename.indexOf(".") ? filename.split(".").pop() : "";
|
|
373
|
+
},
|
|
374
|
+
domain: function() {
|
|
375
|
+
return this.protocol ? this.protocol + "://" + this.host : "";
|
|
376
|
+
},
|
|
377
|
+
isCrossDomain: function( uri ) {
|
|
378
|
+
uri = URI(uri || win.location.href);
|
|
379
|
+
var domain = this.domain(),
|
|
380
|
+
uriDomain = uri.domain()
|
|
381
|
+
return (domain && uriDomain && domain != uriDomain) || this.protocol === "file" || (domain && !uriDomain);
|
|
382
|
+
},
|
|
383
|
+
isRelativeToDomain: function() {
|
|
384
|
+
return !this.path.indexOf("/");
|
|
385
|
+
},
|
|
386
|
+
hash: function() {
|
|
387
|
+
return this.fragment ? "#" + this.fragment : ""
|
|
388
|
+
},
|
|
389
|
+
search: function() {
|
|
390
|
+
return this.query ? "?" + this.query : ""
|
|
391
|
+
},
|
|
392
|
+
// like join, but returns a string
|
|
393
|
+
add: function( uri ) {
|
|
394
|
+
return this.join(uri) + '';
|
|
395
|
+
},
|
|
396
|
+
join: function( uri, min ) {
|
|
397
|
+
uri = URI(uri);
|
|
398
|
+
if ( uri.isCrossDomain(this) ) {
|
|
399
|
+
return uri;
|
|
400
|
+
}
|
|
401
|
+
if ( uri.isRelativeToDomain() ) {
|
|
402
|
+
return URI(this.domain() + uri)
|
|
403
|
+
}
|
|
404
|
+
// at this point we either
|
|
405
|
+
// - have the same domain
|
|
406
|
+
// - this has a domain but uri does not
|
|
407
|
+
// - both don't have domains
|
|
408
|
+
var left = this.path ? this.path.split("/") : [],
|
|
409
|
+
right = uri.path.split("/"),
|
|
410
|
+
part = right[0];
|
|
411
|
+
//if we are joining from a folder like cookbook/, remove the last empty part
|
|
412
|
+
if ( this.path.match(/\/$/) ) {
|
|
413
|
+
left.pop();
|
|
414
|
+
}
|
|
415
|
+
while ( part == ".." && left.length ) {
|
|
416
|
+
// if we've emptied out, folders, just break
|
|
417
|
+
// leaving any additional ../s
|
|
418
|
+
if (!left.pop() ) {
|
|
419
|
+
break;
|
|
420
|
+
}
|
|
421
|
+
right.shift();
|
|
422
|
+
|
|
423
|
+
part = right[0];
|
|
424
|
+
}
|
|
425
|
+
return extend(URI(this.domain() + left.concat(right).join("/")), {
|
|
426
|
+
query: uri.query
|
|
427
|
+
});
|
|
428
|
+
},
|
|
429
|
+
/**
|
|
430
|
+
* For a given path, a given working directory, and file location, update the
|
|
431
|
+
* path so it points to a location relative to steal's root.
|
|
432
|
+
*
|
|
433
|
+
* We want everything relative to steal's root so the same app can work in
|
|
434
|
+
* multiple pages.
|
|
435
|
+
*
|
|
436
|
+
* ./files/a.js = steals a.js
|
|
437
|
+
* ./files/a = a/a.js
|
|
438
|
+
* files/a = //files/a/a.js
|
|
439
|
+
* files/a.js = loads //files/a.js
|
|
440
|
+
*/
|
|
441
|
+
normalize: function( cur ) {
|
|
442
|
+
cur = cur ? cur.dir() : URI.cur.dir();
|
|
443
|
+
var path = this.path,
|
|
444
|
+
res = URI(path);
|
|
445
|
+
//if path is rooted from steal's root (DEPRECATED)
|
|
446
|
+
if (!path.indexOf("//") ) {
|
|
447
|
+
res = URI(path.substr(2));
|
|
448
|
+
} else if (!path.indexOf("./") ) { // should be relative
|
|
449
|
+
res = cur.join(path.substr(2));
|
|
450
|
+
}
|
|
451
|
+
// only if we start with ./ or have a /foo should we join from cur
|
|
452
|
+
else if ( this.isRelative() ) {
|
|
453
|
+
res = cur.join(this.domain() + path)
|
|
454
|
+
}
|
|
455
|
+
res.query = this.query;
|
|
456
|
+
return res;
|
|
457
|
+
},
|
|
458
|
+
isRelative: function() {
|
|
459
|
+
return /^[\.|\/]/.test(this.path)
|
|
460
|
+
},
|
|
461
|
+
// a min path from 2 urls that share the same domain
|
|
462
|
+
pathTo: function( uri ) {
|
|
463
|
+
uri = URI(uri);
|
|
464
|
+
var uriParts = uri.path.split("/"),
|
|
465
|
+
thisParts = this.path.split("/"),
|
|
466
|
+
result = [];
|
|
467
|
+
while ( uriParts.length && thisParts.length && uriParts[0] == thisParts[0] ) {
|
|
468
|
+
uriParts.shift();
|
|
469
|
+
thisParts.shift();
|
|
470
|
+
}
|
|
471
|
+
each(thisParts, function() {
|
|
472
|
+
result.push("../")
|
|
473
|
+
})
|
|
474
|
+
return URI(result.join("") + uriParts.join("/"));
|
|
475
|
+
},
|
|
476
|
+
mapJoin: function( url ) {
|
|
477
|
+
return this.join(URI(url).insertMapping());
|
|
478
|
+
},
|
|
479
|
+
// helper to go from jquery to jquery/jquery.js
|
|
480
|
+
addJS: function() {
|
|
481
|
+
var ext = this.ext();
|
|
482
|
+
if (!ext ) {
|
|
483
|
+
// if first character of path is a . or /, just load this file
|
|
484
|
+
if (!this.isRelative() ) {
|
|
485
|
+
this.path += "/" + this.filename();
|
|
486
|
+
}
|
|
487
|
+
this.path += ".js"
|
|
488
|
+
}
|
|
489
|
+
return this;
|
|
490
|
+
}
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
// create the steal function now to use as a namespace.
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
function steal() {
|
|
497
|
+
// convert arguments into an array
|
|
498
|
+
var args = map(arguments);
|
|
499
|
+
if ( args.length ) {
|
|
500
|
+
pending.push.apply(pending, args);
|
|
501
|
+
// steal.after is called everytime steal is called
|
|
502
|
+
// it kicks off loading these files
|
|
503
|
+
steal.after(args);
|
|
504
|
+
// return steal for chaining
|
|
505
|
+
}
|
|
506
|
+
return steal;
|
|
507
|
+
};
|
|
508
|
+
steal._id = Math.floor(1000 * Math.random());
|
|
509
|
+
// ## CONFIG ##
|
|
510
|
+
|
|
511
|
+
// stores the current config settings
|
|
512
|
+
var stealConfig = {
|
|
513
|
+
types: {},
|
|
514
|
+
ext: {},
|
|
515
|
+
env: "development",
|
|
516
|
+
loadProduction: true,
|
|
517
|
+
logLevel: 0
|
|
518
|
+
},
|
|
519
|
+
|
|
520
|
+
matchesId = function( loc, id ) {
|
|
521
|
+
if ( loc === "*" ) {
|
|
522
|
+
return true;
|
|
523
|
+
} else if ( id.indexOf(loc) === 0 ) {
|
|
524
|
+
return true;
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
/**
|
|
528
|
+
* `steal.config(config)` configures steal. Typically it it used
|
|
529
|
+
* in __stealconfig.js__. The available options are:
|
|
530
|
+
*
|
|
531
|
+
* - map - map an id to another id
|
|
532
|
+
* - paths - maps an id to a file
|
|
533
|
+
* - root - the path to the "root" folder
|
|
534
|
+
* - env - `"development"` or `"production"`
|
|
535
|
+
* - types - processor rules for various types
|
|
536
|
+
* - ext - behavior rules for extensions
|
|
537
|
+
* - urlArgs - extra queryString arguments
|
|
538
|
+
* - startFile - the file to load
|
|
539
|
+
*
|
|
540
|
+
* ## map
|
|
541
|
+
*
|
|
542
|
+
* Maps an id to another id with a certain scope of other ids. This can be
|
|
543
|
+
* used to use different modules within the same id or map ids to another id.
|
|
544
|
+
* Example:
|
|
545
|
+
*
|
|
546
|
+
* steal.config({
|
|
547
|
+
* map: {
|
|
548
|
+
* "*": {
|
|
549
|
+
* "jquery/jquery.js": "jquery"
|
|
550
|
+
* },
|
|
551
|
+
* "compontent1":{
|
|
552
|
+
* "underscore" : "underscore1.2"
|
|
553
|
+
* },
|
|
554
|
+
* "component2":{
|
|
555
|
+
* "underscore" : "underscore1.1"
|
|
556
|
+
* }
|
|
557
|
+
* }
|
|
558
|
+
* })
|
|
559
|
+
*
|
|
560
|
+
* ## paths
|
|
561
|
+
*
|
|
562
|
+
* Maps an id or matching ids to a url. Each mapping is specified
|
|
563
|
+
* by an id or part of the id to match and what that
|
|
564
|
+
* part should be replaced with.
|
|
565
|
+
*
|
|
566
|
+
* steal.config({
|
|
567
|
+
* paths: {
|
|
568
|
+
* // maps everything in a jquery folder like: `jquery/controller`
|
|
569
|
+
* // to http://cdn.com/jquery/controller/controller.com
|
|
570
|
+
* "jquery/" : "http://cdn.com/jquery/"
|
|
571
|
+
*
|
|
572
|
+
* // if path does not end with /, it matches only that id
|
|
573
|
+
* "jquery" : "https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"
|
|
574
|
+
* }
|
|
575
|
+
* })
|
|
576
|
+
*
|
|
577
|
+
* ## root
|
|
578
|
+
* ## env
|
|
579
|
+
*
|
|
580
|
+
* If production, does not load "ignored" scripts and loads production script. If development gives more warnings / errors.
|
|
581
|
+
*
|
|
582
|
+
* ## types
|
|
583
|
+
*
|
|
584
|
+
* The types option can specify how a type is loaded.
|
|
585
|
+
*
|
|
586
|
+
* ## ext
|
|
587
|
+
*
|
|
588
|
+
* The ext option specifies the default behavior if file is loaded with the
|
|
589
|
+
* specified extension. For a given extension, a file that configures the type can be given or
|
|
590
|
+
* an existing type. For example, for ejs:
|
|
591
|
+
*
|
|
592
|
+
* steal.config({ext: {"ejs": "can/view/ejs/ejs.js"}})
|
|
593
|
+
*
|
|
594
|
+
* This tells steal to make sure `can/view/ejs/ejs.js` is executed before any file with
|
|
595
|
+
* ".ejs" is executed.
|
|
596
|
+
*
|
|
597
|
+
* ## startFile
|
|
598
|
+
*/
|
|
599
|
+
steal.config = function( config ) {
|
|
600
|
+
if(!config){ // called as a getter, so just return
|
|
601
|
+
return stealConfig;
|
|
602
|
+
}
|
|
603
|
+
if(arguments.length === 1 && typeof config === "string"){ // called as a getter, so just return
|
|
604
|
+
return stealConfig[config];
|
|
605
|
+
}
|
|
606
|
+
for(var prop in config){
|
|
607
|
+
var value = config[prop]
|
|
608
|
+
// if it's a special function
|
|
609
|
+
steal.config[prop] ?
|
|
610
|
+
// run it
|
|
611
|
+
steal.config[prop](value) :
|
|
612
|
+
// otherwise set or extend
|
|
613
|
+
(typeof value == "object" && stealConfig[prop] ?
|
|
614
|
+
// extend
|
|
615
|
+
extend( stealConfig[prop], value) :
|
|
616
|
+
// set
|
|
617
|
+
stealConfig[prop] = value);
|
|
618
|
+
|
|
619
|
+
}
|
|
620
|
+
// redo all resources
|
|
621
|
+
each(resources, function( id, resource ) {
|
|
622
|
+
if ( resource.options.type != "fn" ) {
|
|
623
|
+
// TODO this is terrible
|
|
624
|
+
var buildType = resource.options.buildType;
|
|
625
|
+
resource.setOptions(resource.orig);
|
|
626
|
+
var newId = resource.options.id;
|
|
627
|
+
// this mapping is to move a config'd key
|
|
628
|
+
if ( id !== newId ) {
|
|
629
|
+
resources[newId] = resource;
|
|
630
|
+
// TODO: remove the old one ....
|
|
631
|
+
}
|
|
632
|
+
resource.options.buildType = buildType;
|
|
633
|
+
}
|
|
634
|
+
})
|
|
635
|
+
return stealConfig;
|
|
636
|
+
};
|
|
637
|
+
steal.config.startFile = function(startFile){
|
|
638
|
+
// make sure startFile and production look right
|
|
639
|
+
stealConfig.startFile = "" + URI(startFile).addJS()
|
|
640
|
+
if (!stealConfig.production ) {
|
|
641
|
+
stealConfig.production = URI(stealConfig.startFile).dir() + "/production.js";
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* Read or define the path relative URI's should be referenced from.
|
|
647
|
+
*
|
|
648
|
+
* window.location //-> "http://foo.com/site/index.html"
|
|
649
|
+
* steal.URI.root("http://foo.com/app/files/")
|
|
650
|
+
* steal.root.toString() //-> "../../app/files/"
|
|
651
|
+
*/
|
|
652
|
+
steal.config.root = function( relativeURI ) {
|
|
653
|
+
if ( relativeURI !== undefined ) {
|
|
654
|
+
var root = URI(relativeURI);
|
|
655
|
+
|
|
656
|
+
// the current folder-location of the page http://foo.com/bar/card
|
|
657
|
+
var cleaned = URI.page,
|
|
658
|
+
// the absolute location or root
|
|
659
|
+
loc = cleaned.join(relativeURI);
|
|
660
|
+
|
|
661
|
+
// cur now points to the 'root' location, but from the page
|
|
662
|
+
URI.cur = loc.pathTo(cleaned)
|
|
663
|
+
stealConfig.root = root;
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
stealConfig.root = root || URI("");
|
|
667
|
+
}
|
|
668
|
+
steal.config.root("");
|
|
669
|
+
/**
|
|
670
|
+
* @function steal.id
|
|
671
|
+
*
|
|
672
|
+
* Given a resource id passed to `steal( resourceID, currentWorkingId )`, this function converts it to the
|
|
673
|
+
* final, unique id. This function can be overwritten
|
|
674
|
+
* to change how unique ids are defined, for example, to be more AMD-like.
|
|
675
|
+
*
|
|
676
|
+
* The following are the default rules.
|
|
677
|
+
*
|
|
678
|
+
* Given an ID:
|
|
679
|
+
*
|
|
680
|
+
* 1. Check the id has an extension like _.js_ or _.customext_. If it doesn't:
|
|
681
|
+
* 1. Check if the id is relative, meaning it starts with _../_ or _./_. If it is not, add
|
|
682
|
+
* "/" plus everything after the last "/". So `foo/bar` becomes `foo/bar/bar`
|
|
683
|
+
* 2. Add .js to the id.
|
|
684
|
+
* 2. Check if the id is relative, meaning it starts with _../_ or _./_. If it is relative,
|
|
685
|
+
* set the id to the id joined from the currentWorkingId.
|
|
686
|
+
* 3. Check the
|
|
687
|
+
*
|
|
688
|
+
*
|
|
689
|
+
* `steal.id()`
|
|
690
|
+
*/
|
|
691
|
+
// returns the "rootSrc" id, something that looks like requireJS
|
|
692
|
+
// for a given id/path, what is the "REAL" id that should be used
|
|
693
|
+
// this is where substituation can happen
|
|
694
|
+
steal.id = function( id, currentWorkingId, type ) {
|
|
695
|
+
// id should be like
|
|
696
|
+
var uri = URI(id);
|
|
697
|
+
uri = uri.addJS().normalize(currentWorkingId ? new URI(currentWorkingId) : null)
|
|
698
|
+
// check foo/bar
|
|
699
|
+
if (!type ) {
|
|
700
|
+
type = "js"
|
|
701
|
+
}
|
|
702
|
+
if ( type == "js" ) {
|
|
703
|
+
// if it ends with .js remove it ...
|
|
704
|
+
// if it ends
|
|
705
|
+
}
|
|
706
|
+
// check map config
|
|
707
|
+
var map = stealConfig.map || {};
|
|
708
|
+
// always run past
|
|
709
|
+
each(map, function( loc, maps ) {
|
|
710
|
+
// is the current working id matching loc
|
|
711
|
+
if ( matchesId(loc, currentWorkingId) ) {
|
|
712
|
+
// run maps
|
|
713
|
+
each(maps, function( part, replaceWith ) {
|
|
714
|
+
if (("" + uri).indexOf(part) == 0 ) {
|
|
715
|
+
uri = URI(("" + uri).replace(part, replaceWith))
|
|
716
|
+
}
|
|
717
|
+
})
|
|
718
|
+
}
|
|
719
|
+
})
|
|
720
|
+
|
|
721
|
+
return uri;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
steal.amdToId = function(id, currentWorkingId, type){
|
|
725
|
+
var uri = URI(id);
|
|
726
|
+
uri = uri.normalize(currentWorkingId ? new URI(currentWorkingId) : null)
|
|
727
|
+
// check foo/bar
|
|
728
|
+
if (!type ) {
|
|
729
|
+
type = "js"
|
|
730
|
+
}
|
|
731
|
+
if ( type == "js" ) {
|
|
732
|
+
// if it ends with .js remove it ...
|
|
733
|
+
// if it ends
|
|
734
|
+
}
|
|
735
|
+
// check map config
|
|
736
|
+
var map = stealConfig.map || {};
|
|
737
|
+
// always run past
|
|
738
|
+
each(map, function( loc, maps ) {
|
|
739
|
+
// is the current working id matching loc
|
|
740
|
+
if ( matchesId(loc, currentWorkingId) ) {
|
|
741
|
+
// run maps
|
|
742
|
+
each(maps, function( part, replaceWith ) {
|
|
743
|
+
if (("" + uri).indexOf(part) == 0 ) {
|
|
744
|
+
uri = URI(("" + uri).replace(part, replaceWith))
|
|
745
|
+
}
|
|
746
|
+
})
|
|
747
|
+
}
|
|
748
|
+
})
|
|
749
|
+
return uri;
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
|
|
753
|
+
steal.config.shim = function(shims){
|
|
754
|
+
|
|
755
|
+
for(var id in shims){
|
|
756
|
+
var resource = Resource.make(id);
|
|
757
|
+
if(typeof shims[id] === "object"){
|
|
758
|
+
var needs = shims[id].deps || []
|
|
759
|
+
if(typeof shims[id].exports === "string"){
|
|
760
|
+
var exports = (function(_exports){
|
|
761
|
+
return function(){
|
|
762
|
+
return win[_exports];
|
|
763
|
+
}
|
|
764
|
+
})(shims[id].exports)
|
|
765
|
+
} else {
|
|
766
|
+
exports = shims[id].exports;
|
|
767
|
+
}
|
|
768
|
+
} else {
|
|
769
|
+
needs = shims[id];
|
|
770
|
+
}
|
|
771
|
+
(function(_resource, _needs){
|
|
772
|
+
_resource.options.needs = _needs;
|
|
773
|
+
})(resource, needs)
|
|
774
|
+
|
|
775
|
+
if(exports){
|
|
776
|
+
resource.exports = (function(_resource, _exports, _needs){
|
|
777
|
+
return function(){
|
|
778
|
+
var args = _needs.map(function(id){
|
|
779
|
+
return Resource.make(id).value;
|
|
780
|
+
})
|
|
781
|
+
_resource.value = _exports.apply(null, args)
|
|
782
|
+
return _resource.value
|
|
783
|
+
}
|
|
784
|
+
})(resource, exports, needs)
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
// for a given ID, where should I find this resource
|
|
791
|
+
/**
|
|
792
|
+
* `steal.idToUri( id, noJoin )` takes an id and returns a URI that
|
|
793
|
+
* is the location of the file. It uses the paths option of [steal.config].
|
|
794
|
+
* Passing true for `noJoin` does not join from the root URI.
|
|
795
|
+
*/
|
|
796
|
+
steal.idToUri = function( id, noJoin ) {
|
|
797
|
+
// this is normalize
|
|
798
|
+
var paths = stealConfig.paths || {},
|
|
799
|
+
path;
|
|
800
|
+
// always run past
|
|
801
|
+
each(paths, function( part, replaceWith ) {
|
|
802
|
+
path = ""+id;
|
|
803
|
+
// if path ends in / only check first part of id
|
|
804
|
+
if((endsInSlashRegex.test(part) && path.indexOf(part) == 0) ||
|
|
805
|
+
// or check if its a full match only
|
|
806
|
+
path === part){
|
|
807
|
+
id = URI(path.replace(part, replaceWith));
|
|
808
|
+
}
|
|
809
|
+
})
|
|
810
|
+
|
|
811
|
+
return noJoin ? id : stealConfig.root.join(id)
|
|
812
|
+
}
|
|
813
|
+
steal.amdIdToUri = function( id, noJoin ){
|
|
814
|
+
// this is normalize
|
|
815
|
+
var paths = stealConfig.paths || {},
|
|
816
|
+
path;
|
|
817
|
+
// always run past
|
|
818
|
+
each(paths, function( part, replaceWith ) {
|
|
819
|
+
path = ""+id;
|
|
820
|
+
// if path ends in / only check first part of id
|
|
821
|
+
if((endsInSlashRegex.test(part) && path.indexOf(part) == 0) ||
|
|
822
|
+
// or check if its a full match only
|
|
823
|
+
path === part){
|
|
824
|
+
id = URI(path.replace(part, replaceWith));
|
|
825
|
+
}
|
|
826
|
+
})
|
|
827
|
+
if( /(^|\/)[^\/\.]+$/.test(id) ){
|
|
828
|
+
id= URI(id+".js")
|
|
829
|
+
}
|
|
830
|
+
return id //noJoin ? id : stealConfig.root.join(id)
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
|
|
834
|
+
|
|
835
|
+
// This can't be added to the prototype using extend because
|
|
836
|
+
// then for some reason IE < 9 won't recognize it.
|
|
837
|
+
URI.prototype.toString = function() {
|
|
838
|
+
return this.domain() + this.path + this.search() + this.hash();
|
|
839
|
+
};
|
|
840
|
+
|
|
841
|
+
// temp add steal.File for backward compat
|
|
842
|
+
steal.File = steal.URI = URI;
|
|
843
|
+
// --- END URI
|
|
844
|
+
var pending = [],
|
|
845
|
+
s = steal,
|
|
846
|
+
id = 0;
|
|
847
|
+
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* @add steal
|
|
851
|
+
*/
|
|
852
|
+
// =============================== STATIC API ===============================
|
|
853
|
+
var page;
|
|
854
|
+
|
|
855
|
+
extend(steal, {
|
|
856
|
+
each: each,
|
|
857
|
+
extend: extend,
|
|
858
|
+
Deferred: Deferred,
|
|
859
|
+
// Currently used a few places
|
|
860
|
+
isRhino: win.load && win.readUrl && win.readFile,
|
|
861
|
+
/**
|
|
862
|
+
* @hide
|
|
863
|
+
* Makes options
|
|
864
|
+
* @param {Object} options
|
|
865
|
+
*/
|
|
866
|
+
makeOptions: function( options, curId ) {
|
|
867
|
+
// convert it to a uri
|
|
868
|
+
if (!options.id ) {
|
|
869
|
+
throw {
|
|
870
|
+
message: "no id",
|
|
871
|
+
options: options
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
options.id = options.toId ? options.toId(options.id, curId) : steal.id(options.id, curId);
|
|
875
|
+
// set the ext
|
|
876
|
+
options.ext = options.id.ext();
|
|
877
|
+
|
|
878
|
+
// Check if it's a configured needs
|
|
879
|
+
var configedExt = stealConfig.ext[options.ext];
|
|
880
|
+
// if we have something, but it's not a type
|
|
881
|
+
if ( configedExt && ! stealConfig.types[configedExt] ) {
|
|
882
|
+
if (!options.needs ) {
|
|
883
|
+
options.needs = [];
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
options.needs.push(configedExt);
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
return options;
|
|
890
|
+
},
|
|
891
|
+
/**
|
|
892
|
+
* Calls steal, but waits until all previous steals
|
|
893
|
+
* have completed loading until loading the
|
|
894
|
+
* files passed to the arguments.
|
|
895
|
+
*/
|
|
896
|
+
then: function() {
|
|
897
|
+
var args = map(arguments);
|
|
898
|
+
args.unshift(null)
|
|
899
|
+
return steal.apply(win, args);
|
|
900
|
+
},
|
|
901
|
+
/**
|
|
902
|
+
* `steal.bind( event, handler(eventData...) )` listens to
|
|
903
|
+
* events on steal. Typically these are used by various build processes
|
|
904
|
+
* to know when steal starts and finish loading resources and their
|
|
905
|
+
* dependencies. Listen to an event like:
|
|
906
|
+
*
|
|
907
|
+
* steal.bind('end', function(rootResource){
|
|
908
|
+
* rootResource.dependencies // the first stolen resources.
|
|
909
|
+
* })
|
|
910
|
+
*
|
|
911
|
+
* Steal supports the following events:
|
|
912
|
+
*
|
|
913
|
+
* - __start__ - steal has started loading a group of resources and their dependencies.
|
|
914
|
+
* - __end__ - steal has finished loading a group of resources and their dependencies.
|
|
915
|
+
* - __done__ - steal has finished loading the first set of resources and their dependencies.
|
|
916
|
+
* - __ready__ - after both steal's "done" event and the `window`'s onload event have fired.
|
|
917
|
+
*
|
|
918
|
+
* For example, the following html:
|
|
919
|
+
*
|
|
920
|
+
* @codestart html
|
|
921
|
+
* <script src='steal/steal.js'></script>
|
|
922
|
+
* <script>
|
|
923
|
+
* steal('can/control', function(){
|
|
924
|
+
* setTimeout(function(){
|
|
925
|
+
* steal('can/model')
|
|
926
|
+
* },200)
|
|
927
|
+
* })
|
|
928
|
+
* </script>
|
|
929
|
+
* @codeend
|
|
930
|
+
*
|
|
931
|
+
* Would fire:
|
|
932
|
+
*
|
|
933
|
+
* - __start__ - immediately after `steal('can/control')` is called
|
|
934
|
+
* - __end__ - after 'can/control', all of it's dependencies, and the callback function have executed and completed.
|
|
935
|
+
* - __done__ - fired after the first 'end' event.
|
|
936
|
+
* - __ready__ - fired after window.onload and the 'done' event
|
|
937
|
+
* - __start__ - immediately after `steal('can/model')` is called
|
|
938
|
+
* - __end__ - fired after 'can/model' and all of it's dependencies have fired.
|
|
939
|
+
*
|
|
940
|
+
*
|
|
941
|
+
*
|
|
942
|
+
* @param {String} event
|
|
943
|
+
* @param {Function} listener
|
|
944
|
+
*/
|
|
945
|
+
bind: function( event, listener ) {
|
|
946
|
+
if (!events[event] ) {
|
|
947
|
+
events[event] = []
|
|
948
|
+
}
|
|
949
|
+
var special = steal.events[event]
|
|
950
|
+
if ( special && special.add ) {
|
|
951
|
+
listener = special.add(listener);
|
|
952
|
+
}
|
|
953
|
+
listener && events[event].push(listener);
|
|
954
|
+
return steal;
|
|
955
|
+
},
|
|
956
|
+
/**
|
|
957
|
+
* `steal.one(eventName, handler(eventArgs...) )` works just like
|
|
958
|
+
* [steal.bind] but immediately unbinds after `handler` is called.
|
|
959
|
+
*/
|
|
960
|
+
one: function( event, listener ) {
|
|
961
|
+
return steal.bind(event, function() {
|
|
962
|
+
listener.apply(this, arguments);
|
|
963
|
+
steal.unbind(event, arguments.callee);
|
|
964
|
+
});
|
|
965
|
+
},
|
|
966
|
+
events: {},
|
|
967
|
+
/**
|
|
968
|
+
* `steal.unbind( eventName, handler )` removes an event listener on steal.
|
|
969
|
+
* @param {String} event
|
|
970
|
+
* @param {Function} listener
|
|
971
|
+
*/
|
|
972
|
+
unbind: function( event, listener ) {
|
|
973
|
+
var evs = events[event] || [],
|
|
974
|
+
i = 0;
|
|
975
|
+
while ( i < evs.length ) {
|
|
976
|
+
if ( listener === evs[i] ) {
|
|
977
|
+
evs.splice(i, 1);
|
|
978
|
+
} else {
|
|
979
|
+
i++;
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
},
|
|
983
|
+
trigger: function( event, arg ) {
|
|
984
|
+
var arr = events[event] || [];
|
|
985
|
+
// array items might be removed during each iteration (with unbind),
|
|
986
|
+
// so we iterate over a copy
|
|
987
|
+
each(map(arr), function( i, f ) {
|
|
988
|
+
f(arg);
|
|
989
|
+
})
|
|
990
|
+
},
|
|
991
|
+
/**
|
|
992
|
+
* @hide
|
|
993
|
+
* Creates resources and marks them as loading so steal doesn't try
|
|
994
|
+
* to load them.
|
|
995
|
+
*
|
|
996
|
+
* steal.has("foo/bar.js","zed/car.js");
|
|
997
|
+
*
|
|
998
|
+
* This is used when a file has other resources in it.
|
|
999
|
+
*/
|
|
1000
|
+
has: function() {
|
|
1001
|
+
// we don't use IE's interactive script functionality while
|
|
1002
|
+
// production scripts are loading
|
|
1003
|
+
support.interactive = false;
|
|
1004
|
+
each(arguments, function( i, arg ) {
|
|
1005
|
+
var stel = Resource.make(arg);
|
|
1006
|
+
stel.loading = stel.executing = true;
|
|
1007
|
+
});
|
|
1008
|
+
},
|
|
1009
|
+
|
|
1010
|
+
// a dummy function to add things to after the stel is created, but before executed is called
|
|
1011
|
+
preexecuted: function() {},
|
|
1012
|
+
/**
|
|
1013
|
+
* @hide
|
|
1014
|
+
* Signals that a resource's JS code has been run. This is used
|
|
1015
|
+
* when a file has other resources in it.
|
|
1016
|
+
*
|
|
1017
|
+
* steal.has("foo/bar.js");
|
|
1018
|
+
*
|
|
1019
|
+
* //start code for foo/bar.js
|
|
1020
|
+
* steal("zed/car.js", function(){ ... });
|
|
1021
|
+
* steal.executed("foo/bar.js");
|
|
1022
|
+
*
|
|
1023
|
+
* When a resource is executed, its dependent resources are loaded and eventually
|
|
1024
|
+
* executed.
|
|
1025
|
+
*/
|
|
1026
|
+
// called when a script has loaded via production
|
|
1027
|
+
executed: function( name ) {
|
|
1028
|
+
// create the steal, mark it as loading, then as loaded
|
|
1029
|
+
var resource = Resource.make(name);
|
|
1030
|
+
resource.loading = resource.executing = true;
|
|
1031
|
+
//convert(stel, "complete");
|
|
1032
|
+
steal.preexecuted(resource);
|
|
1033
|
+
resource.executed()
|
|
1034
|
+
return steal;
|
|
1035
|
+
},
|
|
1036
|
+
type: function( type, cb ) {
|
|
1037
|
+
var typs = type.split(" ");
|
|
1038
|
+
|
|
1039
|
+
if (!cb ) {
|
|
1040
|
+
return types[typs.shift()].require
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
types[typs.shift()] = {
|
|
1044
|
+
require: cb,
|
|
1045
|
+
convert: typs
|
|
1046
|
+
};
|
|
1047
|
+
}
|
|
1048
|
+
});
|
|
1049
|
+
|
|
1050
|
+
|
|
1051
|
+
// ============ RESOURCE ================
|
|
1052
|
+
// a map of resources by resourceID
|
|
1053
|
+
var resources = {};
|
|
1054
|
+
// this is for methods on a 'steal instance'. A file can be in one of a few states:
|
|
1055
|
+
// created - the steal instance is created, but we haven't started loading it yet
|
|
1056
|
+
// this happens when thens are used
|
|
1057
|
+
// loading - (loading=true) By calling load, this will tell steal to load a file
|
|
1058
|
+
// loaded - (isLoaded=true) The file has been run, but its dependency files have been completed
|
|
1059
|
+
// complete - all of this files dependencies have loaded and completed.
|
|
1060
|
+
|
|
1061
|
+
// A Resource is almost anything. It is different from a module
|
|
1062
|
+
// as it doesn't represent some unit of functionality, rather
|
|
1063
|
+
// it represents a unit that can have other units "within" it
|
|
1064
|
+
// as dependencies. A resource can:
|
|
1065
|
+
//
|
|
1066
|
+
// - load - load the resource to the client so it is available, but don't run it yet
|
|
1067
|
+
// - run - run the code for the resource
|
|
1068
|
+
// - executed - the code has been run for the resource, but all
|
|
1069
|
+
// dependencies for that resource might not have finished
|
|
1070
|
+
// - completed - all resources within the resource have completed
|
|
1071
|
+
//
|
|
1072
|
+
// __options__
|
|
1073
|
+
// `options` can be a string, function, or object.
|
|
1074
|
+
//
|
|
1075
|
+
// __properties__
|
|
1076
|
+
//
|
|
1077
|
+
// - options - has a number of properties
|
|
1078
|
+
// - src - a URI to this resource that can be loaded from the current page
|
|
1079
|
+
// - rootSrc - a URI to this resource relative to the current root URI.
|
|
1080
|
+
// - type - the type of resource: "fn", "js", "css", etc
|
|
1081
|
+
// - needs - other resources that must be loaded prior to this resource
|
|
1082
|
+
// - fn - a callback function to run when executed
|
|
1083
|
+
// - unique - false if this resource should be loaded each time
|
|
1084
|
+
// - waits - this resource should wait until all prior scripts have completed before running
|
|
1085
|
+
// - loaded - a deferred indicating if this resource has been loaded to the client
|
|
1086
|
+
// - run - a deferred indicating if the the code for this resource run
|
|
1087
|
+
// - completed - a deferred indicating if all of this resources dependencies have
|
|
1088
|
+
// completed
|
|
1089
|
+
// - dependencies - an array of dependencies
|
|
1090
|
+
var Resource = function( options ) {
|
|
1091
|
+
// an array for dependencies, this is the steal calls this resource makes
|
|
1092
|
+
this.dependencies = [];
|
|
1093
|
+
|
|
1094
|
+
// an array of implicit dependencies this steal needs
|
|
1095
|
+
this.needsDependencies = [];
|
|
1096
|
+
|
|
1097
|
+
// id for debugging
|
|
1098
|
+
this.id = (++id);
|
|
1099
|
+
// the original options
|
|
1100
|
+
this.orig = options;
|
|
1101
|
+
// the parent steal's id
|
|
1102
|
+
this.curId = steal.cur && steal.cur.options.id;
|
|
1103
|
+
|
|
1104
|
+
this.setOptions(options);
|
|
1105
|
+
// create the deferreds used to manage state
|
|
1106
|
+
this.loaded = Deferred();
|
|
1107
|
+
this.run = Deferred();
|
|
1108
|
+
this.completed = Deferred();
|
|
1109
|
+
};
|
|
1110
|
+
// `Resource.make` is used to either create
|
|
1111
|
+
// a new resource, or return an existing
|
|
1112
|
+
// resource that matches the options.
|
|
1113
|
+
Resource.make = function( options ) {
|
|
1114
|
+
// create the temporary reasource
|
|
1115
|
+
var resource = new Resource(options),
|
|
1116
|
+
// use `rootSrc` as the definitive ID
|
|
1117
|
+
id = resource.options.id;
|
|
1118
|
+
|
|
1119
|
+
// assuming this resource should not be created again.
|
|
1120
|
+
if ( resource.unique && id ) {
|
|
1121
|
+
|
|
1122
|
+
// Check if we already have a resource for this rootSrc
|
|
1123
|
+
// Also check with a .js ending because we defer 'type'
|
|
1124
|
+
// determination until later
|
|
1125
|
+
if (!resources[id] && !resources[id + ".js"] ) {
|
|
1126
|
+
// If we haven't loaded, cache the resource
|
|
1127
|
+
resources[id] = resource;
|
|
1128
|
+
} else {
|
|
1129
|
+
|
|
1130
|
+
// Otherwise get the cached resource
|
|
1131
|
+
existingResource = resources[id];
|
|
1132
|
+
// If options were passed, copy new properties over.
|
|
1133
|
+
// Don't copy src, etc because those have already
|
|
1134
|
+
// been changed to be the right values;
|
|
1135
|
+
if (!isString(options) ) {
|
|
1136
|
+
// extend everything other than id
|
|
1137
|
+
for(var prop in options){
|
|
1138
|
+
if(prop !== "id") {
|
|
1139
|
+
existingResource.options[prop] = options[prop];
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
return existingResource;
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
return resource;
|
|
1148
|
+
};
|
|
1149
|
+
|
|
1150
|
+
// updates the paths of things ...
|
|
1151
|
+
// use modules b/c they are more fuzzy
|
|
1152
|
+
// a module's id stays the same, but a path might change
|
|
1153
|
+
//
|
|
1154
|
+
Resource.update = function() {
|
|
1155
|
+
for ( var rootSrc in resources ) {
|
|
1156
|
+
if (!resources[resources].loaded.isResolved() ) {
|
|
1157
|
+
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
};
|
|
1161
|
+
|
|
1162
|
+
extend(Resource.prototype, {
|
|
1163
|
+
setOptions: function( options ) {
|
|
1164
|
+
var prevOptions = this.options;
|
|
1165
|
+
// if we have no options, we are the global Resource that
|
|
1166
|
+
// contains all other resources.
|
|
1167
|
+
if (!options ) { //global init cur ...
|
|
1168
|
+
this.options = {};
|
|
1169
|
+
this.waits = false;
|
|
1170
|
+
}
|
|
1171
|
+
//handle callback functions
|
|
1172
|
+
else if ( isFn(options) ) {
|
|
1173
|
+
var uri = URI.cur,
|
|
1174
|
+
self = this,
|
|
1175
|
+
cur = steal.cur;
|
|
1176
|
+
this.options = {
|
|
1177
|
+
fn: function() {
|
|
1178
|
+
|
|
1179
|
+
// Set the URI if there are steals
|
|
1180
|
+
// within the callback.
|
|
1181
|
+
URI.cur = uri;
|
|
1182
|
+
|
|
1183
|
+
// we should get the current "module"
|
|
1184
|
+
// check it's listed dependencies and see
|
|
1185
|
+
// if they have a value
|
|
1186
|
+
var args = [],
|
|
1187
|
+
found = false,
|
|
1188
|
+
dep, value;
|
|
1189
|
+
// iterate backwards through dependencies
|
|
1190
|
+
for ( var i = cur.dependencies.length; i >= 0; i-- ) {
|
|
1191
|
+
dep = cur.dependencies[i];
|
|
1192
|
+
|
|
1193
|
+
if ( found ) {
|
|
1194
|
+
if ( dep === null ) {
|
|
1195
|
+
// //alert("YES")
|
|
1196
|
+
break;
|
|
1197
|
+
}
|
|
1198
|
+
// We need to access the stored modules in this order
|
|
1199
|
+
// - calculated id
|
|
1200
|
+
// - original name
|
|
1201
|
+
// - dependency return value otherwise
|
|
1202
|
+
value = modules[dep.options.id] || modules[dep.orig] || dep.value;
|
|
1203
|
+
args.unshift(value);
|
|
1204
|
+
|
|
1205
|
+
// what does this do?
|
|
1206
|
+
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
if ( dep === self ) {
|
|
1210
|
+
found = true;
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
|
|
1215
|
+
|
|
1216
|
+
var ret = options.apply(cur, args);
|
|
1217
|
+
|
|
1218
|
+
// if this returns a value, we should register it as a module ...
|
|
1219
|
+
if ( ret ) {
|
|
1220
|
+
// register this module ....
|
|
1221
|
+
cur.value = ret;
|
|
1222
|
+
}
|
|
1223
|
+
return ret;
|
|
1224
|
+
},
|
|
1225
|
+
id: uri,
|
|
1226
|
+
type: "fn"
|
|
1227
|
+
}
|
|
1228
|
+
// this has nothing to do with 'loading' options
|
|
1229
|
+
this.waits = true;
|
|
1230
|
+
this.unique = false;
|
|
1231
|
+
} else {
|
|
1232
|
+
// save the original options
|
|
1233
|
+
this.options = steal.makeOptions(extend({}, isString(options) ? {
|
|
1234
|
+
id: options
|
|
1235
|
+
} : options), this.curId);
|
|
1236
|
+
|
|
1237
|
+
this.waits = this.options.waits || false;
|
|
1238
|
+
this.unique = true;
|
|
1239
|
+
}
|
|
1240
|
+
// if there are other options we haven't already set, reuse the old ones
|
|
1241
|
+
for(opt in prevOptions){
|
|
1242
|
+
if(!this.options[opt]){
|
|
1243
|
+
this.options[opt] = prevOptions[opt];
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
},
|
|
1247
|
+
|
|
1248
|
+
// Calling complete indicates that all dependencies have
|
|
1249
|
+
// been completed for this resource
|
|
1250
|
+
complete: function() {
|
|
1251
|
+
this.completed.resolve();
|
|
1252
|
+
},
|
|
1253
|
+
// After the script has been loaded and run
|
|
1254
|
+
// - checks what has been stolen (in pending)
|
|
1255
|
+
// - wires up pendings steal's deferreds to eventually complete this
|
|
1256
|
+
// - this is where all of steal's complexity is
|
|
1257
|
+
executed: function( script ) {
|
|
1258
|
+
var myqueue,
|
|
1259
|
+
stel,
|
|
1260
|
+
src = this.options.src,
|
|
1261
|
+
rootSrc = this.options.rootSrc;
|
|
1262
|
+
// Set this as the current file so any relative urls
|
|
1263
|
+
// will load from it.
|
|
1264
|
+
// rootSrc needs to be the translated path
|
|
1265
|
+
// we need id vs rootSrc ...
|
|
1266
|
+
|
|
1267
|
+
if ( this.options.id ) {
|
|
1268
|
+
URI.cur = URI(this.options.id);
|
|
1269
|
+
}
|
|
1270
|
+
if( this.exports ){
|
|
1271
|
+
this.exports()
|
|
1272
|
+
}
|
|
1273
|
+
// set this as the current resource
|
|
1274
|
+
steal.cur = this;
|
|
1275
|
+
|
|
1276
|
+
// mark yourself as 'loaded'.
|
|
1277
|
+
this.run.resolve();
|
|
1278
|
+
|
|
1279
|
+
// If we are IE, get the queue from interactives.
|
|
1280
|
+
// It in interactives because you can't use onload to know
|
|
1281
|
+
// which script is executing.
|
|
1282
|
+
if ( support.interactive && src ) {
|
|
1283
|
+
myqueue = interactives[src];
|
|
1284
|
+
}
|
|
1285
|
+
// In other browsers, the queue of items to load is
|
|
1286
|
+
// what is in pending
|
|
1287
|
+
if (!myqueue ) {
|
|
1288
|
+
myqueue = pending.slice(0);
|
|
1289
|
+
pending = [];
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
// if we have nothing, mark us as complete
|
|
1293
|
+
if (!myqueue.length ) {
|
|
1294
|
+
this.complete();
|
|
1295
|
+
return;
|
|
1296
|
+
}
|
|
1297
|
+
//print("-setting up "+this.options.id)
|
|
1298
|
+
// now we have to figure out how to wire up our pending steals
|
|
1299
|
+
var self = this,
|
|
1300
|
+
// the current
|
|
1301
|
+
isProduction = stealConfig.env == "production",
|
|
1302
|
+
|
|
1303
|
+
stealInstances = [];
|
|
1304
|
+
|
|
1305
|
+
// iterate through the collection and add all the 'needs'
|
|
1306
|
+
// before fetching...
|
|
1307
|
+
each(myqueue, function( i, item ) {
|
|
1308
|
+
if( item === null){
|
|
1309
|
+
stealInstances.push(null);
|
|
1310
|
+
return
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
if ( (isProduction && item.ignore) || (!isProduction && !steal.isRhino && item.prodonly)) {
|
|
1314
|
+
return;
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1317
|
+
// make a steal object
|
|
1318
|
+
var stel = Resource.make(item);
|
|
1319
|
+
if ( packHash[stel.options.id] && stel.options.type !== 'fn' ) { // if we are production, and this is a package, mark as loading, but steal package?
|
|
1320
|
+
steal.has(""+stel.options.id);
|
|
1321
|
+
stel = Resource.make(packHash[""+stel.options.id]);
|
|
1322
|
+
}
|
|
1323
|
+
// has to happen before 'needs' for when reversed...
|
|
1324
|
+
stealInstances.push(stel);
|
|
1325
|
+
});
|
|
1326
|
+
//print("-instances "+this.options.id)
|
|
1327
|
+
// The set of resources before the previous "wait" resource
|
|
1328
|
+
var priorSet = [],
|
|
1329
|
+
// The current set of resources after and including the
|
|
1330
|
+
// previous "wait" resource
|
|
1331
|
+
set = [],
|
|
1332
|
+
// The first set of resources that we will execute
|
|
1333
|
+
// right away. This should be the first set of dependencies
|
|
1334
|
+
// that we can load in parallel. If something has
|
|
1335
|
+
// a need, the need should be in this set
|
|
1336
|
+
firstSet = [],
|
|
1337
|
+
// Should we be adding resources to the
|
|
1338
|
+
// firstSet
|
|
1339
|
+
setFirstSet = true;
|
|
1340
|
+
|
|
1341
|
+
// Goes through each resource and maintains
|
|
1342
|
+
// a list of the set of resources
|
|
1343
|
+
// that must be complete before the current
|
|
1344
|
+
// resource (`priorSet`).
|
|
1345
|
+
each( stealInstances, function( i, resource ) {
|
|
1346
|
+
// add it as a dependency, circular are not allowed
|
|
1347
|
+
self.dependencies.push(resource);
|
|
1348
|
+
|
|
1349
|
+
// if there's a wait and it's not the first thing
|
|
1350
|
+
if ( (resource === null || resource.waits) && set.length ) {
|
|
1351
|
+
// add the current set to `priorSet`
|
|
1352
|
+
priorSet = priorSet.concat(set);
|
|
1353
|
+
// empty the current set
|
|
1354
|
+
set = [];
|
|
1355
|
+
// we have our firs set of items
|
|
1356
|
+
setFirstSet = false;
|
|
1357
|
+
if(resource === null) {
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
}
|
|
1362
|
+
if ( resource === null ) return;
|
|
1363
|
+
|
|
1364
|
+
// when the priorSet is completed, execute this resource
|
|
1365
|
+
// and when it's needs are done
|
|
1366
|
+
var waitsOn = priorSet.slice(0);
|
|
1367
|
+
// if there are needs, this can not be part of the "firstSet"
|
|
1368
|
+
each(resource.options.needs || [], function( i, raw ) {
|
|
1369
|
+
|
|
1370
|
+
var need = Resource.make(raw);
|
|
1371
|
+
// add the need to the resource's dependencies
|
|
1372
|
+
uniquePush(resource.needsDependencies, need);
|
|
1373
|
+
waitsOn.push(need);
|
|
1374
|
+
// add needs to first set to execute
|
|
1375
|
+
firstSet.push(need)
|
|
1376
|
+
});
|
|
1377
|
+
waitsOn.length && whenEach(waitsOn, "completed", resource, "execute");
|
|
1378
|
+
|
|
1379
|
+
// what is this used for?
|
|
1380
|
+
resource.waitedOn = resource.waitedOn ? resource.waitedOn.concat(priorSet) : priorSet.slice(0);
|
|
1381
|
+
|
|
1382
|
+
// add this steal to the current set
|
|
1383
|
+
set.push(resource);
|
|
1384
|
+
// if we are still on the first set, and this has no needs
|
|
1385
|
+
if ( setFirstSet && (resource.options.needs || []).length == 0) {
|
|
1386
|
+
// add this to the first set of things
|
|
1387
|
+
firstSet.push(resource)
|
|
1388
|
+
}
|
|
1389
|
+
// start loading the resource if possible
|
|
1390
|
+
resource.load();
|
|
1391
|
+
});
|
|
1392
|
+
|
|
1393
|
+
// when every thing is complete, mark us as completed
|
|
1394
|
+
priorSet = priorSet.concat(set);
|
|
1395
|
+
whenEach(priorSet, "completed", self, "completed");
|
|
1396
|
+
|
|
1397
|
+
// execute the first set of dependencies
|
|
1398
|
+
each(firstSet, function( i, f ) {
|
|
1399
|
+
f.execute();
|
|
1400
|
+
});
|
|
1401
|
+
|
|
1402
|
+
},
|
|
1403
|
+
/**
|
|
1404
|
+
* Loads this steal
|
|
1405
|
+
*/
|
|
1406
|
+
load: function( returnScript ) {
|
|
1407
|
+
// if we are already loading / loaded
|
|
1408
|
+
if ( this.loading || this.loaded.isResolved() ) {
|
|
1409
|
+
return;
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
this.loading = true;
|
|
1413
|
+
this.loaded.resolve();
|
|
1414
|
+
},
|
|
1415
|
+
execute: function() {
|
|
1416
|
+
var self = this;
|
|
1417
|
+
if (!self.loaded.isResolved() ) {
|
|
1418
|
+
self.loaded.resolve();
|
|
1419
|
+
}
|
|
1420
|
+
if (!self.executing ) {
|
|
1421
|
+
self.executing = true;
|
|
1422
|
+
|
|
1423
|
+
steal.require(self.options, function( value ) {
|
|
1424
|
+
|
|
1425
|
+
self.executed( value );
|
|
1426
|
+
}, function( error, src ) {
|
|
1427
|
+
var abortFlag = self.options.abort,
|
|
1428
|
+
errorCb = self.options.error;
|
|
1429
|
+
|
|
1430
|
+
// if an error callback was provided, fire it
|
|
1431
|
+
if ( errorCb ) {
|
|
1432
|
+
errorCb.call(self.options);
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
win.clearTimeout && win.clearTimeout(self.completeTimeout)
|
|
1436
|
+
|
|
1437
|
+
// if abort: false, register the script as loaded, and don't throw
|
|
1438
|
+
if ( abortFlag === false ) {
|
|
1439
|
+
self.executed();
|
|
1440
|
+
return;
|
|
1441
|
+
}
|
|
1442
|
+
throw "steal.js : " + self.options.src + " not completed"
|
|
1443
|
+
});
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
});
|
|
1448
|
+
|
|
1449
|
+
|
|
1450
|
+
var events = {};
|
|
1451
|
+
|
|
1452
|
+
|
|
1453
|
+
|
|
1454
|
+
// ### TYPES ##
|
|
1455
|
+
var types = stealConfig.types;
|
|
1456
|
+
/**
|
|
1457
|
+
* Registers a type. You define the type of the file, the basic type it
|
|
1458
|
+
* converts to, and a conversion function where you convert the original file
|
|
1459
|
+
* to JS or CSS. This is modeled after the
|
|
1460
|
+
* [http://api.jquery.com/extending-ajax/#Converters AJAX converters] in jQuery.
|
|
1461
|
+
*
|
|
1462
|
+
* Types are designed to make it simple to switch between steal's development
|
|
1463
|
+
* and production modes. In development mode, the types are converted
|
|
1464
|
+
* in the browser to allow devs to see changes as they work. When the app is
|
|
1465
|
+
* built, these converter functions are run by the build process,
|
|
1466
|
+
* and the processed text is inserted into the production script, optimized for
|
|
1467
|
+
* performance.
|
|
1468
|
+
*
|
|
1469
|
+
* Here's an example converting files of type .foo to JavaScript. Foo is a
|
|
1470
|
+
* fake language that saves global variables defined like. A .foo file might
|
|
1471
|
+
* look like this:
|
|
1472
|
+
*
|
|
1473
|
+
* REQUIRED FOO
|
|
1474
|
+
*
|
|
1475
|
+
* To define this type, you'd call steal.type like this:
|
|
1476
|
+
*
|
|
1477
|
+
* steal.type("foo js", function(options, original, success, error){
|
|
1478
|
+
* var parts = options.text.split(" ")
|
|
1479
|
+
* options.text = parts[0]+"='"+parts[1]+"'";
|
|
1480
|
+
* success();
|
|
1481
|
+
* });
|
|
1482
|
+
*
|
|
1483
|
+
* The method we provide is called with the text of .foo files in options.text.
|
|
1484
|
+
* We parse the file, create JavaScript and put it in options.text. Couldn't
|
|
1485
|
+
* be simpler.
|
|
1486
|
+
*
|
|
1487
|
+
* Here's an example,
|
|
1488
|
+
* converting [http://jashkenas.github.com/coffee-script/ coffeescript]
|
|
1489
|
+
* to JavaScript:
|
|
1490
|
+
*
|
|
1491
|
+
* steal.type("coffee js", function(options, original, success, error){
|
|
1492
|
+
* options.text = CoffeeScript.compile(options.text);
|
|
1493
|
+
* success();
|
|
1494
|
+
* });
|
|
1495
|
+
*
|
|
1496
|
+
* In this example, any time steal encounters a file with extension .coffee,
|
|
1497
|
+
* it will call the given converter method. CoffeeScript.compile takes the
|
|
1498
|
+
* text of the file, converts it from coffeescript to javascript, and saves
|
|
1499
|
+
* the JavaScript text in options.text.
|
|
1500
|
+
*
|
|
1501
|
+
* Similarly, languages on top of CSS, like [http://lesscss.org/ LESS], can
|
|
1502
|
+
* be converted to CSS:
|
|
1503
|
+
*
|
|
1504
|
+
* steal.type("less css", function(options, original, success, error){
|
|
1505
|
+
* new (less.Parser)({
|
|
1506
|
+
* optimization: less.optimization,
|
|
1507
|
+
* paths: []
|
|
1508
|
+
* }).parse(options.text, function (e, root) {
|
|
1509
|
+
* options.text = root.toCSS();
|
|
1510
|
+
* success();
|
|
1511
|
+
* });
|
|
1512
|
+
* });
|
|
1513
|
+
*
|
|
1514
|
+
* This simple type system could be used to convert any file type to be used
|
|
1515
|
+
* in your JavaScript app. For example, [http://fdik.org/yml/ yml] could be
|
|
1516
|
+
* used for configuration. jQueryMX uses steal.type to support JS templates,
|
|
1517
|
+
* such as EJS, TMPL, and others.
|
|
1518
|
+
*
|
|
1519
|
+
* @param {String} type A string that defines the new type being defined and
|
|
1520
|
+
* the type being converted to, separated by a space, like "coffee js".
|
|
1521
|
+
*
|
|
1522
|
+
* There can be more than two steps used in conversion, such as "ejs view js".
|
|
1523
|
+
* This will define a method that converts .ejs files to .view files. There
|
|
1524
|
+
* should be another converter for "view js" that makes this final conversion
|
|
1525
|
+
* to JS.
|
|
1526
|
+
*
|
|
1527
|
+
* @param {Function} cb( options, original, success, error ) a callback
|
|
1528
|
+
* function that converts the new file type to a basic type. This method
|
|
1529
|
+
* needs to do two things: 1) save the text of the converted file in
|
|
1530
|
+
* options.text and 2) call success() when the conversion is done (it can work
|
|
1531
|
+
* asynchronously).
|
|
1532
|
+
*
|
|
1533
|
+
* - __options__ - the steal options for this file, including path information
|
|
1534
|
+
* - __original__ - the original argument passed to steal, which might be a
|
|
1535
|
+
* path or a function
|
|
1536
|
+
* - __success__ - a method to call when the file is converted and processed
|
|
1537
|
+
* successfully
|
|
1538
|
+
* - __error__ - a method called if the conversion fails or the file doesn't
|
|
1539
|
+
* exist
|
|
1540
|
+
*/
|
|
1541
|
+
steal.config.types = function(types){
|
|
1542
|
+
each(types, steal.type)
|
|
1543
|
+
};
|
|
1544
|
+
|
|
1545
|
+
|
|
1546
|
+
|
|
1547
|
+
// adds a type (js by default) and buildType (css, js)
|
|
1548
|
+
// this should happen right before loading
|
|
1549
|
+
// however, what if urls are different
|
|
1550
|
+
// because one file has JS and another does not?
|
|
1551
|
+
// we could check if it matches something with .js because foo.less.js SHOULD
|
|
1552
|
+
// be rare
|
|
1553
|
+
Resource.prototype.execute = before(Resource.prototype.execute, function() {
|
|
1554
|
+
var raw = this.options;
|
|
1555
|
+
|
|
1556
|
+
// if it's a string, get it's extension and check if
|
|
1557
|
+
// it is a registered type, if it is ... set the type
|
|
1558
|
+
if (!raw.type ) {
|
|
1559
|
+
var ext = URI(raw.id).ext();
|
|
1560
|
+
if (!ext && !types[ext] ) {
|
|
1561
|
+
ext = "js";
|
|
1562
|
+
}
|
|
1563
|
+
raw.type = ext;
|
|
1564
|
+
}
|
|
1565
|
+
if (!types[raw.type] && stealConfig.env == 'development' ) {
|
|
1566
|
+
throw "steal.js - type " + raw.type + " has not been loaded.";
|
|
1567
|
+
} else if (!types[raw.type] && stealConfig.env == 'production' ) {
|
|
1568
|
+
// if we haven't defined EJS yet and we're in production, its ok, just ignore it
|
|
1569
|
+
return;
|
|
1570
|
+
}
|
|
1571
|
+
var converters = types[raw.type].convert;
|
|
1572
|
+
raw.buildType = converters.length ? converters[converters.length - 1] : raw.type;
|
|
1573
|
+
});
|
|
1574
|
+
|
|
1575
|
+
steal.
|
|
1576
|
+
/**
|
|
1577
|
+
* Called for every file that is loaded. It sets up a string of methods called
|
|
1578
|
+
* for each type in the conversion chain and calls each type one by one.
|
|
1579
|
+
*
|
|
1580
|
+
* For example, if the file is a coffeescript file, here's what happens:
|
|
1581
|
+
*
|
|
1582
|
+
* - The "text" type converter is called first. This will perform an AJAX
|
|
1583
|
+
* request for the file and save it in options.text.
|
|
1584
|
+
* - Then the coffee type converter is called (the user provided method).
|
|
1585
|
+
* This converts the text from coffeescript to JavaScript.
|
|
1586
|
+
* - Finally the "js" type converter is called, which inserts the JavaScript
|
|
1587
|
+
* in the page as a script tag that is executed.
|
|
1588
|
+
*
|
|
1589
|
+
* @param {Object} options the steal options for this file, including path information
|
|
1590
|
+
* @param {Function} success a method to call when the file is converted and processed successfully
|
|
1591
|
+
* @param {Function} error a method called if the conversion fails or the file doesn't exist
|
|
1592
|
+
*/
|
|
1593
|
+
require = function( options, success, error ) {
|
|
1594
|
+
// add the src option
|
|
1595
|
+
options.src = options.idToUri ? options.idToUri(options.id) : steal.idToUri(options.id);
|
|
1596
|
+
|
|
1597
|
+
// get the type
|
|
1598
|
+
var type = types[options.type],
|
|
1599
|
+
converters;
|
|
1600
|
+
|
|
1601
|
+
// if this has converters, make it get the text first, then pass it to the type
|
|
1602
|
+
if ( type.convert.length ) {
|
|
1603
|
+
converters = type.convert.slice(0);
|
|
1604
|
+
converters.unshift("text", options.type)
|
|
1605
|
+
} else {
|
|
1606
|
+
converters = [options.type]
|
|
1607
|
+
}
|
|
1608
|
+
require(options, converters, success, error)
|
|
1609
|
+
};
|
|
1610
|
+
|
|
1611
|
+
function require(options, converters, success, error) {
|
|
1612
|
+
|
|
1613
|
+
var type = types[converters.shift()];
|
|
1614
|
+
|
|
1615
|
+
type.require(options, function require_continue_check() {
|
|
1616
|
+
// if we have more types to convert
|
|
1617
|
+
if ( converters.length ) {
|
|
1618
|
+
require(options, converters, success, error)
|
|
1619
|
+
} else { // otherwise this is the final
|
|
1620
|
+
success.apply(this, arguments);
|
|
1621
|
+
}
|
|
1622
|
+
}, error)
|
|
1623
|
+
};
|
|
1624
|
+
|
|
1625
|
+
|
|
1626
|
+
// =============================== TYPES ===============================
|
|
1627
|
+
// a clean up script that prevents memory leaks and removes the
|
|
1628
|
+
// script
|
|
1629
|
+
var cleanUp = function( elem ) {
|
|
1630
|
+
elem.onreadystatechange = elem.onload = elem.onerror = null;
|
|
1631
|
+
|
|
1632
|
+
setTimeout(function() {
|
|
1633
|
+
head().removeChild(elem);
|
|
1634
|
+
}, 1);
|
|
1635
|
+
},
|
|
1636
|
+
// the last inserted script, needed for IE
|
|
1637
|
+
lastInserted,
|
|
1638
|
+
// if the state is done
|
|
1639
|
+
stateCheck = /^loade|c|u/;
|
|
1640
|
+
|
|
1641
|
+
|
|
1642
|
+
var cssCount = 0,
|
|
1643
|
+
createSheet = doc && doc.createStyleSheet,
|
|
1644
|
+
lastSheet, lastSheetOptions;
|
|
1645
|
+
|
|
1646
|
+
// Apply all the basic types
|
|
1647
|
+
steal.config({
|
|
1648
|
+
types:{
|
|
1649
|
+
"js": function( options, success, error ) {
|
|
1650
|
+
// create a script tag
|
|
1651
|
+
var script = scriptTag(),
|
|
1652
|
+
callback = function() {
|
|
1653
|
+
if (!script.readyState || stateCheck.test(script.readyState) ) {
|
|
1654
|
+
cleanUp(script);
|
|
1655
|
+
success();
|
|
1656
|
+
}
|
|
1657
|
+
};
|
|
1658
|
+
|
|
1659
|
+
// if we have text, just set and insert text
|
|
1660
|
+
if ( options.text ) {
|
|
1661
|
+
// insert
|
|
1662
|
+
script.text = options.text;
|
|
1663
|
+
|
|
1664
|
+
} else {
|
|
1665
|
+
|
|
1666
|
+
// listen to loaded
|
|
1667
|
+
script.onload = script.onreadystatechange = callback;
|
|
1668
|
+
|
|
1669
|
+
var src = options.src; //steal.idToUri( options.id );
|
|
1670
|
+
// error handling doesn't work on firefox on the filesystem
|
|
1671
|
+
if ( support.error && error && src.protocol !== "file" ) {
|
|
1672
|
+
script.onerror = error;
|
|
1673
|
+
}
|
|
1674
|
+
script.src = "" + src;
|
|
1675
|
+
//script.src = options.src = addSuffix(options.src);
|
|
1676
|
+
//script.async = false;
|
|
1677
|
+
script.onSuccess = success;
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
// insert the script
|
|
1681
|
+
lastInserted = script;
|
|
1682
|
+
head().insertBefore(script, head().firstChild);
|
|
1683
|
+
|
|
1684
|
+
// if text, just call success right away, and clean up
|
|
1685
|
+
if ( options.text ) {
|
|
1686
|
+
callback();
|
|
1687
|
+
}
|
|
1688
|
+
},
|
|
1689
|
+
"fn": function( options, success ) {
|
|
1690
|
+
var ret;
|
|
1691
|
+
if (!options.skipCallbacks ) {
|
|
1692
|
+
ret = options.fn();
|
|
1693
|
+
}
|
|
1694
|
+
success(ret);
|
|
1695
|
+
},
|
|
1696
|
+
"text": function( options, success, error ) {
|
|
1697
|
+
steal.request(options, function( text ) {
|
|
1698
|
+
options.text = text;
|
|
1699
|
+
success(text);
|
|
1700
|
+
}, error)
|
|
1701
|
+
},
|
|
1702
|
+
"css": function( options, success, error ) {
|
|
1703
|
+
if ( options.text ) { // less
|
|
1704
|
+
var css = createElement("style");
|
|
1705
|
+
css.type = "text/css";
|
|
1706
|
+
if ( css.styleSheet ) { // IE
|
|
1707
|
+
css.styleSheet.cssText = options.text;
|
|
1708
|
+
} else {
|
|
1709
|
+
(function( node ) {
|
|
1710
|
+
if ( css.childNodes.length ) {
|
|
1711
|
+
if ( css.firstChild.nodeValue !== node.nodeValue ) {
|
|
1712
|
+
css.replaceChild(node, css.firstChild);
|
|
1713
|
+
}
|
|
1714
|
+
} else {
|
|
1715
|
+
css.appendChild(node);
|
|
1716
|
+
}
|
|
1717
|
+
})(doc.createTextNode(options.text));
|
|
1718
|
+
}
|
|
1719
|
+
head().appendChild(css);
|
|
1720
|
+
} else {
|
|
1721
|
+
if ( createSheet ) {
|
|
1722
|
+
// IE has a 31 sheet and 31 import per sheet limit
|
|
1723
|
+
if (!cssCount++ ) {
|
|
1724
|
+
lastSheet = doc.createStyleSheet(addSuffix(options.src));
|
|
1725
|
+
lastSheetOptions = options;
|
|
1726
|
+
} else {
|
|
1727
|
+
var relative = "" + URI(URI(lastSheetOptions.src).dir()).pathTo(options.src);
|
|
1728
|
+
lastSheet.addImport(addSuffix(relative));
|
|
1729
|
+
if ( cssCount == 30 ) {
|
|
1730
|
+
cssCount = 0;
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
success();
|
|
1734
|
+
return;
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1737
|
+
options = options || {};
|
|
1738
|
+
var link = createElement("link");
|
|
1739
|
+
link.rel = options.rel || "stylesheet";
|
|
1740
|
+
link.href = addSuffix(options.src);
|
|
1741
|
+
link.type = "text/css";
|
|
1742
|
+
head().appendChild(link);
|
|
1743
|
+
}
|
|
1744
|
+
|
|
1745
|
+
success();
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
});
|
|
1749
|
+
|
|
1750
|
+
|
|
1751
|
+
|
|
1752
|
+
// =============================== HELPERS ===============================
|
|
1753
|
+
var factory = function() {
|
|
1754
|
+
return win.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
|
|
1755
|
+
};
|
|
1756
|
+
|
|
1757
|
+
|
|
1758
|
+
steal.
|
|
1759
|
+
/**
|
|
1760
|
+
* Performs an XHR request
|
|
1761
|
+
* @param {Object} options
|
|
1762
|
+
* @param {Function} success
|
|
1763
|
+
* @param {Function} error
|
|
1764
|
+
*/
|
|
1765
|
+
request = function( options, success, error ) {
|
|
1766
|
+
var request = new factory(),
|
|
1767
|
+
contentType = (options.contentType || "application/x-www-form-urlencoded; charset=utf-8"),
|
|
1768
|
+
clean = function() {
|
|
1769
|
+
request = check = clean = null;
|
|
1770
|
+
},
|
|
1771
|
+
check = function() {
|
|
1772
|
+
var status;
|
|
1773
|
+
if ( request && request.readyState === 4 ) {
|
|
1774
|
+
status = request.status;
|
|
1775
|
+
if ( status === 500 || status === 404 || status === 2 || request.status < 0 || (!status && request.responseText === "") ) {
|
|
1776
|
+
error && error(request.status);
|
|
1777
|
+
} else {
|
|
1778
|
+
success(request.responseText);
|
|
1779
|
+
}
|
|
1780
|
+
clean();
|
|
1781
|
+
}
|
|
1782
|
+
};
|
|
1783
|
+
request.open("GET", options.src + '', !(options.async === false));
|
|
1784
|
+
request.setRequestHeader("Content-type", contentType);
|
|
1785
|
+
if ( request.overrideMimeType ) {
|
|
1786
|
+
request.overrideMimeType(contentType);
|
|
1787
|
+
}
|
|
1788
|
+
|
|
1789
|
+
request.onreadystatechange = check;
|
|
1790
|
+
try {
|
|
1791
|
+
request.send(null);
|
|
1792
|
+
}
|
|
1793
|
+
catch (e) {
|
|
1794
|
+
if ( clean ) {
|
|
1795
|
+
console.error(e);
|
|
1796
|
+
error && error();
|
|
1797
|
+
clean();
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1801
|
+
};
|
|
1802
|
+
|
|
1803
|
+
|
|
1804
|
+
// ============================== Packages ===============================
|
|
1805
|
+
/**
|
|
1806
|
+
* @function steal.packages
|
|
1807
|
+
* `steal.packages( packageIds... )` defines modules for deferred downloading.
|
|
1808
|
+
*
|
|
1809
|
+
* This is used by the build system to build collections of modules that will be downloaded
|
|
1810
|
+
* after initial page load.
|
|
1811
|
+
*
|
|
1812
|
+
* For example, an application that wants to progressively load the contents and
|
|
1813
|
+
* dependencies of _login/login.js_, _filemanager/filemanager.js_, and _contacts/contacts.js_,
|
|
1814
|
+
* while immediately loading the current users's data might look like:
|
|
1815
|
+
*
|
|
1816
|
+
* steal.packages('login','filemanager','contacts')
|
|
1817
|
+
* steal('models/user', function(User){
|
|
1818
|
+
*
|
|
1819
|
+
* // get the current User
|
|
1820
|
+
* User.findOne({id: "current"},
|
|
1821
|
+
*
|
|
1822
|
+
* // success - they logged in
|
|
1823
|
+
* function(user){
|
|
1824
|
+
* if(window.location.hash == "#filemanager"){
|
|
1825
|
+
* steal('filemanager')
|
|
1826
|
+
* }
|
|
1827
|
+
* },
|
|
1828
|
+
* // error - they are logged out
|
|
1829
|
+
* function(){
|
|
1830
|
+
* steal('login', function(){
|
|
1831
|
+
* new Login(document.body);
|
|
1832
|
+
* // preload filemanager
|
|
1833
|
+
*
|
|
1834
|
+
* })
|
|
1835
|
+
* })
|
|
1836
|
+
* })
|
|
1837
|
+
*
|
|
1838
|
+
*
|
|
1839
|
+
* steal.packages('tasks','dashboard','fileman');
|
|
1840
|
+
*
|
|
1841
|
+
*/
|
|
1842
|
+
var packs = [],
|
|
1843
|
+
packHash = {};
|
|
1844
|
+
steal.packages = function( map ) {
|
|
1845
|
+
|
|
1846
|
+
if (!arguments.length ) {
|
|
1847
|
+
return packs;
|
|
1848
|
+
} else {
|
|
1849
|
+
if ( typeof map == 'string' ) {
|
|
1850
|
+
packs.push.apply(packs, arguments);
|
|
1851
|
+
} else {
|
|
1852
|
+
packHash = map;
|
|
1853
|
+
}
|
|
1854
|
+
|
|
1855
|
+
return this;
|
|
1856
|
+
}
|
|
1857
|
+
};
|
|
1858
|
+
|
|
1859
|
+
|
|
1860
|
+
|
|
1861
|
+
// =============================== MAPPING ===============================
|
|
1862
|
+
URI.prototype.insertMapping = function() {
|
|
1863
|
+
// go through mappings
|
|
1864
|
+
var orig = "" + this,
|
|
1865
|
+
key, value;
|
|
1866
|
+
for ( key in steal.mappings ) {
|
|
1867
|
+
value = steal.mappings[key]
|
|
1868
|
+
if ( value.test.test(orig) ) {
|
|
1869
|
+
return orig.replace(key, value.path);
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1872
|
+
return URI(orig);
|
|
1873
|
+
};
|
|
1874
|
+
|
|
1875
|
+
// =============================== STARTUP ===============================
|
|
1876
|
+
var rootSteal = false;
|
|
1877
|
+
|
|
1878
|
+
// essentially ... we need to know when we are on our first steal
|
|
1879
|
+
// then we need to know when the collection of those steals ends ...
|
|
1880
|
+
// and, it helps if we use a 'collection' steal because of it's natural
|
|
1881
|
+
// use for going through the pending queue
|
|
1882
|
+
//
|
|
1883
|
+
extend(steal, {
|
|
1884
|
+
// modifies src
|
|
1885
|
+
/*makeOptions : after(steal.makeOptions,function(raw){
|
|
1886
|
+
raw.src = URI.root().join(raw.rootSrc = URI( raw.rootSrc ).insertMapping());
|
|
1887
|
+
}),*/
|
|
1888
|
+
|
|
1889
|
+
//root mappings to other locations
|
|
1890
|
+
mappings: {},
|
|
1891
|
+
|
|
1892
|
+
/**
|
|
1893
|
+
* Maps a 'rooted' folder to another location.
|
|
1894
|
+
* @param {String|Object} from the location you want to map from. For example:
|
|
1895
|
+
* 'foo/bar'
|
|
1896
|
+
* @param {String} [to] where you want to map this folder too. Ex: 'http://foo.cdn/bar'
|
|
1897
|
+
* @return {steal}
|
|
1898
|
+
*/
|
|
1899
|
+
map: function( from, to ) {
|
|
1900
|
+
if ( isString(from) ) {
|
|
1901
|
+
steal.mappings[from] = {
|
|
1902
|
+
test: new RegExp("^(\/?" + from + ")([/.]|$)"),
|
|
1903
|
+
path: to
|
|
1904
|
+
};
|
|
1905
|
+
each(resources, function( id, resource ) {
|
|
1906
|
+
if ( resource.options.type != "fn" ) {
|
|
1907
|
+
// TODO terrible
|
|
1908
|
+
var buildType = resource.options.buildType;
|
|
1909
|
+
resource.setOptions(resource.orig);
|
|
1910
|
+
resource.options.buildType = buildType;
|
|
1911
|
+
}
|
|
1912
|
+
})
|
|
1913
|
+
} else { // its an object
|
|
1914
|
+
each(from, steal.map);
|
|
1915
|
+
}
|
|
1916
|
+
return this;
|
|
1917
|
+
},
|
|
1918
|
+
// called after steals are added to the pending queue
|
|
1919
|
+
after: function() {
|
|
1920
|
+
// if we don't have a current 'top' steal
|
|
1921
|
+
// we create one and set it up
|
|
1922
|
+
// to start loading its dependencies (the current pending steals)
|
|
1923
|
+
if (!rootSteal ) {
|
|
1924
|
+
rootSteal = new Resource();
|
|
1925
|
+
// keep a reference in case it disappears
|
|
1926
|
+
var cur = rootSteal,
|
|
1927
|
+
// runs when a steal is starting
|
|
1928
|
+
go = function() {
|
|
1929
|
+
// indicates that a collection of steals has started
|
|
1930
|
+
steal.trigger("start", cur);
|
|
1931
|
+
cur.completed.then(function() {
|
|
1932
|
+
|
|
1933
|
+
rootSteal = null;
|
|
1934
|
+
steal.trigger("end", cur);
|
|
1935
|
+
|
|
1936
|
+
|
|
1937
|
+
});
|
|
1938
|
+
|
|
1939
|
+
cur.executed();
|
|
1940
|
+
};
|
|
1941
|
+
// If we are in the browser, wait a
|
|
1942
|
+
// brief timeout before executing the rootResource.
|
|
1943
|
+
// This allows embeded script tags with steal to be part of
|
|
1944
|
+
// the initial set
|
|
1945
|
+
if ( win.setTimeout ) {
|
|
1946
|
+
// we want to insert a "wait" after the current pending
|
|
1947
|
+
steal.pushPending();
|
|
1948
|
+
setTimeout(function() {
|
|
1949
|
+
steal.popPending();
|
|
1950
|
+
go();
|
|
1951
|
+
}, 0)
|
|
1952
|
+
} else {
|
|
1953
|
+
// if we are in rhino, start loading dependencies right away
|
|
1954
|
+
go()
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
},
|
|
1958
|
+
_before: before,
|
|
1959
|
+
_after: after
|
|
1960
|
+
});
|
|
1961
|
+
|
|
1962
|
+
(function(){
|
|
1963
|
+
var myPending;
|
|
1964
|
+
steal.pushPending = function(){
|
|
1965
|
+
myPending = pending.slice(0);
|
|
1966
|
+
pending = [];
|
|
1967
|
+
each(myPending, function(i, arg){
|
|
1968
|
+
Resource.make(arg);
|
|
1969
|
+
})
|
|
1970
|
+
}
|
|
1971
|
+
steal.popPending = function(){
|
|
1972
|
+
pending = pending.length ? myPending.concat(null,pending) : myPending;
|
|
1973
|
+
}
|
|
1974
|
+
})();
|
|
1975
|
+
|
|
1976
|
+
// =============================== jQuery ===============================
|
|
1977
|
+
(function() {
|
|
1978
|
+
var jQueryIncremented = false,
|
|
1979
|
+
jQ, ready = false;
|
|
1980
|
+
|
|
1981
|
+
// check if jQuery loaded after every script load ...
|
|
1982
|
+
Resource.prototype.executed = before(Resource.prototype.executed, function() {
|
|
1983
|
+
|
|
1984
|
+
var $ = win.jQuery;
|
|
1985
|
+
if ( $ && "readyWait" in $ ) {
|
|
1986
|
+
|
|
1987
|
+
//Increment jQuery readyWait if ncecessary.
|
|
1988
|
+
if (!jQueryIncremented ) {
|
|
1989
|
+
jQ = $;
|
|
1990
|
+
$.readyWait += 1;
|
|
1991
|
+
jQueryIncremented = true;
|
|
1992
|
+
}
|
|
1993
|
+
}
|
|
1994
|
+
});
|
|
1995
|
+
|
|
1996
|
+
// once the current batch is done, fire ready if it hasn't already been done
|
|
1997
|
+
steal.bind("end", function() {
|
|
1998
|
+
if ( jQueryIncremented && !ready ) {
|
|
1999
|
+
jQ.ready(true);
|
|
2000
|
+
ready = true;
|
|
2001
|
+
}
|
|
2002
|
+
})
|
|
2003
|
+
|
|
2004
|
+
|
|
2005
|
+
})();
|
|
2006
|
+
|
|
2007
|
+
// =============================== ERROR HANDLING ===============================
|
|
2008
|
+
extend(Resource.prototype, {
|
|
2009
|
+
load: after(Resource.prototype.load, function( stel ) {
|
|
2010
|
+
var self = this;
|
|
2011
|
+
if ( doc && !self.completed && !self.completeTimeout && !steal.isRhino && (self.options.src.protocol == "file" || !support.error) ) {
|
|
2012
|
+
self.completeTimeout = setTimeout(function() {
|
|
2013
|
+
throw "steal.js : " + self.options.src + " not completed"
|
|
2014
|
+
}, 5000);
|
|
2015
|
+
}
|
|
2016
|
+
}),
|
|
2017
|
+
complete: after(Resource.prototype.complete, function() {
|
|
2018
|
+
this.completeTimeout && clearTimeout(this.completeTimeout)
|
|
2019
|
+
}),
|
|
2020
|
+
|
|
2021
|
+
|
|
2022
|
+
// if we're about to mark a file as executed, mark its "has" array files as
|
|
2023
|
+
// executed also
|
|
2024
|
+
executed: before(Resource.prototype.executed, function() {
|
|
2025
|
+
if ( this.options.has ) {
|
|
2026
|
+
this.loadHas();
|
|
2027
|
+
}
|
|
2028
|
+
}),
|
|
2029
|
+
|
|
2030
|
+
/**
|
|
2031
|
+
* @hide
|
|
2032
|
+
* Goes through the array of files listed in this.options.has, marks them all as loaded.
|
|
2033
|
+
* This is used for files like production.css, which, once they load, need to mark the files they
|
|
2034
|
+
* contain as loaded.
|
|
2035
|
+
*/
|
|
2036
|
+
loadHas: function() {
|
|
2037
|
+
var stel, i, current = URI.cur;
|
|
2038
|
+
|
|
2039
|
+
if ( this.options.buildType == 'js' ) {
|
|
2040
|
+
return;
|
|
2041
|
+
}
|
|
2042
|
+
|
|
2043
|
+
// mark everything in has loaded
|
|
2044
|
+
each(this.options.has, function( i, has ) {
|
|
2045
|
+
// don't want the current file to change, since we're just marking files as loaded
|
|
2046
|
+
URI.cur = URI(current);
|
|
2047
|
+
steal.executed(has);
|
|
2048
|
+
});
|
|
2049
|
+
|
|
2050
|
+
}
|
|
2051
|
+
});
|
|
2052
|
+
|
|
2053
|
+
// =========== HAS ARRAY STUFF ============
|
|
2054
|
+
// Logic that deals with files that have collections of other files within
|
|
2055
|
+
// them. This is usually a production.css file,
|
|
2056
|
+
// which when it loads, needs to mark several CSS and LESS files it represents
|
|
2057
|
+
// as being "loaded". This is done by the production.js file having
|
|
2058
|
+
// steal({src: "production.css", has: ["file1.css", "file2.css"]
|
|
2059
|
+
//
|
|
2060
|
+
// after a steal is created, if its been loaded
|
|
2061
|
+
// already and has a "has", mark those files as loaded
|
|
2062
|
+
Resource.make = after(Resource.make, function( stel ) {
|
|
2063
|
+
// if we have things
|
|
2064
|
+
if ( stel.options.has ) {
|
|
2065
|
+
// if we have loaded this already (and we are adding has's)
|
|
2066
|
+
if ( stel.run.isResolved() ) {
|
|
2067
|
+
stel.loadHas();
|
|
2068
|
+
} else {
|
|
2069
|
+
// have to mark has as loading and executing (so we don't try to get them)
|
|
2070
|
+
steal.has.apply(steal, stel.options.has)
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
return stel;
|
|
2074
|
+
}, true);
|
|
2075
|
+
|
|
2076
|
+
|
|
2077
|
+
|
|
2078
|
+
|
|
2079
|
+
// =========== DEBUG =========
|
|
2080
|
+
|
|
2081
|
+
|
|
2082
|
+
/*var name = function(stel){
|
|
2083
|
+
if(stel.options && stel.options.type == "fn"){
|
|
2084
|
+
return stel.orig.name? stel.orig.name : stel.options.id+":fn";//(""+stel.orig).substr(0,10)
|
|
2085
|
+
}
|
|
2086
|
+
return stel.options ? stel.options.id + "": "CONTAINER"
|
|
2087
|
+
}
|
|
2088
|
+
|
|
2089
|
+
|
|
2090
|
+
//Resource.prototype.load = before( Resource.prototype.load, function(){
|
|
2091
|
+
// console.log(" load", name(this), this.loading, steal._id, this.id)
|
|
2092
|
+
//})
|
|
2093
|
+
|
|
2094
|
+
Resource.prototype.executed = before(Resource.prototype.executed, function(){
|
|
2095
|
+
var namer= name(this)
|
|
2096
|
+
console.log(" executed", namer, steal._id, this.id)
|
|
2097
|
+
})
|
|
2098
|
+
|
|
2099
|
+
Resource.prototype.complete = before(Resource.prototype.complete, function(){
|
|
2100
|
+
console.log(" complete", name(this), steal._id, this.id)
|
|
2101
|
+
})*/
|
|
2102
|
+
|
|
2103
|
+
|
|
2104
|
+
|
|
2105
|
+
// ============= WINDOW LOAD ========
|
|
2106
|
+
var addEvent = function( elem, type, fn ) {
|
|
2107
|
+
if ( elem.addEventListener ) {
|
|
2108
|
+
elem.addEventListener(type, fn, false);
|
|
2109
|
+
} else if ( elem.attachEvent ) {
|
|
2110
|
+
elem.attachEvent("on" + type, fn);
|
|
2111
|
+
} else {
|
|
2112
|
+
fn();
|
|
2113
|
+
}
|
|
2114
|
+
},
|
|
2115
|
+
loaded = {
|
|
2116
|
+
load: Deferred(),
|
|
2117
|
+
end: Deferred()
|
|
2118
|
+
},
|
|
2119
|
+
firstEnd = false;
|
|
2120
|
+
|
|
2121
|
+
addEvent(win, "load", function() {
|
|
2122
|
+
loaded.load.resolve();
|
|
2123
|
+
});
|
|
2124
|
+
|
|
2125
|
+
steal.one("end", function( collection ) {
|
|
2126
|
+
loaded.end.resolve(collection);
|
|
2127
|
+
firstEnd = collection;
|
|
2128
|
+
steal.trigger("done", firstEnd)
|
|
2129
|
+
})
|
|
2130
|
+
steal.firstComplete = loaded.end;
|
|
2131
|
+
|
|
2132
|
+
Deferred.when(loaded.load, loaded.end).then(function() {
|
|
2133
|
+
steal.trigger("ready")
|
|
2134
|
+
steal.isReady = true;
|
|
2135
|
+
});
|
|
2136
|
+
|
|
2137
|
+
steal.events.done = {
|
|
2138
|
+
add: function( cb ) {
|
|
2139
|
+
if ( firstEnd ) {
|
|
2140
|
+
cb(firstEnd);
|
|
2141
|
+
return false;
|
|
2142
|
+
} else {
|
|
2143
|
+
return cb;
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
2146
|
+
};
|
|
2147
|
+
|
|
2148
|
+
|
|
2149
|
+
|
|
2150
|
+
// =========== INTERACTIVE STUFF ===========
|
|
2151
|
+
// Logic that deals with making steal work with IE. IE executes scripts out of order, so in order to tell which scripts are
|
|
2152
|
+
// dependencies of another, steal needs to check which is the currently "interactive" script.
|
|
2153
|
+
var interactiveScript,
|
|
2154
|
+
// key is script name, value is array of pending items
|
|
2155
|
+
interactives = {},
|
|
2156
|
+
getInteractiveScript = function() {
|
|
2157
|
+
var scripts = getElementsByTagName("script"),
|
|
2158
|
+
i = scripts.length;
|
|
2159
|
+
while ( i-- ) {
|
|
2160
|
+
if ( scripts[i].readyState === "interactive" ) {
|
|
2161
|
+
return scripts[i];
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
},
|
|
2165
|
+
getCachedInteractiveScript = function() {
|
|
2166
|
+
if ( interactiveScript && interactiveScript.readyState === 'interactive' ) {
|
|
2167
|
+
return interactiveScript;
|
|
2168
|
+
}
|
|
2169
|
+
|
|
2170
|
+
if ( interactiveScript = getInteractiveScript() ) {
|
|
2171
|
+
return interactiveScript;
|
|
2172
|
+
}
|
|
2173
|
+
|
|
2174
|
+
// check last inserted
|
|
2175
|
+
if ( lastInserted && lastInserted.readyState == 'interactive' ) {
|
|
2176
|
+
return lastInserted;
|
|
2177
|
+
}
|
|
2178
|
+
|
|
2179
|
+
return null;
|
|
2180
|
+
};
|
|
2181
|
+
|
|
2182
|
+
|
|
2183
|
+
support.interactive = doc && !! getInteractiveScript();
|
|
2184
|
+
|
|
2185
|
+
if ( support.interactive ) {
|
|
2186
|
+
|
|
2187
|
+
// after steal is called, check which script is "interactive" (for IE)
|
|
2188
|
+
steal.after = after(steal.after, function() {
|
|
2189
|
+
|
|
2190
|
+
// check if disabled by steal.loading()
|
|
2191
|
+
if (!support.interactive ) {
|
|
2192
|
+
return;
|
|
2193
|
+
}
|
|
2194
|
+
|
|
2195
|
+
var interactive = getCachedInteractiveScript();
|
|
2196
|
+
// if no interactive script, this is a steal coming from inside a steal, let complete handle it
|
|
2197
|
+
if (!interactive || !interactive.src || /steal\.(production|production\.[a-zA-Z0-9\-\.\_]*)*js/.test(interactive.src) ) {
|
|
2198
|
+
return;
|
|
2199
|
+
}
|
|
2200
|
+
// get the source of the script
|
|
2201
|
+
var src = interactive.src;
|
|
2202
|
+
// create an array to hold all steal calls for this script
|
|
2203
|
+
if (!interactives[src] ) {
|
|
2204
|
+
interactives[src] = []
|
|
2205
|
+
}
|
|
2206
|
+
// add to the list of steals for this script tag
|
|
2207
|
+
if ( src ) {
|
|
2208
|
+
interactives[src].push.apply(interactives[src], pending);
|
|
2209
|
+
pending = [];
|
|
2210
|
+
}
|
|
2211
|
+
})
|
|
2212
|
+
|
|
2213
|
+
// This is used for packaged scripts. As the packaged script executes, we grab the
|
|
2214
|
+
// dependencies that have come so far and assign them to the loaded script
|
|
2215
|
+
steal.preexecuted = before(steal.preexecuted, function( stel ) {
|
|
2216
|
+
// check if disabled by steal.loading()
|
|
2217
|
+
if (!support.interactive ) {
|
|
2218
|
+
return;
|
|
2219
|
+
}
|
|
2220
|
+
|
|
2221
|
+
// get the src name
|
|
2222
|
+
var src = stel.options.src,
|
|
2223
|
+
// and the src of the current interactive script
|
|
2224
|
+
interactiveSrc = getCachedInteractiveScript().src;
|
|
2225
|
+
|
|
2226
|
+
interactives[src] = interactives[interactiveSrc];
|
|
2227
|
+
interactives[interactiveSrc] = null;
|
|
2228
|
+
|
|
2229
|
+
})
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2232
|
+
|
|
2233
|
+
// ## Config ##
|
|
2234
|
+
var stealCheck = /steal\.(production\.)?js.*/,
|
|
2235
|
+
getStealScriptSrc = function() {
|
|
2236
|
+
if (!doc ) {
|
|
2237
|
+
return;
|
|
2238
|
+
}
|
|
2239
|
+
var scripts = getElementsByTagName("script"),
|
|
2240
|
+
script;
|
|
2241
|
+
|
|
2242
|
+
// find the steal script and setup initial paths.
|
|
2243
|
+
each(scripts, function( i, s ) {
|
|
2244
|
+
if ( stealCheck.test(s.src) ) {
|
|
2245
|
+
script = s;
|
|
2246
|
+
}
|
|
2247
|
+
});
|
|
2248
|
+
return script;
|
|
2249
|
+
};
|
|
2250
|
+
|
|
2251
|
+
steal.getScriptOptions = function( script ) {
|
|
2252
|
+
|
|
2253
|
+
var options = {},
|
|
2254
|
+
parts, src, query, startFile, env;
|
|
2255
|
+
|
|
2256
|
+
script = script || getStealScriptSrc();
|
|
2257
|
+
|
|
2258
|
+
if ( script ) {
|
|
2259
|
+
|
|
2260
|
+
// Split on question mark to get query
|
|
2261
|
+
parts = script.src.split("?");
|
|
2262
|
+
src = parts.shift();
|
|
2263
|
+
query = parts.join("?");
|
|
2264
|
+
|
|
2265
|
+
// Split on comma to get startFile and env
|
|
2266
|
+
parts = query.split(",");
|
|
2267
|
+
|
|
2268
|
+
if ( src.indexOf("steal.production") > -1 ) {
|
|
2269
|
+
options.env = "production";
|
|
2270
|
+
}
|
|
2271
|
+
|
|
2272
|
+
// Grab startFile
|
|
2273
|
+
startFile = parts[0];
|
|
2274
|
+
|
|
2275
|
+
if ( startFile ) {
|
|
2276
|
+
if ( startFile.indexOf(".js") == -1 ) {
|
|
2277
|
+
startFile += "/" + startFile.split("/").pop() + ".js";
|
|
2278
|
+
}
|
|
2279
|
+
options.startFile = startFile;
|
|
2280
|
+
}
|
|
2281
|
+
|
|
2282
|
+
// Grab env
|
|
2283
|
+
env = parts[1];
|
|
2284
|
+
|
|
2285
|
+
if ( env ) {
|
|
2286
|
+
options.env = env;
|
|
2287
|
+
}
|
|
2288
|
+
|
|
2289
|
+
// Split on / to get rootUrl
|
|
2290
|
+
parts = src.split("/")
|
|
2291
|
+
parts.pop();
|
|
2292
|
+
if ( parts[parts.length - 1] == "steal" ) {
|
|
2293
|
+
parts.pop();
|
|
2294
|
+
}
|
|
2295
|
+
options.root = parts.join("/")
|
|
2296
|
+
|
|
2297
|
+
}
|
|
2298
|
+
|
|
2299
|
+
return options;
|
|
2300
|
+
};
|
|
2301
|
+
|
|
2302
|
+
startup = after(startup, function() {
|
|
2303
|
+
// get options from
|
|
2304
|
+
var options = {};
|
|
2305
|
+
|
|
2306
|
+
// A: GET OPTIONS
|
|
2307
|
+
// 1. get script options
|
|
2308
|
+
extend(options, steal.getScriptOptions());
|
|
2309
|
+
|
|
2310
|
+
// 2. options from a steal object that existed before this steal
|
|
2311
|
+
extend(options, opts);
|
|
2312
|
+
|
|
2313
|
+
// 3. if url looks like steal[xyz]=bar, add those to the options
|
|
2314
|
+
// does this ened to be supported anywhere?
|
|
2315
|
+
var search = win.location && decodeURIComponent(win.location.search);
|
|
2316
|
+
search && search.replace(/steal\[([^\]]+)\]=([^&]+)/g, function( whoe, prop, val ) {
|
|
2317
|
+
options[prop] = ~val.indexOf(",") ? val.split(",") : val;
|
|
2318
|
+
});
|
|
2319
|
+
|
|
2320
|
+
// B: DO THINGS WITH OPTIONS
|
|
2321
|
+
// CALCULATE CURRENT LOCATION OF THINGS ...
|
|
2322
|
+
steal.config(options);
|
|
2323
|
+
|
|
2324
|
+
|
|
2325
|
+
// mark things that have already been loaded
|
|
2326
|
+
each(options.executed || [], function( i, stel ) {
|
|
2327
|
+
steal.executed(stel)
|
|
2328
|
+
})
|
|
2329
|
+
// immediate steals we do
|
|
2330
|
+
var steals = [];
|
|
2331
|
+
|
|
2332
|
+
// add start files first
|
|
2333
|
+
if ( options.startFiles ) {
|
|
2334
|
+
/// this can be a string or an array
|
|
2335
|
+
steals.push.apply(steals, isString(options.startFiles) ? [options.startFiles] : options.startFiles)
|
|
2336
|
+
options.startFiles = steals.slice(0)
|
|
2337
|
+
}
|
|
2338
|
+
|
|
2339
|
+
// either instrument is in this page (if we're the window opened from
|
|
2340
|
+
// steal.browser), or its opener has it
|
|
2341
|
+
// try-catching this so we dont have to build up to the iframe
|
|
2342
|
+
// instrumentation check
|
|
2343
|
+
try {
|
|
2344
|
+
// win.top.steal.instrument is for qunit
|
|
2345
|
+
// win.top.opener.steal.instrument is for funcunit
|
|
2346
|
+
if(!options.browser && ((win.top && win.top.steal.instrument) ||
|
|
2347
|
+
(win.top && win.top.opener && win.top.opener.steal && win.top.opener.steal.instrument))) {
|
|
2348
|
+
|
|
2349
|
+
// force startFiles to load before instrument
|
|
2350
|
+
steals.push(noop, {
|
|
2351
|
+
id: "steal/instrument",
|
|
2352
|
+
waits: true
|
|
2353
|
+
});
|
|
2354
|
+
}
|
|
2355
|
+
} catch (e) {
|
|
2356
|
+
// This would throw permission denied if
|
|
2357
|
+
// the child window was from a different domain
|
|
2358
|
+
}
|
|
2359
|
+
|
|
2360
|
+
// we only load things with force = true
|
|
2361
|
+
if ( stealConfig.env == "production" && stealConfig.loadProduction && stealConfig.production ) {
|
|
2362
|
+
steal({
|
|
2363
|
+
id: stealConfig.production,
|
|
2364
|
+
force: true
|
|
2365
|
+
});
|
|
2366
|
+
} else {
|
|
2367
|
+
steals.unshift("stealconfig.js")
|
|
2368
|
+
|
|
2369
|
+
if ( options.loadDev !== false ) {
|
|
2370
|
+
steals.unshift({
|
|
2371
|
+
id: "steal/dev/dev.js",
|
|
2372
|
+
ignore: true
|
|
2373
|
+
});
|
|
2374
|
+
}
|
|
2375
|
+
|
|
2376
|
+
if ( options.startFile ) {
|
|
2377
|
+
steals.push(null,options.startFile)
|
|
2378
|
+
}
|
|
2379
|
+
}
|
|
2380
|
+
if ( steals.length ) {
|
|
2381
|
+
steal.apply(win, steals);
|
|
2382
|
+
}
|
|
2383
|
+
});
|
|
2384
|
+
|
|
2385
|
+
|
|
2386
|
+
// ## AMD ##
|
|
2387
|
+
var modules = {
|
|
2388
|
+
|
|
2389
|
+
};
|
|
2390
|
+
|
|
2391
|
+
// convert resources to modules ...
|
|
2392
|
+
// a function is a module definition piece
|
|
2393
|
+
// you steal(moduleId1, moduleId2, function(module1, module2){});
|
|
2394
|
+
//
|
|
2395
|
+
win.define = function( moduleId, dependencies, method ) {
|
|
2396
|
+
if(typeof moduleId == 'function'){
|
|
2397
|
+
modules[URI.cur+""] = moduleId();
|
|
2398
|
+
} else if(!method && dependencies){
|
|
2399
|
+
if(typeof dependencies == "function"){
|
|
2400
|
+
modules[moduleId] = dependencies();
|
|
2401
|
+
} else {
|
|
2402
|
+
modules[moduleId] = dependencies;
|
|
2403
|
+
}
|
|
2404
|
+
|
|
2405
|
+
} else if (dependencies && method && !dependencies.length ) {
|
|
2406
|
+
modules[moduleId] = method();
|
|
2407
|
+
} else {
|
|
2408
|
+
steal.apply(null, map(dependencies, function(dependency){
|
|
2409
|
+
dependency = typeof dependency === "string" ? {
|
|
2410
|
+
id: dependency
|
|
2411
|
+
} : dependency;
|
|
2412
|
+
dependency.toId = steal.amdToId;
|
|
2413
|
+
|
|
2414
|
+
dependency.idToUri = steal.amdIdToUri;
|
|
2415
|
+
return dependency;
|
|
2416
|
+
}).concat(method) )
|
|
2417
|
+
}
|
|
2418
|
+
|
|
2419
|
+
}
|
|
2420
|
+
win.require = function(dependencies, method){
|
|
2421
|
+
var depends = map(dependencies, function(dependency){
|
|
2422
|
+
dependency = typeof dependency === "string" ? {
|
|
2423
|
+
id: dependency
|
|
2424
|
+
} : dependency;
|
|
2425
|
+
dependency.toId = steal.amdToId;
|
|
2426
|
+
|
|
2427
|
+
dependency.idToUri = steal.amdIdToUri;
|
|
2428
|
+
return dependency;
|
|
2429
|
+
}).concat([method]);
|
|
2430
|
+
console.log("stealing",depends.slice(0))
|
|
2431
|
+
steal.apply(null, depends )
|
|
2432
|
+
}
|
|
2433
|
+
win.define.amd = {
|
|
2434
|
+
jQuery: true
|
|
2435
|
+
}
|
|
2436
|
+
|
|
2437
|
+
|
|
2438
|
+
//steal.when = when;
|
|
2439
|
+
// make steal public
|
|
2440
|
+
win.steal = steal;
|
|
2441
|
+
|
|
2442
|
+
|
|
2443
|
+
// make steal loaded
|
|
2444
|
+
define("steal", [], function() {
|
|
2445
|
+
return steal;
|
|
2446
|
+
});
|
|
2447
|
+
|
|
2448
|
+
define("require",function(){
|
|
2449
|
+
return require;
|
|
2450
|
+
})
|
|
2451
|
+
|
|
2452
|
+
var stealResource = new Resource("steal")
|
|
2453
|
+
stealResource.value = steal;
|
|
2454
|
+
stealResource.loaded.resolve();
|
|
2455
|
+
stealResource.run.resolve();
|
|
2456
|
+
stealResource.executing = true;
|
|
2457
|
+
stealResource.completed.resolve();
|
|
2458
|
+
|
|
2459
|
+
resources[stealResource.options.id] = stealResource;
|
|
2460
|
+
|
|
2461
|
+
startup();
|
|
2462
|
+
//win.steals = steals;
|
|
2463
|
+
win.steal.resources = resources;
|
|
2464
|
+
win.Resource = Resource;
|
|
2465
|
+
|
|
2466
|
+
})(this);
|