
/*
 * CFX
 * JavaScript Programmer's Framework
 * Release 6
 * Version 1.0
 *
 * Filename:	cfx_core.js
 * Module:		Core
 * Description:	CFX Core provides the basic structures for the CFX system. All CFX require that
 *				this module is loaded.
 */

/*** Constants ***************************************************************/
	/* Misc */
		CFX_CORE_VERSION = "1.6";		/* Version number of the core module */
		CFX_CORE_FULLID = "CFX Core Architecture Release 6 Version " + CFX_CORE_VERSION;
		CFX_FILE_LOCATION = "scripts/";	/* Location of the CFX files */
	/* Runlevels */
		CFX_RUNLEVEL_NONE = 0;			/* Core initialization
									 * At this runlevel no module or user function may do anything except call
									 * cfx_preInit(). User functions should usually wait for runlevel 2.
									 */
		CFX_RUNLEVEL_PREINIT = 1;		/* Module initialization */
		CFX_RUNLEVEL_INIT = 2;			/* User-Level object initialization */
		CFX_RUNLEVEL_POSTINIT = 3;		/* For stuff depending on things done in level 2 */
		CFX_RUNLEVEL_PAGELOAD = 4;		/* reached on window's onLoad-Event */
		CFX_RUNLEVEL_FINAL = 5;			/* reached after parsing any onLoad-stuff */
	/* Browser Types - browser check only partially implemented yet */			
		CFX_BROWSER_UNKNOWN = 0;		/* Unknown browser, no known API compatibility */
		CFX_BROWSER_NETSCAPE = 1;		/* Any Netscape browser */
		CFX_BROWSER_IEXPLORER = 2;		/* Any Microsoft Internet Explorer */
		CFX_BROWSER_GECKO = 3;			/* Any Mozilla.org/Gecko Browser - check NYI */
		CFX_BROWSER_OPERA = 4;			/* Any Opera browser - check NYI*/
	/* Platform Types */
		CFX_PLATFORM_UNKNOWN = 0;		/* Unknown system, or not revealed by browser */
		CFX_PLATFORM_WIN32 = 1;			/* Any of Win95, 98, NT, 2000 */
		CFX_PLATFORM_MACOS = 2;			/* Any Apple Macintosh */
		CFX_PLATFORM_UNIX = 3;			/* Any Unix system */
	/* Platform Versions*/
		CFX_PLATFORM_VERSION_UNKNOWN = 0;	/* Unknown subplatform, or not applicable */
		CFX_PLATFORM_VERSION_WIN95 = 1;		/* The various Win32 flavors */
		CFX_PLATFORM_VERSION_WIN98 = 2;
		CFX_PLATFORM_VERSION_WINNT4 = 3;
		CFX_PLATFORM_VERSION_WIN2000 = 4;

/*** Init ********************************************************************/

window.onerror = cfxprivate_onErrorHandlerDefault;		/* activate default error handler */
window.onload = cfxprivate_onLoadHandler; 				/* activate other event handlers */
window.onresize = cfxprivate_onResizeHandler;
document.cfx_runlevel = CFX_RUNLEVEL_NONE;				/* signal to all: we're not here yet */
var cfxprivate_runlevel_commands = new Array();			/* create arrays for the runlevel command lists */
cfxprivate_runlevel_commands[CFX_RUNLEVEL_PREINIT] = new Array();
cfxprivate_runlevel_commands[CFX_RUNLEVEL_INIT] = new Array();
cfxprivate_runlevel_commands[CFX_RUNLEVEL_POSTINIT] = new Array();
cfxprivate_runlevel_commands[CFX_RUNLEVEL_PAGELOAD] = new Array();
cfxprivate_runlevel_commands[CFX_RUNLEVEL_FINAL] = new Array();
var cfxprivate_event_commands = new Array();			/* create arrays for the event command lists */
cfxprivate_event_commands["onload"] = new Array();
cfxprivate_event_commands["onresize"] = new Array();
var cfx = new cfxprivate_core();						/* create CFX core object */
cfxprivate_switchRunlevel(CFX_RUNLEVEL_PREINIT);		/* switch to next Runlevel */
cfxprivate_switchRunlevel(CFX_RUNLEVEL_INIT);
cfxprivate_switchRunlevel(CFX_RUNLEVEL_POSTINIT);
/* from here on waiting for the onLoad-Event */


/*** Objects *****************************************************************/

function cfxprivate_core() {
	/* This is the core object of the CFX framework. It contains almost everything the CFX modules need to know,
	 * except the runlevel, which is stored in 'document.cfx_runlevel'.
	 */
	this.browser = new cfxprivate_browserTest(); /* create an Object for checking all interesting things in the browser */
	this.modules = new cfxprivate_cfxModules(); /* create an Object for registering all loaded CFX modules */
	this.extensions = new Array();
	this.location = CFX_FILE_LOCATION;
	this.debug = false;
	this.debugDeep = false;
}

