text: /*
  	Copyright (c) 2004-2006, The Dojo Foundation
  	All Rights Reserved.
  
  	Licensed under the Academic Free License version 2.1 or above OR the
  	modified BSD license. For more information on Dojo licensing, see:
  
  		http://dojotoolkit.org/community/licensing.shtml
  */
  
  //Cross-domain package loader.
  
  //FIXME: How will xd loading work with debugAtAllCosts? Any bad interactions?
  //FIXME: widgets won't work fully (HTML/CSS) and also because of the requireIf() thing.
  
  dojo.hostenv.resetXd = function(){
  	//This flag indicates where or not we have crossed into xdomain territory. Once any package says
  	//it is cross domain, then the rest of the packages have to be treated as xdomain because we need
  	//to evaluate packages in order. If there is a xdomain package followed by a xhr package, we can't load
  	//the xhr package until the one before it finishes loading. The text of the xhr package will be converted
  	//to match the format for a xd package and put in the xd load queue.
  	//You can force all packages to be treated as xd by setting the djConfig.forceXDomain.
  	this.isXDomain = djConfig.forceXDomain || false;
  
  	this.xdTimer = 0;
  	this.xdInFlight = {};
  	this.xdOrderedReqs = [];
  	this.xdDepMap = {};
  	this.xdContents = [];
  }
  
  //Call reset immediately to set the state.
  dojo.hostenv.resetXd();
  
  dojo.hostenv.createXdPackage = function(contents){
  	//Find dependencies.
  	var deps = [];
      var depRegExp = /dojo.(require|requireIf|requireAll|provide|requireAfterIf|requireAfter|kwCompoundRequire|conditionalRequire|hostenv\.conditionalLoadModule|.hostenv\.loadModule|hostenv\.moduleLoaded)\(([\w\W]*?)\)/mg;
      var match;
  	while((match = depRegExp.exec(contents)) != null){
  		deps.push("\"" + match[1] + "\", " + match[2]);
  	}
  
  	//Create package object and the call to packageLoaded.
  	var output = [];
  	output.push("dojo.hostenv.packageLoaded({\n");
  
  	//Add dependencies
  	if(deps.length > 0){
  		output.push("depends: [");
  		for(var i = 0; i < deps.length; i++){
  			if(i > 0){
  				output.push(",\n");
  			}
  			output.push("[" + deps[i] + "]");
  		}
  		output.push("],");
  	}
  
  	//Add the contents of the file inside a function.
  	//Pass in dojo as an argument to the function to help with
  	//allowing multiple versions of dojo in a page.
  	output.push("\ndefinePackage: function(dojo){");
  	output.push(contents);
  	output.push("\n}});");
  	
  	return output.join("");
  }
  
  dojo.hostenv.loadPath = function(relpath, module /*optional*/, cb /*optional*/){
  	//Only do getBaseScriptUri if path does not start with a URL with a protocol.
  	//If there is a colon before the first / then, we have a URL with a protocol.
  	var colonIndex = relpath.indexOf(":");
  	var slashIndex = relpath.indexOf("/");
  	var uri;
  	var currentIsXDomain = false;
  	if(colonIndex > 0 && colonIndex < slashIndex){
  		uri = relpath;
  		this.isXDomain = currentIsXDomain = true;
  	}else{
  		uri = this.getBaseScriptUri() + relpath;
  
  		//Is ithe base script URI-based URL a cross domain URL?
  		colonIndex = uri.indexOf(":");
  		slashIndex = uri.indexOf("/");
  		if(colonIndex > 0 && colonIndex < slashIndex && (!location.host || uri.indexOf("http://" + location.host) != 0)){
  			this.isXDomain = currentIsXDomain = true;
  		}
  	}
  
  	if(djConfig.cacheBust && dojo.render.html.capable) { uri += "?" + String(djConfig.cacheBust).replace(/\W+/g,""); }
  	try{
  		return ((!module || this.isXDomain) ? this.loadUri(uri, cb, currentIsXDomain, module) : this.loadUriAndCheck(uri, module, cb));
  	}catch(e){
  		dojo.debug(e);
  		return false;
  	}
  }
  
  //Overriding loadUri for now. Wanted to override getText(), but it is used by
  //the widget code in too many, synchronous ways right now. This means the xd stuff
  //is not suitable for widgets yet.
  dojo.hostenv.loadUri = function(uri, cb, currentIsXDomain, module){
  	if(this.loadedUris[uri]){
  		return 1;
  	}
  
  	//Add the module (package) to the list of modules.
  	if(this.isXDomain){
  		//Curious: is this array going to get whacked with multiple access since scripts
  		//load asynchronously and may be accessing the array at the same time?
  		//JS is single-threaded supposedly, so it should be ok. And we don't need
  		//a precise ordering.
  		this.xdOrderedReqs.push(module);
  
  		//Add to waiting packages.
  		//If this is a __package__.js file, then this must be
  		//a package.* request (since xdomain can only work with the first
  		//path in a package search list. However, .* module names are not
  		//passed to this function, so do an adjustment here.
  		if(uri.indexOf("__package__") != -1){
  			module += ".*";
  		}
  
  		this.xdInFlight[module] = true;
  
  		//Increment inFlightCount
  		//This will stop the modulesLoaded from firing all the way.
  		this.inFlightCount++;
  				
  		//Start timer
  		if(!this.xdTimer){
  			this.xdTimer = setInterval("dojo.hostenv.watchInFlightXDomain();", 100);
  		}
  		this.xdStartTime = (new Date()).getTime();
  	}
  
  	if (currentIsXDomain){
  		//Fix name to be a .xd.fileextension name.
  		var lastIndex = uri.lastIndexOf('.');
  		if(lastIndex <= 0){
  			lastIndex = uri.length - 1;
  		}
  
  		var xdUri = uri.substring(0, lastIndex) + ".xd";
  		if(lastIndex != uri.length - 1){
  			xdUri += uri.substring(lastIndex, uri.length);
  		}
  
  		//Add to script src
  		var element = document.createElement("script");
  		element.type = "text/javascript";
  		element.src = xdUri;
  		if(!this.headElement){
  			this.headElement = document.getElementsByTagName("head")[0];
  		}
  		this.headElement.appendChild(element);
  	}else{
  		var contents = this.getText(uri, null, true);
  		if(contents == null){ return 0; }
  		
  		if(this.isXDomain){
  			var pkg = this.createXdPackage(contents);
  			dj_eval(pkg);
  		}else{
  			if(cb){ contents = '('+contents+')'; }
  			var value = dj_eval(contents);
  			if(cb){
  				cb(value);
  			}
  		}
  	}
  
  	//These steps are done in the non-xd loader version of this function.
  	//Maintain these steps to fit in with the existing system.
  	this.loadedUris[uri] = true;
  	return 1;
  }
  
  dojo.hostenv.packageLoaded = function(pkg){
  	var deps = pkg.depends;
  	var requireList = null;
  	var requireAfterList = null;
  	var provideList = [];
  	if(deps && deps.length > 0){
  		var dep = null;
  		var insertHint = 0;
  		var attachedPackage = false;
  		for(var i = 0; i < deps.length; i++){
  			dep = deps[i];
  
  			//Look for specific dependency indicators.
  			if (dep[0] == "provide" || dep[0] == "hostenv.moduleLoaded"){
  				provideList.push(dep[1]);
  			}else{
  				if(!requireList){
  					requireList = [];
  				}
  				if(!requireAfterList){
  					requireAfterList = [];
  				}
  
  				var unpackedDeps = this.unpackXdDependency(dep);
  				if(unpackedDeps.requires){
  					requireList = requireList.concat(unpackedDeps.requires);
  				}
  				if(unpackedDeps.requiresAfter){
  					requireAfterList = requireAfterList.concat(unpackedDeps.requiresAfter);
  				}
  			}
  
  			//Call the dependency indicator to allow for the normal dojo setup.
  			//Only allow for one dot reference, for the hostenv.* type calls.
  			var depType = dep[0];
  			var objPath = depType.split(".");
  			if(objPath.length == 2){
  				dojo[objPath[0]][objPath[1]].apply(dojo[objPath[0]], dep.slice(1));
  			}else{
  				dojo[depType].apply(dojo, dep.slice(1));
  			}
  		}
  
  		//Save off the package contents for definition later.
  		var contentIndex = this.xdContents.push({content: pkg.definePackage, isDefined: false}) - 1;
  
  		//Add provide/requires to dependency map.
  		for(var i = 0; i < provideList.length; i++){
  			this.xdDepMap[provideList[i]] = { requires: requireList, requiresAfter: requireAfterList, contentIndex: contentIndex };
  		}
  
  		//Now update the inflight status for any provided packages in this loaded package.
  		//Do this at the very end (in a *separate* for loop) to avoid shutting down the 
  		//inflight timer check too soon.
  		for(var i = 0; i < provideList.length; i++){
  			this.xdInFlight[provideList[i]] = false;
  		}
  	}
  }
  
  //This is a bit brittle: it has to know about the dojo methods that deal with dependencies
  //It would be ideal to intercept the actual methods and do something fancy at that point,
  //but I have concern about knowing which provide to match to the dependency in that case,
  //since scripts can load whenever they want, and trigger new calls to dojo.hostenv.packageLoaded().
  dojo.hostenv.unpackXdDependency = function(dep){
  	//Extract the dependency(ies).
  	var newDeps = null;
  	var newAfterDeps = null;
  	switch(dep[0]){
  		case "requireIf":
  		case "requireAfterIf":
  		case "conditionalRequire":
  			//First arg (dep[1]) is the test. Depedency is dep[2].
  			if((dep[1] === true)||(dep[1]=="common")||(dep[1] && dojo.render[dep[1]].capable)){
  				newDeps = [{name: dep[2], content: null}];
  			}
  			break;
  		case "requireAll":
  			//the arguments are an array, each element a call to require.
  			//Get rid of first item, which is "requireAll".
  			dep.shift();
  			newDeps = dep;
  			dojo.hostenv.flattenRequireArray(newDeps);
  			break;
  		case "kwCompoundRequire":
  		case "hostenv.conditionalLoadModule":
  			var modMap = dep[1];
  			var common = modMap["common"]||[];
  			var newDeps = (modMap[dojo.hostenv.name_]) ? common.concat(modMap[dojo.hostenv.name_]||[]) : common.concat(modMap["default"]||[]);	
  			dojo.hostenv.flattenRequireArray(newDeps);
  			break;
  		case "require":
  		case "requireAfter":
  		case "hostenv.loadModule":
  			//Just worry about dep[1]
  			newDeps = [{name: dep[1], content: null}];
  			break;
  	}
  
  	//The requireAfterIf or requireAfter needs to be evaluated after the current package is evaluated.
  	if(dep[0] == "requireAfterIf"){
  		newAfterDeps = newDeps;
  		newDeps = null;
  	}
  	return {requires: newDeps, requiresAfter: newAfterDeps};
  }
  
  //Walks the requires and evaluates package contents in
  //the right order.
  dojo.hostenv.xdWalkReqs = function(){
  	var reqChain = null;
  	var req;
  	for(var i = 0; i < this.xdOrderedReqs.length; i++){
  		req = this.xdOrderedReqs[i];
  		if(this.xdDepMap[req]){
  			reqChain = [req];
  			reqChain[req] = true; //Allow for fast lookup of the req in the array
  			this.xdEvalReqs(reqChain);
  		}
  	}
  }
  
  //Trace down any requires.
  dojo.hostenv.xdTraceReqs = function(reqs, reqChain){
  	if(reqs && reqs.length > 0){
  		var nextReq;
  		for(var i = 0; i < reqs.length; i++){
  			nextReq = reqs[i].name;
  			if(nextReq && !reqChain[nextReq]){
  				//New req depedency. Follow it down.
  				reqChain.push(nextReq);
  				reqChain[nextReq] = true;
  				this.xdEvalReqs(reqChain);
  			}
  		}
  	}
  }
  
  //Do a depth first, breadth second search and eval or reqs.
  dojo.hostenv.xdEvalReqs = function(reqChain){
  	if(reqChain.length > 0){
  		var req = reqChain[reqChain.length - 1];
  		var pkg = this.xdDepMap[req];
  		if(pkg){
  			//Trace down any requires for this package.
  			this.xdTraceReqs(pkg.requires, reqChain);
  
  			//Evaluate the package.
  			var contents = this.xdContents[pkg.contentIndex];
  			if(!contents.isDefined){
  				//Evaluate the package to bring it into being.
  				//Pass dojo in so that later, to support multiple versions of dojo
  				//in a page, we can pass which version of dojo to use.
  				contents.content(dojo);
  				contents.isDefined = true;
  			}
  			this.xdDepMap[req] = null;
  
  			//Trace down any requireAfters for this package..
  			this.xdTraceReqs(pkg.requiresAfter, reqChain);
  		}
  
  		//Done with that require. Remove it and go to the next one.
  		reqChain.pop();
  		this.xdEvalReqs(reqChain);
  	}
  }
  
  dojo.hostenv.clearXdInterval = function(){
  	clearInterval(this.xdTimer);
  	this.xdTimer = 0;
  }
  
  dojo.hostenv.watchInFlightXDomain = function(){
  	//Make sure we haven't waited timed out.
  	var waitInterval = (djConfig.xdWaitSeconds || 30) * 1000;
  
  	if(this.xdStartTime + waitInterval < (new Date()).getTime()){
  		this.clearXdInterval();
  		var noLoads = "";
  		for(var param in this.xdInFlight){
  			if(this.xdInFlight[param]){
  				noLoads += param + " ";
  			}
  		}
  		dojo.raise("Could not load cross-domain packages: " + noLoads);
  	}
  
  	//If any are true, then still waiting.
  	//Come back later.	
  	for(var param in this.xdInFlight){
  		if(this.xdInFlight[param]){
  			return;
  		}
  	}
  
  	//All done loading. Clean up and notify that we are loaded.
  	this.clearXdInterval();
  
  	this.xdWalkReqs();
  
  	//Evaluate any packages that were not evaled before.
  	//This normally shouldn't happen with proper dojo.provide and dojo.require
  	//usage, but providing it just in case. Note that these may not be executed
  	//in the original order that the developer intended.
  	//Pass dojo in so that later, to support multiple versions of dojo
  	//in a page, we can pass which version of dojo to use.
  	for(var i = 0; i < this.xdContents.length; i++){
  		var current = this.xdContents[i];
  		if(current.content && !current.isDefined){
  			current.content(dojo);
  		}
  	}
  
  	//Clean up for the next round of xd loading.
  	this.resetXd();
  
  	//Clear inflight count so we will finally do finish work.
  	this.inFlightCount = 0; 
  	this.callLoaded();
  }
  
  dojo.hostenv.flattenRequireArray = function(target){
  	//Each result could be an array of 3 elements  (the 3 arguments to dojo.require).
  	//We only need the first one.
  	if(target){
  		for(var i = 0; i < target.length; i++){
  			if(target[i] instanceof Array){
  				target[i] = {name: target[i][0], content: null};
  			}else{
  				target[i] = {name: target[i], content: null};
  			}
  		}
  	}
  }
  
  //Need to preload any flattened i18n bundles before we start
  //executing code, since we cannot do it synchronously, as the
  //i18n code normally expects.
  dojo.hostenv.xdHasCalledPreload = false;
  dojo.hostenv.xdRealCallLoaded = dojo.hostenv.callLoaded;
  dojo.hostenv.callLoaded = function(){
  	//If getModulePrefix for dojo returns anything other than "src", that means
  	//there is a path registered for dojo, with implies that dojo was xdomain loaded.
  	if(this.xdHasCalledPreload || dojo.hostenv.getModulePrefix("dojo") == "src"){
  		this.xdRealCallLoaded();
  		this.xdHasCalledPreload = true;
  	}else{
  		if(this.localesGenerated){
  			this.registerNlsPrefix = function(){
  				//Need to set the nls prefix to be the xd location.
  				dojo.registerModulePath("nls", dojo.hostenv.getModulePrefix("dojo") + "/../nls");	
  			};
  			this.preloadLocalizations();
  		}
  		this.xdHasCalledPreload = true;
  	}
  }
  