/**
 * This file contains methods and objects that exist in the
 * 'questia' namespace.  This namespace is intented to contain those methods
 * and classes that are utilities or required for framework purposes. 
 * All other Javascript code (that exists in the context of a module) should
 * be packaged according to   com.questia.familyname.modulename
 * 
 */
  /**
  * the global object.  Typically this is the widow object.
  */
var _q_global = this;

/**
 * define the 'questia' namespace. This is only for objects in this file.
 */
_q_global['questia'] = new Object();


/**
 * The main object to store variables which need to be shared between components
 * in a web page.
 */
questia.Dictionary = new Object();

/**
 * logger method for logging messages back to the server during development.
 * To see the log enter:  http://hostname/javascriptLogger?action=viewLog
 */
questia.Log = function( msg ) {
   if ( questia.rhino )
     print( msg );
   else if ( questia.Dictionary.development ){
     var params = "msg=" + encodeURI( msg );
     questia.asyncRequest.post( "/javascriptLogger", params, null );
   }
}

/**
 * Creates a package namespace relative to the global object.
 * You must declare a package before declaring Javascript classes
 * that belong to that package.
 * 
 * Example.  The first line creates the com.questia.coreweb.common namespace.
 * Now, the second line can declare the constructor Foo as belonging to that namespace.
 * 
 *    package("coreweb.common");
 * 
 *    coreweb.common.Foo = function() {
 *    }
 */
questia.Package = function(pkgName) {
   var pnames = pkgName.split('.');
   var pkgContext = _q_global;
   for(var i=0; i < pnames.length; i++) {
      var pname = pnames[i];
      if ( pkgContext[pname] == null ) {
      	  pkgContext[pname] = new Object();
      }
   	  pkgContext = pkgContext[pname];
   }
}

/**
 * Import allows you to import all objects for the specified namespace into
 * the global namespace.
 * For example, if you have an object defined in: com.questia.coreweb.common.Foo
 * you can do an import:
 *   questia.import("com.questia.coreweb.common.*);
 *    or
 *   questia.import("com.questia.coreweb.common.Foo);
 * 
 *  after the import, you can access Foo without its fully qualified package.
 *   var f = new Foo();
 * 
 *  An exception is thrown if the specified package does not exist or if an object
 *  already exists in the global namespace.
 */
questia.Import = function( pkgName ) {
   var pnames = pkgName.split('.');
   var pkgContext = _q_global;
   for(var i=0; i < pnames.length; i++) {
      var pname = pnames[i];
      if ( i == pnames.length - 1 ) {
      	if ( pname == '*') {
			for (var varName in pkgContext ) {
			   if ( pkgContext.hasOwnProperty(varName)) {
			   	   var obj = pkgContext[varName];
				   if ( !obj) {
					  throw varname + " is null in " + pkgName;
				   }
				   questia.registerGlobal( pkgName, varName, pkgContext[varName]);
			   }
			}
      	} else {
      		pkgContext = pkgContext[pname];
   			if ( !pkgContext ) {
		       	throw pname + " is null in " + pkgName;
			}
			questia.registerGlobal( pkgName, pname, pkgContext );
      	}
      	return;
      } else {
      	if ( pname == '*')
      		throw '* is not allowed here: ' + pkgName;
      }
      pkgContext = pkgContext[pname];
      if ( pkgContext == null ) {
    	var emsg = null;
        for(var j=0; j <= i; j++ ) {
        	if ( emsg != null)
        		emsg += ".";
			emsg += pnames[j];
       	}
       	throw emsg + " not declared as a package.";
      }
   }
}

/**
 * Helper method for registering objects in the global namespace.
 */
questia.registerGlobal = function( pkgName, varName, obj ) {
		var existing = _q_global[varName];
		if ( existing && existing != obj )
			throw "Import: " + pkgName + " failed.  " + varName + " already exists at global scope";
		else if ( obj ) {
			_q_global[varName] = obj;
		}
	}	


questia.tapestrySubmits = new Object();
/**
* list of functions to be invoked after page is loaded
*/
questia.initializers = new Array();


questia.addInitializer = function( func ) {
    if ( func ) {
		questia.initializers.push( func );
	}
}

/**
* Helper method to get around the ridiculous Tapestry limitation preventing 'onsubmit' JavaScript attributes
* in forms
*/
questia.onsubmit = function( formId, functionObj ) {
   questia.tapestrySubmits[formId] = functionObj;
}

questia.registerFormSubmits = function() {
   for( var fid in questia.tapestrySubmits ) {
      // See: http://yuiblog.com/blog/2006/09/26/for-in-intrigue/  
      // for discussion of issue with for(in) loops in JavaScript 
      if ( questia.tapestrySubmits.hasOwnProperty(fid)) {
	     Tapestry.onsubmit( fid, questia.tapestrySubmits[fid] );
      }
   }
}


questia.initialize = function() {
	for( var i = 0; i < questia.initializers.length; i++ ) {
		questia.initializers[i]();
	}
	questia.registerFormSubmits();
}