function cfxprivate_browserTest() {
	/*
	 * This object contains information about the browser's capabilities. It checks them at creation time
	 * and then stores the information.
	 * These are the fields:
	 *	field name	|	true if browser supports
	 *	images			image operations
	 *	timeout			window.setTimeout
	 */
	this.client = CFX_BROWSER_UNKNOWN; 
	this.clientVersion = 0;
	this.platform = CFX_PLATFORM_UNKNOWN;
	this.platformVersion = CFX_PLATFORM_VERSION_UNKNOWN;
	var appName = navigator.appName;
	var appVersion = navigator.appVersion;
	var platform = navigator.platform;
	var userAgent = navigator.userAgent;
	if (appName == "Microsoft Internet Explorer" && (appVersion.indexOf("MSIE") > -1)) {
	 	this.client = CFX_BROWSER_IEXPLORER;
		this.clientVersion = parseInt(appVersion.substr(appVersion.indexOf("MSIE") + 5, 3));
	} else if (appName == "Netscape") {
		this.client = CFX_BROWSER_NETSCAPE;
		this.clientVersion = parseInt(appVersion.substr(0,5));
	}
	if (platform == "Win32") {
		this.platform = CFX_PLATFORM_WIN32;
		if (userAgent.indexOf("Windows NT 5.0") > -1) {
			this.platformVersion = CFX_PLATFORM_VERSION_WIN2000;
		} else if (userAgent.indexOf("Windows NT 4.0") > -1) {
			this.platformVersion = CFX_PLATFORM_VERSION_WINNT4;
		} else if ((userAgent.indexOf("Win98") > -1) || (userAgent.indexOf("Windows 98") > -1)) {
			this.platformVersion = CFX_PLATFORM_VERSION_WIN98;
		} else if ((userAgent.indexOf("Win95") > -1) || (userAgent.indexOf("Windows 95") > -1)) {
			this.platformVersion = CFX_PLATFORM_VERSION_WIN95;
		}
	}
	if (platform == "MacPPC") {
		this.platform = CFX_PLATFORM_MACOS;
	}
	this.imagesAvailable = false;
	this.timeoutAvailable = false;
	this.intervalAvailable = false;
	this.documentAllAvailable = false;
	this.DOMAvailable = false;
	this.layerAvailable = false;
	this.windowMovable = false;
	this.windowSizeAvailable = false;
	this.screenAvailable = false;
	if ((this.client == CFX_BROWSER_IEXPLORER) && (this.clientVersion < 5) && (this.platform == CFX_PLATFORM_MACOS))
	{
		/* stupid stupid MSIE4.5 on the mac completely f***s up the object capability tests. instead of just returning
		 * false or undefined, it hits us with errors. DUH.
		 * even though at this time this block only gets called for MacIE4.5, i'm testing for the capabilities anyway.
		 * other browsers might suck too, so i'll do the base work right now.
		 * object method tests currently don't work in MacIE4.5. 
		 */
		
		/* object property tests, these should work */
		this.imagesAvailable = (document.images) ? true : false;
		this.documentAllAvailable = (document.all) ? true : false;
		this.DOMAvailable = (document.implementation && document.implementation.hasFeature("HTML","1.0")) ? true : false;
		this.layerAvailable = (document.layers) ? true : false;
		this.windowSizeAvailable = (window.outerWidth) ? true : false;
		this.screenAvailable = (screen) ? true : false;
	}
	else
	{
		this.imagesAvailable = (document.images) ? true : false;
		this.timeoutAvailable = (window.setTimeout) ? true : false;
		this.intervalAvailable = (window.setInterval) ? true : false;
		this.documentAllAvailable = (document.all) ? true : false;
		this.DOMAvailable = (document.implementation && document.implementation.hasFeature("HTML","1.0")) ? true : false;
		this.layerAvailable = (document.layers) ? true : false;
		this.windowMovable = (window.moveTo) ? true : false;
		this.windowSizeAvailable = (window.outerWidth) ? true : false;
		this.screenAvailable = (screen) ? true : false;
	}
}

function cfxprivate_cfxModules() {
	/* This is where all loaded CFX modules register themselves with their version number.
	 * The name of the field is identical to the internal module name, which can be found in the
	 * module source files.
	 */
	this.core = CFX_CORE_VERSION;
}


/*** Functions ***************************************************************/
function cfx_preinit(command) {
	/* Shortcut for cfx_runlevelCommand() for runlevel 1 */
	cfx_runlevelCommand(CFX_RUNLEVEL_PREINIT, command);
}

