Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 757 lines (672 sloc) 32.946 kb
0a4294f Jakob Heuser first commit
Jakobo authored
1 ###
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
2 # Inject: Dependency Awesomeness #
0a4294f Jakob Heuser first commit
Jakobo authored
3
cc47e42 Jakob Heuser readme made, standardized variable names
Jakobo authored
4 Some sample ways to use inject...
cbe4aa6 Jakob Heuser 0.2.0 API change isn't backwards compatible. require() now the standard ...
Jakobo authored
5 var foo = require("moduleName");
6 require.ensure(["moduleOne", "moduleTwo", "moduleThree"], function(require, exports, module) {
7 var foo = require("moduleOne");
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
8 })
0a4294f Jakob Heuser first commit
Jakobo authored
9
cbe4aa6 Jakob Heuser 0.2.0 API change isn't backwards compatible. require() now the standard ...
Jakobo authored
10 Configuring Inject
11 require.setModuleRoot("http://example.com/path/to/js/root")
12 require.setCrossDomain("http://local.example.com/path/to/relay.html", "http://remote.example.com/path/to/relay.html")
13 require.manifest({
14 moduleName: "http://local.example.com/path/to/module"
15 }, [weight])
16 require.manifest(function(path) {
17
18 }, [weight])
19 require.run("appName")
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
20
21 For more details, check out the README or github: https://github.com/Jakobo/inject
0a4294f Jakob Heuser first commit
Jakobo authored
22 ###
23
99d20c0 Jakob Heuser Cleans up #1 coffeescript, adds comments
Jakobo authored
24 #
25 # Conventions and syntax for inject() for contributions
26 #
27 # CoffeeScript @ 2 spaces indent
28 #
29 # Parentheses () required at all times except:
30 # * Statement is single line, single argument: someValue.push pushableItem
31 # * Statement is single line, last argument is a callback: someAsyncFunction argOne, argTwo, (cbOne, cbTwo) ->
32 #
33 # Over Comment
34 #
35 # Always run "cake build" and make sure it compiles. Testing is also a bonus
36 #
37
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
38 ###
39 Constants and Registries used
40 ###
41 schemaVersion = 1 # version of inject()'s localstorage schema
42 context = this # context is our local scope. Should be "window"
abbd0b0 Jakob Heuser added docs for #1, added default file expiry, updated readme
Jakobo authored
43 pauseRequired = false # can we run immediately? when using iframe transport, the answer is no
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
44 fileRegistry = null # a registry of file text that has been loaded
abbd0b0 Jakob Heuser added docs for #1, added default file expiry, updated readme
Jakobo authored
45 xDomainRpc = null # a cross domain RPC object (Porthole)
8696542 Fermin Simeon Replaced PersistJs with lscache
fsimeon authored
46 fileStorageToken = "FILEDB" # a storagetoken identifier we use (lscache)
f57166e merging in cache expiration support
Eugene O'Neill authored
47 fileStore = "Inject FileStorage" # file store to use
cbe4aa6 Jakob Heuser 0.2.0 API change isn't backwards compatible. require() now the standard ...
Jakobo authored
48 namespace = "Inject" # the namespace for inject() that is publicly reachable
ff0a9ce Fermin Simeon Retiring PersistJS, moved expiration handling to lscache
fsimeon authored
49 fileExpiration = 1440 # the default time (in minutes lscache) to cache a file for (one day)
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
50 counter = 0 # a counter used for transaction IDs
561d11e Jakob Heuser initial pointcut support for #7. Not documented, but can now use before ...
Jakobo authored
51 loadQueue = [] # when making iframe calls, there's a queue that can stack up while waiting on everything to load
52 userModules = {} # any mappings for module => handling defined by the user
336caf2 Jakob Heuser addrule prototype
Jakobo authored
53 rules = [] # a collection of rules to run
54 rulesDirty = false # a dirty flag for the rules
55 sortedRules = [] # a sorted state for the rules
561d11e Jakob Heuser initial pointcut support for #7. Not documented, but can now use before ...
Jakobo authored
56 moduleRegistry = {} # a registry of modules that have been loaded
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
57 modulePathRegistry = {} # a collection of modules organized by their path information
58 callbackRegistry = {} # a registry of callbacks keyed by Transaction IDs
59 txnRegistry = {} # a list of modules that were required for a transaction, keyed by Transaction IDs
60 fileOnComplete = {} # a list of subscribing transactions for a file's onModuleLoad resolution, keyed by Path
abbd0b0 Jakob Heuser added docs for #1, added default file expiry, updated readme
Jakobo authored
61 config = # This is the default config when no changes are made
62 fileExpiration: fileExpiration # default file expiry
561d11e Jakob Heuser initial pointcut support for #7. Not documented, but can now use before ...
Jakobo authored
63 jsSuffix = /.*?\.js$/ # Regex for identifying things that end in *.js
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
64 hostPrefixRegex = /^https?:\/\// # prefixes for URLs that begin with http/https
65 hostSuffixRegex = /^(.*?)(\/.*|$)/ # suffix for URLs used to capture everything up to / or the end of the string
66 iframeName = "injectProxy" # the name for the iframe proxy created (Porthole)
67 requireRegex = /// # a regex for capturing the require() statements inside of included code
68 require[\s]*\([\s]* # followed by require, a whitespace character 0+, and an opening ( then more whitespace
5fdcf14 Jakob Heuser changes to .exec() from MP, cleaned up regex
Jakobo authored
69 (?:"|') # followed by a quote
e6ba391 Jakob Heuser #30 regex error from coffeescript, / was auto escaped
Jakobo authored
70 ([\w/\.\:]+?) # (1) capture word characters, forward slashes, dots, and colons (at least one)
5fdcf14 Jakob Heuser changes to .exec() from MP, cleaned up regex
Jakobo authored
71 (?:'|") # followed by a quote
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
72 [\s]*\) # followed by whitespace, and then a closing ) that ends the require() call
2ebb97f Jakob Heuser #9 fixes for requires
Jakobo authored
73 ///gm
561d11e Jakob Heuser initial pointcut support for #7. Not documented, but can now use before ...
Jakobo authored
74 responseSlicer = /// # a regular expression for slicing a response from iframe communication into its parts
75 ^(.+?)[\s] # (1) Begins with anything up to a space
76 (.+?)[\s] # (2) Continues with anything up to a space
77 (.+?)[\s] # (3) Continues with anything up to a space
78 ([\w\W]+)$ # (4) Any text up until the end of the string
79 ///m # Supports multiline expressions
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
80
81 ###
82 CommonJS wrappers for a header and footer
83 these bookend the included code and insulate the scope so that it doesn't impact inject()
84 or anything else.
85 this helps secure module bleeding
86 ###
87 commonJSHeader = '''
88 with (window) {
89 (function() {
cbe4aa6 Jakob Heuser 0.2.0 API change isn't backwards compatible. require() now the standard ...
Jakobo authored
90 var module = {}, exports = {}, require = __INJECT_NS__.require, exe = null;
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
91 module.id = "__MODULE_ID__";
92 module.uri = "__MODULE_URI__";
93 module.exports = exports;
f574bd9 Fermin Simeon fixed to check for object definition instead of just function type
fsimeon authored
94 module.setExports = function(xobj) {
95 for (var name in module.exports) {
96 if (module.exports.hasOwnProperty(name)) {
97 throw new Error("module.setExports() failed: Module Exports has already been defined");
98 }
8b98b41 Fermin Simeon added module.setExports function
fsimeon authored
99 }
100 module.exports = xobj;
101 return module.exports;
102 }
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
103 exe = function(module, exports, require) {
561d11e Jakob Heuser initial pointcut support for #7. Not documented, but can now use before ...
Jakobo authored
104 __POINTCUT_BEFORE__
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
105 '''
106 commonJSFooter = '''
561d11e Jakob Heuser initial pointcut support for #7. Not documented, but can now use before ...
Jakobo authored
107 __POINTCUT_AFTER__
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
108 };
109 exe.call(module, module, exports, require);
110 return module.exports;
111 })();
112 }
113 '''
0a4294f Jakob Heuser first commit
Jakobo authored
114 setConfig = (cfg) ->
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
115 ###
116 ## setConfig(cfg) ##
117 _internal_ Set the config
118 ###
0a4294f Jakob Heuser first commit
Jakobo authored
119 config = cfg
f57166e merging in cache expiration support
Eugene O'Neill authored
120 # defaults
121 if !config.fileExpiration? then config.fileExpiration = fileExpiration
0a4294f Jakob Heuser first commit
Jakobo authored
122
123 setUserModules = (modl) ->
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
124 ###
125 ## setUserModules(modl) ##
126 _internal_ Set the collection of user defined modules
127 ###
0a4294f Jakob Heuser first commit
Jakobo authored
128 userModules = modl
129
130 getModule = (module) ->
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
131 ###
132 ## getModule(module) ##
133 _internal_ Get a module by name
134 ###
0a4294f Jakob Heuser first commit
Jakobo authored
135 return moduleRegistry[module] or false
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
136
0a4294f Jakob Heuser first commit
Jakobo authored
137 saveModule = (module, exports) ->
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
138 ###
139 ## saveModule(module, exports) ##
140 _internal_ Save a module by name
141 ###
0a4294f Jakob Heuser first commit
Jakobo authored
142 if moduleRegistry[module] then return
f57166e merging in cache expiration support
Eugene O'Neill authored
143 moduleRegistry[module] = exports
144
145 isCached = (path) ->
146 ###
147 ## isCached(mpath) ##
ff0a9ce Fermin Simeon Retiring PersistJS, moved expiration handling to lscache
fsimeon authored
148 _internal_ test if a file is in the cache validity has been moved to lscache
f57166e merging in cache expiration support
Eugene O'Neill authored
149 ###
ff0a9ce Fermin Simeon Retiring PersistJS, moved expiration handling to lscache
fsimeon authored
150 return fileRegistry? and fileRegistry[path]?
0a4294f Jakob Heuser first commit
Jakobo authored
151
d245b70 Jakob Heuser local storage enabled and tested n chrome
Jakobo authored
152 getFile = (path, cb) ->
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
153 ###
154 ## getFile(path, cb) ##
155 _internal_ Get a file by its path. Asynchronously calls its callback.
156 Uses LocalStorage or UserData if available
157 ###
ff0a9ce Fermin Simeon Retiring PersistJS, moved expiration handling to lscache
fsimeon authored
158 token = "#{fileStorageToken}#{schemaVersion}#{path}"
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
159
d245b70 Jakob Heuser local storage enabled and tested n chrome
Jakobo authored
160 if !fileRegistry
ff0a9ce Fermin Simeon Retiring PersistJS, moved expiration handling to lscache
fsimeon authored
161 fileRegistry = {}
162
163 if fileRegistry[path] and fileRegistry[path].length
164 # the file registry object exists, so we have loaded the content
165 # return the content with the cb set to true
166 return cb(true, fileRegistry[path])
167 else
99d20c0 Jakob Heuser Cleans up #1 coffeescript, adds comments
Jakobo authored
168 # With no file registry, attempt to load from local storage
169 # if the token exists, parse it. If the path is cached, then use the cached item
170 # otherwise, mark the item as false
171 # if there is nothing in cache, create the fileRegistry object
ff0a9ce Fermin Simeon Retiring PersistJS, moved expiration handling to lscache
fsimeon authored
172 file = lscache.get(token)
8696542 Fermin Simeon Replaced PersistJs with lscache
fsimeon authored
173 if file and typeof(file) is "string" and file.length
ff0a9ce Fermin Simeon Retiring PersistJS, moved expiration handling to lscache
fsimeon authored
174 fileRegistry[path] = file
175 return cb(true, fileRegistry[path])
8696542 Fermin Simeon Replaced PersistJs with lscache
fsimeon authored
176 else
177 return cb(false, null)
ff0a9ce Fermin Simeon Retiring PersistJS, moved expiration handling to lscache
fsimeon authored
178
d245b70 Jakob Heuser local storage enabled and tested n chrome
Jakobo authored
179
0a4294f Jakob Heuser first commit
Jakobo authored
180 saveFile = (path, file) ->
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
181 ###
182 ## saveFile(path, file) ##
183 _internal_ Save a file for resource `path` into LocalStorage or UserData
184 Also updates the internal fileRegistry
185 ###
ff0a9ce Fermin Simeon Retiring PersistJS, moved expiration handling to lscache
fsimeon authored
186 token = "#{fileStorageToken}#{schemaVersion}#{path}"
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
187
99d20c0 Jakob Heuser Cleans up #1 coffeescript, adds comments
Jakobo authored
188 if isCached(path) then return
ff0a9ce Fermin Simeon Retiring PersistJS, moved expiration handling to lscache
fsimeon authored
189 fileRegistry[path] = file
190 # using minutes convention because lscache does the expire conversion in added minutes
191 lscache.set(token, file, config.fileExpiration)
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
192
193 clearFileRegistry = (version = schemaVersion) ->
194 ###
195 ## clearFileRegistry(version = schemaVersion) ##
196 _internal_ Clears the internal file registry at `version`
ff0a9ce Fermin Simeon Retiring PersistJS, moved expiration handling to lscache
fsimeon authored
197 clearing all local storage keys that relate to the fileStorageToken and version
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
198 ###
199 token = "#{fileStorageToken}#{version}"
85b3d57 Jakob Heuser updaed 0.1.0 examples and syntax to be a bit cleaner, tidy for build sys...
Jakobo authored
200
ff0a9ce Fermin Simeon Retiring PersistJS, moved expiration handling to lscache
fsimeon authored
201 lscache.remove(lkey) for lkey,file of localStorage when lkey.indexOf(token) isnt -1
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
202 if version == schemaVersion then fileRegistry = {}
203
0a4294f Jakob Heuser first commit
Jakobo authored
204 createTxId = () ->
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
205 ###
206 ## createTxId() ##
207 _internal_ create a transaction id
208 ###
0a4294f Jakob Heuser first commit
Jakobo authored
209 return "txn_#{counter++}"
210
211 createIframe = () ->
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
212 ###
213 ## createIframe() ##
214 _internal_ create an iframe to the config.xd.remote location
215 ###
cc47e42 Jakob Heuser readme made, standardized variable names
Jakobo authored
216 src = config?.xd?.xhr
217 localSrc = config?.xd?.inject
0a4294f Jakob Heuser first commit
Jakobo authored
218 if !src then throw new Error("Configuration requires xd.remote to be defined")
219 if !localSrc then throw new Error("Configuration requires xd.local to be defined")
220
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
221 # trims the host down to its essential values
0a4294f Jakob Heuser first commit
Jakobo authored
222 trimHost = (host) ->
223 host = host.replace(hostPrefixRegex, "").replace(hostSuffixRegex, "$1")
224 return host
225
226 try
227 iframe = document.createElement("<iframe name=\"" + iframeName + "\"/>")
228 catch err
229 iframe = document.createElement("iframe")
230 iframe.name = iframeName
231 iframe.src = src+"#xhr"
232 iframe.style.width = iframe.style.height = "1px"
233 iframe.style.right = iframe.style.bottom = "0px"
234 iframe.style.position = "absolute"
235 iframe.id = iframeName
236 document.body.insertBefore(iframe, document.body.firstChild)
237
238 # Create a proxy window to send to and receive message from the guest iframe
cc47e42 Jakob Heuser readme made, standardized variable names
Jakobo authored
239 xDomainRpc = new Porthole.WindowProxy(config.xd.xhr+"#xhr", iframeName);
0a4294f Jakob Heuser first commit
Jakobo authored
240 xDomainRpc.addEventListener (event) ->
cc47e42 Jakob Heuser readme made, standardized variable names
Jakobo authored
241 if trimHost(event.origin) isnt trimHost(config.xd.xhr) then return
0a4294f Jakob Heuser first commit
Jakobo authored
242
243 # Ready init
244 if event.data is "READY"
245 xDomainRpc.postMessage("READYREADY")
246 pauseRequired = false
247 item() for item in loadQueue
248 return
249
250 pieces = event.data.match(responseSlicer)
251 onModuleLoad(pieces[1], pieces[2], pieces[3], pieces[4])
252
336caf2 Jakob Heuser addrule prototype
Jakobo authored
253 getPointcuts = (path) ->
561d11e Jakob Heuser initial pointcut support for #7. Not documented, but can now use before ...
Jakobo authored
254 ###
336caf2 Jakob Heuser addrule prototype
Jakobo authored
255 ## getPointcuts(path) ##
561d11e Jakob Heuser initial pointcut support for #7. Not documented, but can now use before ...
Jakobo authored
256 _internal_ get the [pointcuts](http://en.wikipedia.org/wiki/Pointcut) for a module if
257 specified
258 ###
336caf2 Jakob Heuser addrule prototype
Jakobo authored
259 cuts = normalizePath(path).pointcuts
260 beforeCut = [";"]
261 afterCut = [";"]
262
263 for cut in cuts.before
264 beforeCut.push(cut.toString().match(/.*?\{([\w\W]*)\}/m)[1])
265 for cut in cuts.after
266 afterCut.push(cut.toString().match(/.*?\{([\w\W]*)\}/m)[1])
267
268 beforeCut.push(";")
269 afterCut.push(";")
270 return {
271 before: beforeCut.join(";\n")
272 after: afterCut.join(";\n")
273 }
274
561d11e Jakob Heuser initial pointcut support for #7. Not documented, but can now use before ...
Jakobo authored
275 noop = () -> return
276 pointcuts =
277 before: noop
278 after: noop
279 if !userModules[module] then return pointcuts
280 definition = userModules[module]
281
282 for cut, fn of pointcuts
283 if definition[cut] then pointcuts[cut] = definition[cut]
284
285 return pointcuts
286
0a4294f Jakob Heuser first commit
Jakobo authored
287 normalizePath = (path) ->
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
288 ###
289 ## normalizePath(path) ##
290 _internal_ normalize the path based on the module collection or any functions
291 associated with its identifier
292 ###
561d11e Jakob Heuser initial pointcut support for #7. Not documented, but can now use before ...
Jakobo authored
293 workingPath = path
336caf2 Jakob Heuser addrule prototype
Jakobo authored
294 pointcuts =
295 before: []
296 after: []
0a4294f Jakob Heuser first commit
Jakobo authored
297 configPath = config.path or ""
298
299 # short circuit: already cached
336caf2 Jakob Heuser addrule prototype
Jakobo authored
300 if rulesDirty is false and modulePathRegistry[path] then return modulePathRegistry[path]
0a4294f Jakob Heuser first commit
Jakobo authored
301
336caf2 Jakob Heuser addrule prototype
Jakobo authored
302 # check rulesets
303 if rulesDirty
304 rulesDirty = false
305 rules.sort (a, b) ->
306 return b.weight - a.weight
307 for rule in rules
308 # start with workingPath, and begin applying rules
309 isMatch = if typeof(rule.key) is "string" then (rule.key.toLowerCase() is workingPath.toLowerCase()) else rule.key.test(workingPath)
310 if isMatch is false then continue
311 # adjust the path and store any relevant pointcuts
312 workingPath = if typeof(rule.path) is "string" then rule.path else rule.path(workingPath)
313 if rule?.pointcuts?.before then pointcuts.before.push(rule.pointcuts.before)
314 if rule?.pointcuts?.after then pointcuts.after.push(rule.pointcuts.after)
0a4294f Jakob Heuser first commit
Jakobo authored
315
336caf2 Jakob Heuser addrule prototype
Jakobo authored
316 # apply global rules for all paths
317 if workingPath.indexOf("/") isnt 0
318 if typeof(configPath) is "undefined" then throw new Error("Module Root must be defined")
319 else if typeof(configPath) is "string" then workingPath = "#{config.path}#{workingPath}"
320 else if typeof(configPath) is "function" then workingPath = configPath(workingPath)
561d11e Jakob Heuser initial pointcut support for #7. Not documented, but can now use before ...
Jakobo authored
321 if !jsSuffix.test(workingPath) then workingPath = "#{workingPath}.js"
0a4294f Jakob Heuser first commit
Jakobo authored
322
336caf2 Jakob Heuser addrule prototype
Jakobo authored
323 # with all rules applied, we can store more complex data in modulePathRegistry
324 modulePathRegistry[path] =
325 originalPath: path
326 resolvedPath: workingPath
327 pointcuts: pointcuts
328
329 return modulePathRegistry[path]
0a4294f Jakob Heuser first commit
Jakobo authored
330
331 loadModules = (modList, cb) ->
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
332 ###
333 ## loadModules(modList, cb) ##
334 _internal_ load a collection of modules in modList, and once they have all loaded, execute the callback cb
335 ###
336
0d70195 chao zhang #18 define() support added using require.ensure. Also fixes error where ...
chaozhang authored
337 # shortcut. If modList is undefined, then call the callback
44a84ab chao zhang #18 missing a return when solving the require.ensure([]) issue
chaozhang authored
338 if modList.length is 0 then return cb.apply(context, [])
0d70195 chao zhang #18 define() support added using require.ensure. Also fixes error where ...
chaozhang authored
339
0a4294f Jakob Heuser first commit
Jakobo authored
340 # for each item in the mod list
341 # resolve it to a full url for file access
342 # if it has been loaded, flag done & go on
343 # else, queue the module.
344 txId = createTxId()
345 paths = {}
336caf2 Jakob Heuser addrule prototype
Jakobo authored
346 (paths[module] = normalizePath(module).resolvedPath) for module in modList
347 txnRegistry[txId] =
348 list: modList
349 run: {}
0a4294f Jakob Heuser first commit
Jakobo authored
350 callbackRegistry[txId] = cb
351
352 # paths now has everything we need to include
353 # if xd params are set, add them to the queue for iframe dispatch
354 for module, path of paths
a1dcc12 Jakob Heuser commonJS compliance. Addresses #5 (preloading dependencies), #4 (exposes...
Jakobo authored
355 if !fileOnComplete[path]
356 fileOnComplete[path] =
357 txns: []
358 loading: false
359
0a4294f Jakob Heuser first commit
Jakobo authored
360 # do we have it locally?
361 if getModule(module) then paths[module] = getModule(module)
a1dcc12 Jakob Heuser commonJS compliance. Addresses #5 (preloading dependencies), #4 (exposes...
Jakobo authored
362 # Check localStorage and load
d245b70 Jakob Heuser local storage enabled and tested n chrome
Jakobo authored
363 getFile path, (ok, val) ->
a1dcc12 Jakob Heuser commonJS compliance. Addresses #5 (preloading dependencies), #4 (exposes...
Jakobo authored
364 # listen for evaluation of the module
365 fileOnComplete[path].txns.push txId
366
f57166e merging in cache expiration support
Eugene O'Neill authored
367 if ok and typeof(val) is "string" and val.length
d245b70 Jakob Heuser local storage enabled and tested n chrome
Jakobo authored
368 onModuleLoad(txId, module, path, val)
0a4294f Jakob Heuser first commit
Jakobo authored
369 else
d245b70 Jakob Heuser local storage enabled and tested n chrome
Jakobo authored
370 # we don't have the file or module, we must retrieve it
a1dcc12 Jakob Heuser commonJS compliance. Addresses #5 (preloading dependencies), #4 (exposes...
Jakobo authored
371 # if it's already loading, we just wait
372 if (!fileOnComplete[path].loading)
373 fileOnComplete[path].loading = true
374 if config.xd?
375 sendToIframe(txId, module, path, onModuleLoad)
376 else
377 sendToXhr(txId, module, path, onModuleLoad)
0a4294f Jakob Heuser first commit
Jakobo authored
378
a1dcc12 Jakob Heuser commonJS compliance. Addresses #5 (preloading dependencies), #4 (exposes...
Jakobo authored
379 onModuleLoad = (txId, module, path, text) ->
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
380 ###
381 ## onModuleLoad(txId, module, path, text) ##
382 _internal_ Fired when a module's file has been loaded. Will then set up
383 the CommonJS harness, and will capture its exports. After this, it will signal
384 to inject() that all items that were waiting on this path should continue checking
385 their depdendencies
386 ###
a1dcc12 Jakob Heuser commonJS compliance. Addresses #5 (preloading dependencies), #4 (exposes...
Jakobo authored
387 # create the commonJS wrapper for this path and execute it
0a4294f Jakob Heuser first commit
Jakobo authored
388 # suck up the exports, write to the module collection
389 # write the collection to the path as well
390 # invoke check for completeness
561d11e Jakob Heuser initial pointcut support for #7. Not documented, but can now use before ...
Jakobo authored
391 cuts = getPointcuts(module)
336caf2 Jakob Heuser addrule prototype
Jakobo authored
392
2d3cc57 Jakob Heuser commonJS compliance, added module.id, .uri to the module object
Jakobo authored
393 header = commonJSHeader.replace(/__MODULE_ID__/g, module)
394 .replace(/__MODULE_URI__/g, path)
cbe4aa6 Jakob Heuser 0.2.0 API change isn't backwards compatible. require() now the standard ...
Jakobo authored
395 .replace(/__INJECT_NS__/g, namespace)
336caf2 Jakob Heuser addrule prototype
Jakobo authored
396 .replace(/__POINTCUT_BEFORE__/g, cuts.before)
397 footer = commonJSFooter.replace(/__POINTCUT_AFTER__/g, cuts.after)
816e155 Jakob Heuser updated surce url for inject to clean up evals for debugging
Jakobo authored
398 runCmd = "#{header}\n#{text}\n#{footer}\n//@ sourceURL=#{path}"
a1dcc12 Jakob Heuser commonJS compliance. Addresses #5 (preloading dependencies), #4 (exposes...
Jakobo authored
399
c4ef0f3 Jakob Heuser #9 final cleanup, ok to merge to master
Jakobo authored
400 # find all require statements
a1dcc12 Jakob Heuser commonJS compliance. Addresses #5 (preloading dependencies), #4 (exposes...
Jakobo authored
401 requires = []
c4ef0f3 Jakob Heuser #9 final cleanup, ok to merge to master
Jakobo authored
402 requires.push(RegExp.$1) while requireRegex.exec(text)
a1dcc12 Jakob Heuser commonJS compliance. Addresses #5 (preloading dependencies), #4 (exposes...
Jakobo authored
403
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
404 # internal method to onModuleLoad, which will eval the contents and save them
405 # will then fire all of the handlers associated w/ the path
336caf2 Jakob Heuser addrule prototype
Jakobo authored
406
407 # by this point we have a list of modules we should load in order
408 # because of dependency hell.
409 # [one, two, three]
410 # if two is lagging, we should see
411 # one: runs ok (ready) FINISH
412 # three: sees one ok (ready), sees two is not available (!ready), queues self (!ready)
413 # two: sees one okay (ready), sees self & runs ok (ready), sees three in queue and runs (ready)
a1dcc12 Jakob Heuser commonJS compliance. Addresses #5 (preloading dependencies), #4 (exposes...
Jakobo authored
414 runModule = () ->
336caf2 Jakob Heuser addrule prototype
Jakobo authored
415 ready = true
416 execRan = false
a1dcc12 Jakob Heuser commonJS compliance. Addresses #5 (preloading dependencies), #4 (exposes...
Jakobo authored
417
336caf2 Jakob Heuser addrule prototype
Jakobo authored
418 execStep = () ->
419 # abort early if we have ran this once already
420 if execRan then return else execRan = true
421
422 try
423 exports = context.eval(runCmd)
424 catch err
425 throw err
426 saveModule(module, exports)
427 saveFile(path, text)
428
429 # fire all oncompletes that may be waiting
430 fileOnComplete[path].loading = false
431 for txn in fileOnComplete[path].txns
432 checkComplete(txn)
433
434 # here's the dependency management loop
435 for mod in txnRegistry[txId].list
436 if mod is module
437 # if self
438 if ready is true
439 # found ourself and we're in the ready state
440 console.log "found #{mod} as self (#{ready}): exec"
441 execStep()
442 else
443 # found ourself and we're in the !ready state
444 console.log "found #{mod} as self (#{ready}): queue"
445 txnRegistry[txId].run[mod] = execStep
446 else
447 # not self
448 if ready is true
449 # still in a ready state, attempt to getModule
450 if getModule(mod) is false
451 # module not available, check run queue
452 if txnRegistry[txId].run[mod]
453 console.log "#{mod} (#{ready}) has exec: run"
454 txnRegistry[txId].run[mod]()
455 else
456 # not in run queue, enter failed state
457 console.log "#{mod} (#{ready}) no exec: ready = false"
458 ready = false
459
460 # load deps if they exist
a1dcc12 Jakob Heuser commonJS compliance. Addresses #5 (preloading dependencies), #4 (exposes...
Jakobo authored
461 if requires.length > 0
462 loadModules requires, () ->
463 runModule()
464 else
465 runModule()
466
0a4294f Jakob Heuser first commit
Jakobo authored
467
468 checkComplete = (txId) ->
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
469 ###
470 ## checkComplete(txId) ##
471 _internal_ check if all modules for a txId have loaded. If so, the callback is fired
472 ###
0a4294f Jakob Heuser first commit
Jakobo authored
473 done = true
474 cb = callbackRegistry[txId]
475 modules = []
c3c9752 chao zhang #21 fix module callback exce multiple times bug
chaozhang authored
476 if txnRegistry[txId]
336caf2 Jakob Heuser addrule prototype
Jakobo authored
477 for module in txnRegistry[txId].list
c3c9752 chao zhang #21 fix module callback exce multiple times bug
chaozhang authored
478 modl = getModule(module)
479 if modl is false then done = false else modules.push(modl)
480 if !done then break
481 if done and cb
0d70195 chao zhang #18 define() support added using require.ensure. Also fixes error where ...
chaozhang authored
482 delete callbackRegistry[txId]
483 delete txnRegistry[txId]
484 cb.apply(context, modules)
0a4294f Jakob Heuser first commit
Jakobo authored
485
486 sendToXhr = (txId, module, path, cb) ->
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
487 ###
488 ## sendToXhr(txId, module, path, cb) ##
489 _internal_ request a module at path using xmlHttpRequest. On retrieval, fire off cb
490 ###
0a4294f Jakob Heuser first commit
Jakobo authored
491 xhr = getXHR()
492 xhr.open("GET", path)
493 xhr.onreadystatechange = () ->
494 if xhr.readyState == 4 and xhr.status == 200 then cb.call(context, txId, module, path, xhr.responseText)
495 xhr.send(null)
496
497 # request a file via iframe
498 sendToIframe = (txId, module, path, cb) ->
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
499 ###
500 ## sendToIframe(txId, module, path, cb) ##
501 _internal_ request a module at path using Porthole + iframe. On retrieval, the cb will be fired
502 ###
0a4294f Jakob Heuser first commit
Jakobo authored
503 xDomainRpc.postMessage("#{txId} #{module} #{path}")
504
505 getXHR = () ->
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
506 ###
507 ## getXHR() ##
508 _internal_ get an XMLHttpRequest object
509 ###
0a4294f Jakob Heuser first commit
Jakobo authored
510 xmlhttp = false
511 if typeof XMLHttpRequest isnt "undefined"
512 try
513 xmlhttp = new XMLHttpRequest()
514 catch errorWin
515 xmlhttp = false
516 if !xmlhttp and typeof window.createRequest isnt "undefined"
517 try
518 xmlhttp = new window.createRequest()
519 catch errorCr
520 xmlhttp = false
521 if !xmlhttp
522 try
523 xmlhttp = new ActiveXObject("Msxml2.XMLHTTP")
524 catch msErrOne
525 try
526 xmlhttp = new ActiveXObject("Microsoft.XMLHTTP")
527 catch msErrTwo
528 xmlhttp = false
529 if !xmlhttp then throw new Error("Could not create an xmlHttpRequest Object")
530 return xmlhttp
531
cbe4aa6 Jakob Heuser 0.2.0 API change isn't backwards compatible. require() now the standard ...
Jakobo authored
532 ###
533 Main Payloads: require, require.ensure, etc
534 ###
535 require = (moduleId) ->
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
536 ###
cbe4aa6 Jakob Heuser 0.2.0 API change isn't backwards compatible. require() now the standard ...
Jakobo authored
537 ## require(moduleId) ##
538 Return the value of a module. This is a synchronous call, meaning the module needs
539 to have already been loaded. If you are unsure about the module's existence, you
540 should be using require.ensure() instead. For modules beyond the first tier, their
541 shallow dependencies are resolved and block, so there is no need for require.ensure()
542 beyond the topmost level.
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
543 ###
cbe4aa6 Jakob Heuser 0.2.0 API change isn't backwards compatible. require() now the standard ...
Jakobo authored
544 mod = getModule(moduleId)
545 if mod is false then throw new Error("#{moduleId} not loaded")
546 return mod
0a4294f Jakob Heuser first commit
Jakobo authored
547
cbe4aa6 Jakob Heuser 0.2.0 API change isn't backwards compatible. require() now the standard ...
Jakobo authored
548 require.ensure = (moduleList, callback) ->
549 ###
550 ## require.ensure(moduleList, callback) ##
551 Ensure the modules in moduleList (array) are loaded, and then execute callback
552 (function). Use this instead of require() when you need to load shallow dependencies
553 first.
554 ###
0a4294f Jakob Heuser first commit
Jakobo authored
555 # init the iframe if required
556 if config.xd? and !xDomainRpc and !pauseRequired
557 createIframe()
558 pauseRequired = true
cbe4aa6 Jakob Heuser 0.2.0 API change isn't backwards compatible. require() now the standard ...
Jakobo authored
559
0a4294f Jakob Heuser first commit
Jakobo authored
560 # our default behavior. Load everything
561 # then, once everything says its loaded, call the callback
562 run = () ->
cbe4aa6 Jakob Heuser 0.2.0 API change isn't backwards compatible. require() now the standard ...
Jakobo authored
563 loadModules moduleList, () ->
564 module = {}
565 exports = {}
566 module.exports = exports
567 callback.call(context, require, module, exports)
0a4294f Jakob Heuser first commit
Jakobo authored
568
569 if pauseRequired then loadQueue.push(run)
570 else run()
e6e1155 Jakob Heuser massive cleanup and documenting binge.
Jakobo authored
571
cbe4aa6 Jakob Heuser 0.2.0 API change isn't backwards compatible. require() now the standard ...
Jakobo authored
572 require.setModuleRoot = (root) ->
573 ###
574 ## require.setModuleRoot(root) ##
575 set the base path for including your modules. This is used as the default if no
576 items in the manifest can be located.
577
578 Optionally, you can set root to a function. The return value of that function will
579 be used instead. This can allow for very complex module configurations and branching
580 with multiple CDNs such as in a complex production environment.
581 ###
582 if typeof(root) is "string" and root.lastIndexOf("/") isnt root.length then root = "#{root}/"
583 config.path = root
584
585 require.setExpires = (expires) ->
586 ###
587 ## require.setExpires(expires) ##
588 Set the time in seconds that files will persist in localStorage. Setting to 0 will disable
589 localstorage caching.
590 ###
591 config.fileExpiration = expires
592
593 require.setCrossDomain = (local, remote) ->
594 ###
595 ## require.setCrossDomain(local, remote) ##
596 Set a pair of URLs to relay files. You must have two relay files in your cross domain setup:
597
598 * one relay file (local) on the same domain as the page hosting Inject
599 * one relay file (remote) on the domain where you are hosting your root from setModuleRoot()
600
601 The same require.setCrossDomain statement should be added to BOTH your relay.html files.
602 ###
603 config.xd = {}
604 config.xd.inject = local
605 config.xd.xhr = remote
606
607 require.clearCache = (version) ->
608 ###
609 ## require.clearCache(version) ##
610 Remove the localStorage class at version. If no version is specified, the entire cache is cleared.
611 ###
612 clearFileRegistry(version)
613
614 require.manifest = (manifest) ->
615 ###
616 ## require.manifest(manifest) ##
617 Provide a custom manifest for Inject. This maps module names to file paths, adds pointcuts, and more.
618 The key is always the module name, and then inside of that key can be either
619
620 * a String (the path that will be used for resolving that module)
621 * an Object containing
622 ** path (String or Function) a path to use for the module, behaves like setModuleRoot()
623 ** pointcuts (Object) a set of Aspect Oriented functions to run before and after the function.
624
625 The pointcuts are a unique solution that allows you to require() things like jQuery. A pointcut could,
626 for example add an after() method which sets exports.$ to jQuery.noConflict(). This would restore the
627 window to its unpoluted state and make jQuery actionable as a commonJS module without having to alter
628 the original library.
629 ###
630 setUserModules(manifest)
631
336caf2 Jakob Heuser addrule prototype
Jakobo authored
632 require.addRule = (match, weight = null, ruleSet = null) ->
633 if ruleSet is null
634 # weight (optional) omitted
635 ruleSet = weight
636 weight = rules.length
637 if typeof(ruleSet) is "string"
638 usePath = ruleSet
639 ruleSet =
640 path: usePath
641 rules.push({
642 key: match
643 weight: weight
644 pointcuts: ruleSet.pointcuts or null
645 path: ruleSet.path or null
646 })
647 rulesDirty = true
648
cbe4aa6 Jakob Heuser 0.2.0 API change isn't backwards compatible. require() now the standard ...
Jakobo authored
649 require.run = (moduleId) ->
650 ###
015427e chao zhang added a small todo note
chaozhang authored
651 ## TODO require.run(moduleId) ##
cbe4aa6 Jakob Heuser 0.2.0 API change isn't backwards compatible. require() now the standard ...
Jakobo authored
652 Execute the specified moduleId. This runs an ensure() to make sure the module has been loaded, and then
653 execute it.
654 ###
655
fae95e8 chao zhang #18 add AMD
chaozhang authored
656 define = (moduleId, deps, callback) ->
657 ###
658 ## define(moduleId, deps, callback) ##
659 Define a module with moduleId, run require.ensure to make sure all dependency modules have been loaded, and then
660 apply the callback function with an array of dependency module objects, add the callback return and moduleId into
661 moduleRegistry list.
662 ###
663 # Allow for anonymous functions, adjust args appropriately
55fb647 chao zhang #26 clean up syntax
chaozhang authored
664 if typeof(moduleId) isnt "string"
fae95e8 chao zhang #18 add AMD
chaozhang authored
665 callback = deps
666 deps = moduleId
667 moduleId = null
668
669 # This module have no dependencies
0d70195 chao zhang #18 define() support added using require.ensure. Also fixes error where ...
chaozhang authored
670 if Object.prototype.toString.call(deps) isnt "[object Array]"
fae95e8 chao zhang #18 add AMD
chaozhang authored
671 callback = deps
672 deps = []
673
674 # Strip out 'require', 'exports', 'module' in deps array for require.ensure
675 strippedDeps = []
55fb647 chao zhang #26 clean up syntax
chaozhang authored
676 for dep in deps
677 if dep isnt "exports" and dep isnt "require" and dep isnt "module" then strippedDeps.push(dep)
fae95e8 chao zhang #18 add AMD
chaozhang authored
678
679 require.ensure(strippedDeps, (require, module, exports) ->
680 # already defined: require, module, exports
681 # create an array with all dependency modules object
682 args = []
683 for dep in deps
684 switch dep
685 when "require" then args.push(require)
686 when "exports" then args.push(exports)
687 when "module" then args.push(module)
688 else args.push(require(dep))
689
690 # if callback is an object, save it to exports
691 # if callback is a function, apply it with args, save the return object to exports
55fb647 chao zhang #26 clean up syntax
chaozhang authored
692 if typeof(callback) is 'function'
0d70195 chao zhang #18 define() support added using require.ensure. Also fixes error where ...
chaozhang authored
693 returnValue = callback.apply(context, args);
694 count = 0
695 count++ for own item in module.exports
696 exports = returnValue if count is 0 and typeof(returnValue) isnt "undefined"
55fb647 chao zhang #26 clean up syntax
chaozhang authored
697 else if typeof(callback) is 'object'
fae95e8 chao zhang #18 add AMD
chaozhang authored
698 exports = callback
699
700 # save moduleId, exports into module list
0d70195 chao zhang #18 define() support added using require.ensure. Also fixes error where ...
chaozhang authored
701 # we only save modules with an ID
702 if moduleId then saveModule(moduleId, exports);
fae95e8 chao zhang #18 add AMD
chaozhang authored
703 )
704
705 # To allow a clear indicator that a global define function conforms to the AMD API
0d70195 chao zhang #18 define() support added using require.ensure. Also fixes error where ...
chaozhang authored
706 define.amd =
707 jQuery: true # jQuery requires explicitly defining inside of define.amd
cbe4aa6 Jakob Heuser 0.2.0 API change isn't backwards compatible. require() now the standard ...
Jakobo authored
708
709 # set context.require to the main inject object
fae95e8 chao zhang #18 add AMD
chaozhang authored
710 # set context.define to the main inject object
cbe4aa6 Jakob Heuser 0.2.0 API change isn't backwards compatible. require() now the standard ...
Jakobo authored
711 # set an alternate interface in Inject in case things get clobbered
712 context.require = require
fae95e8 chao zhang #18 add AMD
chaozhang authored
713 context.define = define
cbe4aa6 Jakob Heuser 0.2.0 API change isn't backwards compatible. require() now the standard ...
Jakobo authored
714 context.Inject = {
1b2e724 chao zhang inject: add debuger for local storage vars
chaozhang authored
715 require: require,
fae95e8 chao zhang #18 add AMD
chaozhang authored
716 define: define,
1b2e724 chao zhang inject: add debuger for local storage vars
chaozhang authored
717 debug: {
718 fileRegistry: fileRegistry,
719 loadQueue: loadQueue,
720 userModules: userModules,
721 moduleRegistry: moduleRegistry,
722 modulePathRegistry: modulePathRegistry,
723 callbackRegistry: callbackRegistry,
724 txnRegistry: txnRegistry
725 }
cbe4aa6 Jakob Heuser 0.2.0 API change isn't backwards compatible. require() now the standard ...
Jakobo authored
726 }
c1a538f Jakob Heuser setup for new build awesomeness with compiler action
Jakobo authored
727
728 ###
729 Porthole
730 ###
731 Porthole = null
732 `
5842bc4 Jakob Heuser #15 lscache update to use better expiry method
Jakobo authored
733 Porthole="undefined"==typeof Porthole||!Porthole?{}:Porthole;Porthole={trace:function(){},error:function(a){try{console.error("Porthole: "+a)}catch(b){}},WindowProxy:function(){}};Porthole.WindowProxy.prototype={postMessage:function(){},addEventListener:function(){},removeEventListener:function(){}};
734 Porthole.WindowProxyLegacy=function(a,b){void 0===b&&(b="");this.targetWindowName=b;this.eventListeners=[];this.origin=window.location.protocol+"//"+window.location.host;null!==a?(this.proxyIFrameName=this.targetWindowName+"ProxyIFrame",this.proxyIFrameLocation=a,this.proxyIFrameElement=this.createIFrameProxy()):this.proxyIFrameElement=null};
735 Porthole.WindowProxyLegacy.prototype={getTargetWindowName:function(){return this.targetWindowName},getOrigin:function(){return this.origin},createIFrameProxy:function(){var a=document.createElement("iframe");a.setAttribute("id",this.proxyIFrameName);a.setAttribute("name",this.proxyIFrameName);a.setAttribute("src",this.proxyIFrameLocation);a.setAttribute("frameBorder","1");a.setAttribute("scrolling","auto");a.setAttribute("width",30);a.setAttribute("height",30);a.setAttribute("style","position: absolute; left: -100px; top:0px;");
736 a.style.setAttribute&&a.style.setAttribute("cssText","position: absolute; left: -100px; top:0px;");document.body.appendChild(a);return a},postMessage:function(a,b){void 0===b&&(b="*");null===this.proxyIFrameElement?Porthole.error("Can't send message because no proxy url was passed in the constructor"):(sourceWindowName=window.name,this.proxyIFrameElement.setAttribute("src",this.proxyIFrameLocation+"#"+a+"&sourceOrigin="+escape(this.getOrigin())+"&targetOrigin="+escape(b)+"&sourceWindowName="+sourceWindowName+
737 "&targetWindowName="+this.targetWindowName),this.proxyIFrameElement.height=50<this.proxyIFrameElement.height?50:100)},addEventListener:function(a){this.eventListeners.push(a);return a},removeEventListener:function(a){try{this.eventListeners.splice(this.eventListeners.indexOf(a),1)}catch(b){this.eventListeners=[],Porthole.error(b)}},dispatchEvent:function(a){for(var b=0;b<this.eventListeners.length;b++)try{this.eventListeners[b](a)}catch(c){Porthole.error("Exception trying to call back listener: "+
738 c)}}};Porthole.WindowProxyHTML5=function(a,b){void 0===b&&(b="");this.targetWindowName=b};
739 Porthole.WindowProxyHTML5.prototype={postMessage:function(a,b){void 0===b&&(b="*");targetWindow=""===this.targetWindowName?top:parent.frames[this.targetWindowName];targetWindow.postMessage(a,b)},addEventListener:function(a){window.addEventListener("message",a,!1);return a},removeEventListener:function(a){window.removeEventListener("message",a,!1)},dispatchEvent:function(a){var b=document.createEvent("MessageEvent");b.initMessageEvent("message",!0,!0,a.data,a.origin,1,window,null);window.dispatchEvent(b)}};
740 "function"!=typeof window.postMessage?(Porthole.trace("Using legacy browser support"),Porthole.WindowProxy=Porthole.WindowProxyLegacy,Porthole.WindowProxy.prototype=Porthole.WindowProxyLegacy.prototype):(Porthole.trace("Using built-in browser support"),Porthole.WindowProxy=Porthole.WindowProxyHTML5,Porthole.WindowProxy.prototype=Porthole.WindowProxyHTML5.prototype);
741 Porthole.WindowProxy.splitMessageParameters=function(a){if("undefined"==typeof a||null===a)return null;var b=[],a=a.split(/&/),c;for(c in a){var d=a[c].split("=");b[d[0]]="undefined"==typeof d[1]?"":d[1]}return b};Porthole.MessageEvent=function(a,b,c){this.data=a;this.origin=b;this.source=c};
742 Porthole.WindowProxyDispatcher={forwardMessageEvent:function(a){a=document.location.hash;if(0<a.length){a=a.substr(1);m=Porthole.WindowProxyDispatcher.parseMessage(a);targetWindow=""===m.targetWindowName?top:parent.frames[m.targetWindowName];var b=Porthole.WindowProxyDispatcher.findWindowProxyObjectInWindow(targetWindow,m.sourceWindowName);b?b.origin==m.targetOrigin||"*"==m.targetOrigin?(a=new Porthole.MessageEvent(m.data,m.sourceOrigin,b),b.dispatchEvent(a)):Porthole.error("Target origin "+b.origin+
743 " does not match desired target of "+m.targetOrigin):Porthole.error("Could not find window proxy object on the target window")}},parseMessage:function(a){if("undefined"==typeof a||null===a)return null;params=Porthole.WindowProxy.splitMessageParameters(a);var b={targetOrigin:"",sourceOrigin:"",sourceWindowName:"",data:""};b.targetOrigin=unescape(params.targetOrigin);b.sourceOrigin=unescape(params.sourceOrigin);b.sourceWindowName=unescape(params.sourceWindowName);b.targetWindowName=unescape(params.targetWindowName);
744 a=a.split(/&/);if(3<a.length)a.pop(),a.pop(),a.pop(),a.pop(),b.data=a.join("&");return b},findWindowProxyObjectInWindow:function(a,b){a.RuntimeObject&&(a=a.RuntimeObject());if(a)for(var c in a)try{if(null!==a[c]&&"object"==typeof a[c]&&a[c]instanceof a.Porthole.WindowProxy&&a[c].getTargetWindowName()==b)return a[c]}catch(d){}return null},start:function(){window.addEventListener?window.addEventListener("resize",Porthole.WindowProxyDispatcher.forwardMessageEvent,!1):document.body.attachEvent?window.attachEvent("onresize",
745 Porthole.WindowProxyDispatcher.forwardMessageEvent):Porthole.error("Can't attach resize event")}};
c1a538f Jakob Heuser setup for new build awesomeness with compiler action
Jakobo authored
746 `
747
748 ###
280fb40 Jakob Heuser added lscache to retire persist #3
Jakobo authored
749 lscache library
750 ###
8696542 Fermin Simeon Replaced PersistJs with lscache
fsimeon authored
751 lscache=null
280fb40 Jakob Heuser added lscache to retire persist #3
Jakobo authored
752 `
5842bc4 Jakob Heuser #15 lscache update to use better expiry method
Jakobo authored
753 var lscache=function(){function g(){return Math.floor((new Date).getTime()/6E4)}function l(a,b,f){function o(){try{localStorage.setItem(a+c,g()),0<f?(localStorage.setItem(a+d,g()+f),localStorage.setItem(a,b)):0>f||0===f?(localStorage.removeItem(a+c),localStorage.removeItem(a+d),localStorage.removeItem(a)):localStorage.setItem(a,b)}catch(h){if("QUOTA_EXCEEDED_ERR"===h.name||"NS_ERROR_DOM_QUOTA_REACHED"==h.name){if(0===i.length&&!m)return localStorage.removeItem(a+c),localStorage.removeItem(a+d),localStorage.removeItem(a),
754 !1;m&&(m=!1);if(!e){for(var n=0,l=localStorage.length;n<l;n++)if(j=localStorage.key(n),-1<j.indexOf(c)){var p=j.split(c)[0];i.push({key:p,touched:parseInt(localStorage[j],10)})}i.sort(function(a,b){return a.touched-b.touched})}if(k=i.shift())localStorage.removeItem(k.key+c),localStorage.removeItem(k.key+d),localStorage.removeItem(k.key);o()}}}var e=!1,m=!0,i=[],j,k;o()}var d="-EXP",c="-LRU",e;try{e=!!localStorage.getItem}catch(q){e=!1}var h=null!=window.JSON;return{set:function(a,b,c){if(e){if("string"!=
755 typeof b){if(!h)return;try{b=JSON.stringify(b)}catch(d){return}}l(a,b,c)}},get:function(a){function b(a){if(h)try{return JSON.parse(localStorage.getItem(a))}catch(b){return localStorage.getItem(a)}else return localStorage.getItem(a)}if(!e)return null;if(localStorage.getItem(a+d)){var f=parseInt(localStorage.getItem(a+d),10);if(g()>=f)localStorage.removeItem(a),localStorage.removeItem(a+d),localStorage.removeItem(a+c);else return localStorage.setItem(a+c,g()),b(a)}else if(localStorage.getItem(a))return localStorage.setItem(a+
756 c,g()),b(a);return null},remove:function(a){if(!e)return null;localStorage.removeItem(a);localStorage.removeItem(a+d);localStorage.removeItem(a+c)}}}();
c1a538f Jakob Heuser setup for new build awesomeness with compiler action
Jakobo authored
757 `
Something went wrong with that request. Please try again.