1 /**
  2                             iiii                                       jjjj                  
  3                            i::::i                                     j::::j                 
  4                             iiii                                       jjjj                  
  5                                                                                              
  6        rrrrr   rrrrrrrrr  iiiiiii    ooooooooooo                     jjjjjjj    ssssssssss   
  7        r::::rrr:::::::::r i:::::i  oo:::::::::::oo  ::::::           j:::::j  ss::::::::::s  
  8        r:::::::::::::::::r i::::i o:::::::::::::::o ::::::            j::::jss:::::::::::::s 
  9        rr::::::rrrrr::::::ri::::i o:::::ooooo:::::o ::::::            j::::js::::::ssss:::::s
 10         r:::::r     r:::::ri::::i o::::o     o::::o                   j::::j s:::::s  ssssss 
 11         r:::::r     rrrrrrri::::i o::::o     o::::o                   j::::j   s::::::s      
 12         r:::::r            i::::i o::::o     o::::o                   j::::j      s::::::s   
 13         r:::::r            i::::i o::::o     o::::o ::::::            j::::jssssss   s:::::s 
 14         r:::::r           i::::::io:::::ooooo:::::o ::::::            j::::js:::::ssss::::::s
 15         r:::::r           i::::::io:::::::::::::::o ::::::            j::::js::::::::::::::s 
 16         r:::::r           i::::::i oo:::::::::::oo                    j::::j s:::::::::::ss  
 17         rrrrrrr           iiiiiiii   ooooooooooo                      j::::j  sssssssssss    
 18                                                                       j::::j                 
 19                                                             jjjj      j::::j                 
 20                                                            j::::jj   j:::::j                 
 21                                                            j::::::jjj::::::j                 
 22                                                             jj::::::::::::j                  
 23                                                               jjj::::::jjj                   
 24                                                                  jjjjjj                      
 25        
 26 
 27 	@name rio
 28 	@namespace
 29 	
 30 	The rio namespace is the root of the entire framework, through which you can access all of the classes and 
 31 	namespaces.
 32 	
 33 	<br />
 34 	
 35 	<h2>Namespaces</h2>
 36 	
 37 	<ul>
 38 		<li>apps - contains instances of rio.Application</li>
 39 		<li>components - contains instances of rio.Component</li>
 40 		<li>models - contains instances of rio.Model</li>
 41 		<li>pages - contains instances of rio.Page</li>
 42 		<li>environment - configuration for the current environment</li>
 43 		<li>environments - configurations varying by environment</li>
 44 		<li>console - stuff related to the development console</li>
 45 		<li>boot - configuration related to the application boot process</li>
 46 	</ul>
 47 	
 48 	<h2>Classes</h2>
 49 	
 50 	<ul>
 51 		<li>AIM - manages AJAX file uploads</li>
 52 		<li>Application - root of application instances</li>
 53 		<li>Attr - root of most rio classes (Application, Component, Model, Page)</li>
 54 		<li>Binding - represents a bindable attribute</li>
 55 		<li>Tag - a collection of methods for building HTML tags</li>
 56 		<li>Utils - a collection of random helper methods</li>
 57 	</ul>
 58 	
 59 	<h2>Methods</h2>
 60 	<ul>
 61 		<li>log - adds a log message to the rio console</li>
 62 	</ul>
 63 	
 64 	<h2>Fields</h2>
 65 	<ul>
 66 		<li>app - the currently running application instance</li>
 67 	</ul>
 68 
 69 	@author Jason Tillery
 70 	@copyright 2008-2009 Thinklink LLC
 71 */
 72 var w = window;
 73 (function() {
 74 	if (!window.console) { window.console = { log: Prototype.emptyFunction }; }
 75 	
 76 	var initialWindowKeys = Object.keys(window);
 77 	
 78 	var bootOptions = window.bootOptions || {};
 79 
 80 	Object.extend(rio, {
 81 		url: function(url) {
 82 			return url + "?" + rio.cacheKey;
 83 		},
 84 		components: {},
 85 		models: {},
 86 		apps: {},
 87 		pages: {},
 88 		console: {},
 89 		log: Prototype.emptyFunction,
 90 		warn: Prototype.emptyFunction,
 91 		error: Prototype.emptyFunction,
 92 		boot: {
 93 			errors: [],
 94 			isMac: navigator.appVersion.toLowerCase().indexOf("mac") != -1,
 95 			root: "/javascripts/",
 96 			appRoot: bootOptions.appRoot || "",
 97 			rioPath: bootOptions.rioPath || "lib/",
 98 			prototypePath: bootOptions.prototypePath || "prototype/",
 99 			prototypePollution: [
100 				"$", "$$", "$A", "$F", "$H", "$R", "$break", "$continue", "$w", "_eventID", "Abstract", "Ajax", "Autocompleter", "Builder", "Class", "Draggable", "Draggables", "Droppables", "Effect", "Element", "Enumerable", "Field", "Form", "Hash", "Insertion", "ObjectRange", "PeriodicalExecuter", "Position", "Prototype", "Selector", "Sortable", "SortableObserver", "Template", "Toggle", "Try"
101 			],
102 			googleAnalyticsPollution: ["gaGlobal", "gaJsHost", "_gat", "pageTracker"],
103 			noConsole: bootOptions.noConsole,
104 			initialWindowKeys: initialWindowKeys,
105 			prototypeScripts: [],
106 			rioScripts: [],
107 			rioScriptsDigest: {},
108 			appScriptsDigest: {},
109 			prototypeScriptsDigest: {},
110 			loadedFiles: [],
111 			loadedStylesheets: [],
112 			loadedTemplates: [],
113 			loadFunctions: {},
114 			
115 			appScripts: function() {
116 				return rio.boot.loadedFiles.reject(function(f) {
117 					return rio.boot.prototypeScripts.include(f) || rio.boot.rioScripts.include(f);
118 				});
119 			},
120 			
121 			pollution: function() {
122 				return Object.keys(window).reject(function(key) {
123 					return rio.boot.initialWindowKeys.include(key) || 
124 						rio.boot.prototypePollution.include(key) || 
125 						rio.boot.googleAnalyticsPollution.include(key);
126 				}.bind(this));
127 			},
128 			
129 			failBoot: function() {
130 				if (rio.environment.bootFailedUrl) {
131 					document.location.href = rio.environment.bootFailedUrl;					
132 				} else {
133 					rio.boot.printErrors();
134 				}
135 			},
136 			
137 			printErrors: function() {
138 				$$("body")[0].update();
139 
140 				var msg = "<h1 style='font-size: 24px; color: #670800;'>Boot failed</h1>";
141 				msg += "<style>.errorLine{font-size:16px; padding:0px 2px; background-color:yellow}</style>";
142 
143 				rio.boot.errors.each(function(e) {
144 					if (e.e) {
145 						msg += "<br /><br />";
146 						msg += "<p style='font-weight: 700'>" + e.msg + "<br /><br />" + e.e + "</p>";
147 						msg += "<br />";
148 					} else if (e.lint) {
149 						e.lint.each(function(err) {
150 							msg += err.toHtml() + "<br />";
151 						});
152 					}
153 				});
154 
155 				$$("body")[0].insert("<div style='padding: 20px'>" + msg + "</div>");
156 			}
157 		}
158 	});
159 
160 	$$("script").each(function(script) {
161 		var src = script.src;
162 		if(src.match(/boot\.js/) && src.indexOf('?') != -1) {
163 			var options = src.split('?')[1].split(',');
164 			if (options.length >= 1) { rio.boot.appName = options[0]; }
165 			if (options.length >= 2) { rio.boot.environment = options[1]; }
166 			if (options.length >= 3) { rio.boot.bootCompressed = (options[2] == "compressed"); }
167 		}
168 	});
169 	
170 	Object.extend(rio.environment, rio.environments[rio.boot.environment]);
171 	Object.extend(rio.boot, rio.environment.boot);
172 
173 	if (bootOptions.noConsole === undefined) {
174 		rio.boot.noConsole = (rio.environment.console == undefined) ? false : !rio.environment.console;
175 	}
176 	
177 	rio.require = function(fileName, options) {
178 		options = Object.extend({
179 			force: false,
180 			track: true
181 		}, options || {});
182 
183 		if (!rio.boot.loadedFiles.include(fileName)) {
184 			if (rio.boot.bootCompressed && options.force) {
185 				if (options.track) { rio.boot.loadedFiles.push(fileName); }
186 				document.write('<script type="text/javascript" src="' + (options.noPrefix ? "" : rio.assetPrefix) + rio.url(rio.boot.root + fileName + '.js') + '"></script>');
187 			} else if (!rio.boot.bootCompressed) {
188 				if (rio.boot.loadFunctions[fileName]) {
189 					rio.boot.loadFunctions[fileName]();
190 				} else {
191 					var path = rio.boot.root + fileName + ".js";
192 					new Ajax.Request(rio.url(path), {
193 						asynchronous: false,
194 						method: "get",
195 						evalJSON: false,
196 						evalJS: false,
197 						onSuccess: function(response) {
198 							try {
199 								w.eval(response.responseText);
200 							} catch(e) {
201 								rio.error(e, "Failed parsing file: " + path);
202 
203 								if (!rio.app) {
204 									if (fileName != "lib/rio_lint") {
205 										rio.require("lib/rio_lint", { track: false });
206 									}
207 									
208 									var lintIt = function(fileName) {
209 										rio.RioLint.checkFileSyntax(fileName, {
210 											onComplete: function(errors) {
211 												rio.boot.errors.push({ lint: errors });
212 											}
213 										});
214 									};
215 									if (fileName == "lib/rio_concat") {
216 										new Ajax.Request(rio.url("/javascripts/lib/rio.build"), {
217 											asynchronous: false,
218 											method: "get",
219 											evalJSON: false,
220 											evalJS: false,
221 											onSuccess: function(response) {
222 												var files = response.responseText.split("\n");
223 												files.without("lib/swfobject").each(function(f) {
224 													lintIt(f);
225 												});
226 											}
227 										});
228 									} else if (fileName == "apps/" + rio.boot.appName + "_concat") {
229 									} else {
230 										rio.boot.errors.push({ e: e, msg: "Failed parsing file: " + path });
231 										lintIt(fileName);
232 									}
233 									
234 								}
235 								throw(e);
236 							}
237 						},
238 						onFailure: function() {
239 							rio.log("Failed loading file: " + path);
240 						}
241 					});					
242 				}
243 				if (options.track) { rio.boot.loadedFiles.push(fileName); }
244 			}
245 		}
246 	};
247 
248 	if (rio.boot.bootCompressed) {
249 		// rio.require(rio.boot.appRoot + "prototype/compressed/prototype", { force: true });
250 		rio.require(rio.boot.rioPath + "compressed/rio", { force: true });
251 		rio.require(rio.boot.appRoot + "apps/compressed/" + rio.boot.appName, { force: true });
252 		if (rio.boot.environment == "development") {
253 			rio.require(rio.boot.rioPath + "rio_development_concat", { force: true });
254 		}
255 	} else {
256 		try {
257 			rio.require(rio.boot.appRoot + "prototype/prototype_concat", { track: false });
258 			rio.require(rio.boot.rioPath + "rio_concat", { track: false });
259 			rio.require(rio.boot.appRoot + "apps/" + rio.boot.appName + "_concat", { track: false });
260 			rio.require(rio.boot.appRoot + "apps/" + rio.boot.appName);
261 		} catch(e) {
262 			// Let the errors print on load
263 		}
264 	}
265 	if (rio.environment.autoConcatCss) {
266 		if (rio.boot.bootCompressed) {
267 			document.write('<script type="text/javascript">' + 'rio.Application.injectCss();' + '</script>')
268 		} else {
269 			rio.Application.injectCss();
270 		}
271 	}
272 	
273 	if (rio.environment.supportSelenium) {
274 		rio.require(rio.boot.rioPath + "event.simulate", { force: true, noPrefix: true });
275 		rio.require(rio.boot.rioPath + "selenium_extensions", { force: true, noPrefix: true });
276 	}
277 
278 	document.observe('dom:loaded', function() {
279 		if (rio.environment.push && !rio.push) {
280 			rio.Push.boot();
281 		}
282 
283 		if (rio.preloadTemplates) {
284 			rio.JsTemplate.preload("apps/" + (rio.boot.bootCompressed ? "compressed/" + rio.boot.appName : rio.boot.appName + "_concat"));
285 		}
286 
287 		if (rio.environment.failOnBootError && rio.boot.errors.length > 0) {
288 			rio.boot.failBoot();
289 			return;
290 		}
291 		try {
292 			window.initialOptions = window.initialOptions || {};
293 			rio.app = new rio.apps[rio.boot.appName.camelize()](initialOptions);
294 			rio.app.launch();
295 		} catch(e) {
296 			rio.boot.errors.push({ e: e, msg: "Failed inititializing or launching application" });
297 			rio.boot.failBoot();
298 		}
299 	}.bind(this));
300 })();
301