function cfx_runlevelCommand(runlevel, command) {
	/* Takes a command and stores it in the command queue. As soon as the desired runlevel is reached, all given commands are
	 * executed directly.
	 */
	if (document.cfx_runlevel < runlevel) {
		cfxprivate_runlevel_commands[runlevel][cfxprivate_runlevel_commands[runlevel].length] = command;
	} else {
		eval(command);
	}
}

function cfx_eventCommand(ev, command) {
	/* Takes a command and stores it in the command queue. As soon as the event is fired, all given commands are
	 * executed.
	 */
	var idx = cfxprivate_event_commands[ev].length;
	cfxprivate_event_commands[ev][idx] = command;
//	alert(cfxprivate_event_commands[ev][idx]);
}

function cfxprivate_switchRunlevel(runlevel) {
	/* Switches to the stated runlevel and executes all accumulated runlevel commands */
	document.cfx_runlevel = runlevel;
	cfx_evalArray(cfxprivate_runlevel_commands[runlevel]);
}

function cfx_evalArray(arr) {
	/* Takes a String Array and evals all strings */
	for (var i = 0; i < arr.length; i++) {
//		alert(arr[i]);
		eval(arr[i]);
	}
}

function cfx_debugOn(deep,suppressAlert) {
	/* Turns on the real error handler. If deep is true, cfx.debugDeep will be set to true, causing some functions
	 * to display interesting stuff!
	 * Setting suppressAlert to true will suppress the "Debugging Activated" message.
	 * This is heavily discouraged because doing so will usually result in forgotten debugOn() calls
	 * in released websites.
	 */
	window.onerror = cfxprivate_onErrorHandlerDebug;
	cfx.debug = true;
	cfx.debugDeep = deep;
	if (!suppressAlert) {
		var alertstring = "* CFX Debugging activated *";
		alertstring += "\nThis is *not* an error message!";
		alertstring += "\nTo keep this message from opening, do not call cfx_debugOn() in";
		alertstring += "\n" + window.location.href;
		alertstring += "\n\n\nDebugging info:";
		alertstring += "\ncfx.browser.client == " + cfx.browser.client;
		alertstring += "\ncfx.browser.clientVersion == " + cfx.browser.clientVersion;
		alertstring += "\ncfx.browser.platform == " + cfx.browser.platform;
		alertstring += "\ncfx.browser.platformVersion == " + cfx.browser.platformVersion;
		alertstring += "\n\nCFX Full ID: " + CFX_CORE_FULLID;
		alert(alertstring);
	}
}

function cfx_debugOff() {
	/* Turns back to the dummy error handler */
	window.onerror = cfxprivate_onErrorHandlerDefault;
	cfx.debug = false;
	cfx.debugDeep = false;
}

function cfx_loadModule(module) {
	/* checks whether the named CFX module is already loaded and loads it if necessary */
	if (document.cfx_runlevel > CFX_RUNLEVEL_NONE) {
		if (!eval("cfx.modules." + module)) {
			document.write('<script src="' + cfx.location + 'cfx_' + module + '.js" language="JavaScript1.2" type="text/javascript"></script>');
		}
	} else {
		location.reload();
	}
}

function cfx_loadScript(url) {
	/* loads the JS script with the given URL */
	if (document.cfx_runlevel > CFX_RUNLEVEL_NONE) {
		document.write('<script src="' + url + '" language="JavaScript1.2" type="text/javascript"></script>');
	} else {
		location.reload();
	}
}

function cfx_setLocation(path) {
	/* sets the CFX path */
	cfx.location = path;
}

/*** Event Handlers **********************************************************/
function cfxprivate_onErrorHandlerDefault() {
	/* The default error handler only reloads the page to workaround some of the stupider Netscape 4 bugs,
	 * especially on the Mac and on some occasions cross-platform with frames. In these cases
	 * Netscape 4 seems to start the following scripts before the first one has completely loaded and
	 * executed, which of course wreaks havoc if those scripts depend on the first. All CFX modules
	 * depend on cfx_core.js, so this is a Bad Thing. Simply issuing a location.reload() seems to
	 * solve the problem.
	 * Warning: Will get stuck in a reload()-Loop in case there's a real error. See cfx_debugOn()
	 */
	location.reload();
	return true;
}

function cfxprivate_onLoadHandler() {
	cfxprivate_switchRunlevel(CFX_RUNLEVEL_PAGELOAD);
	cfx_evalArray(cfxprivate_event_commands["onload"]);
	cfxprivate_switchRunlevel(CFX_RUNLEVEL_FINAL);
}

function cfxprivate_onResizeHandler() {
	cfx_evalArray(cfxprivate_event_commands["onresize"]);
}

function cfxprivate_onErrorHandlerDebug(msg, url, lno) {
	/* Displays an alert() with error message, url and line number */
	alert("JS Error:\n" + msg + "\n\nFile: " + url + "\n\nLine number: " + lno);
	return true;
}

