
/**
 * SWFObject v1.5: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
 *
 * SWFObject is (c) 2007 Geoff Stearns and is released under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 */
if(typeof deconcept == "undefined") var deconcept = new Object();
if(typeof deconcept.util == "undefined") deconcept.util = new Object();
if(typeof deconcept.SWFObjectUtil == "undefined") deconcept.SWFObjectUtil = new Object();
deconcept.SWFObject = function(swf, id, w, h, ver, c, quality, xiRedirectUrl, redirectUrl, detectKey) {
	if (!document.getElementById) { return; }
	this.DETECT_KEY = detectKey ? detectKey : 'detectflash';
	this.skipDetect = deconcept.util.getRequestParameter(this.DETECT_KEY);
	this.params = new Object();
	this.variables = new Object();
	this.attributes = new Array();
	if(swf) { this.setAttribute('swf', swf); }
	if(id) { this.setAttribute('id', id); }
	if(w) { this.setAttribute('width', w); }
	if(h) { this.setAttribute('height', h); }
	if(ver) { this.setAttribute('version', new deconcept.PlayerVersion(ver.toString().split("."))); }
	this.installedVer = deconcept.SWFObjectUtil.getPlayerVersion();
	if (!window.opera && document.all && this.installedVer.major > 7) {
		// only add the onunload cleanup if the Flash Player version supports External Interface and we are in IE
		deconcept.SWFObject.doPrepUnload = true;
	}
	if(c) { this.addParam('bgcolor', c); }
	var q = quality ? quality : 'high';
	this.addParam('quality', q);
	this.setAttribute('useExpressInstall', false);
	this.setAttribute('doExpressInstall', false);
	var xir = (xiRedirectUrl) ? xiRedirectUrl : window.location;
	this.setAttribute('xiRedirectUrl', xir);
	this.setAttribute('redirectUrl', '');
	if(redirectUrl) { this.setAttribute('redirectUrl', redirectUrl); }
}
deconcept.SWFObject.prototype = {
	useExpressInstall: function(path) {
		this.xiSWFPath = !path ? "expressinstall.swf" : path;
		this.setAttribute('useExpressInstall', true);
	},
	setAttribute: function(name, value){
		this.attributes[name] = value;
	},
	getAttribute: function(name){
		return this.attributes[name];
	},
	addParam: function(name, value){
		this.params[name] = value;
	},
	getParams: function(){
		return this.params;
	},
	addVariable: function(name, value){
		this.variables[name] = value;
	},
	getVariable: function(name){
		return this.variables[name];
	},
	getVariables: function(){
		return this.variables;
	},
	getVariablePairs: function(){
		var variablePairs = new Array();
		var key;
		var variables = this.getVariables();
		for(key in variables){
			variablePairs[variablePairs.length] = key +"="+ variables[key];
		}
		return variablePairs;
	},
	getSWFHTML: function() {
		var swfNode = "";
		if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) { // netscape plugin architecture
			if (this.getAttribute("doExpressInstall")) {
				this.addVariable("MMplayerType", "PlugIn");
				this.setAttribute('swf', this.xiSWFPath);
			}
			swfNode = '<embed type="application/x-shockwave-flash" src="'+ this.getAttribute('swf') +'" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'" style="'+ this.getAttribute('style') +'"';
			swfNode += ' id="'+ this.getAttribute('id') +'" name="'+ this.getAttribute('id') +'" ';
			var params = this.getParams();
			 for(var key in params){ swfNode += [key] +'="'+ params[key] +'" '; }
			var pairs = this.getVariablePairs().join("&");
			 if (pairs.length > 0){ swfNode += 'flashvars="'+ pairs +'"'; }
			swfNode += '/>';
		} else { // PC IE
			if (this.getAttribute("doExpressInstall")) {
				this.addVariable("MMplayerType", "ActiveX");
				this.setAttribute('swf', this.xiSWFPath);
			}
			swfNode = '<object id="'+ this.getAttribute('id') +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'" style="'+ this.getAttribute('style') +'">';
			swfNode += '<param name="movie" value="'+ this.getAttribute('swf') +'" />';
			var params = this.getParams();
			for(var key in params) {
			 swfNode += '<param name="'+ key +'" value="'+ params[key] +'" />';
			}
			var pairs = this.getVariablePairs().join("&");
			if(pairs.length > 0) {swfNode += '<param name="flashvars" value="'+ pairs +'" />';}
			swfNode += "</object>";
		}
		return swfNode;
	},
	write: function(elementId){
		if(this.getAttribute('useExpressInstall')) {
			// check to see if we need to do an express install
			var expressInstallReqVer = new deconcept.PlayerVersion([6,0,65]);
			if (this.installedVer.versionIsValid(expressInstallReqVer) && !this.installedVer.versionIsValid(this.getAttribute('version'))) {
				this.setAttribute('doExpressInstall', true);
				this.addVariable("MMredirectURL", escape(this.getAttribute('xiRedirectUrl')));
				document.title = document.title.slice(0, 47) + " - Flash Player Installation";
				this.addVariable("MMdoctitle", document.title);
			}
		}
		if(this.skipDetect || this.getAttribute('doExpressInstall') || this.installedVer.versionIsValid(this.getAttribute('version'))){
			var n = (typeof elementId == 'string') ? document.getElementById(elementId) : elementId;
			n.innerHTML = this.getSWFHTML();
			return true;
		}else{
			if(this.getAttribute('redirectUrl') != "") {
				document.location.replace(this.getAttribute('redirectUrl'));
			}
		}
		return false;
	}
}

/* ---- detection functions ---- */
deconcept.SWFObjectUtil.getPlayerVersion = function(){
	var PlayerVersion = new deconcept.PlayerVersion([0,0,0]);
	if(navigator.plugins && navigator.mimeTypes.length){
		var x = navigator.plugins["Shockwave Flash"];
		if(x && x.description) {
			PlayerVersion = new deconcept.PlayerVersion(x.description.replace(/([a-zA-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split("."));
		}
	}else if (navigator.userAgent && navigator.userAgent.indexOf("Windows CE") >= 0){ // if Windows CE
		var axo = 1;
		var counter = 3;
		while(axo) {
			try {
				counter++;
				axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+ counter);
//				document.write("player v: "+ counter);
				PlayerVersion = new deconcept.PlayerVersion([counter,0,0]);
			} catch (e) {
				axo = null;
			}
		}
	} else { // Win IE (non mobile)
		// do minor version lookup in IE, but avoid fp6 crashing issues
		// see http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
		try{
			var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
		}catch(e){
			try {
				var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
				PlayerVersion = new deconcept.PlayerVersion([6,0,21]);
				axo.AllowScriptAccess = "always"; // error if player version < 6.0.47 (thanks to Michael Williams @ Adobe for this code)
			} catch(e) {
				if (PlayerVersion.major == 6) {
					return PlayerVersion;
				}
			}
			try {
				axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
			} catch(e) {}
		}
		if (axo != null) {
			PlayerVersion = new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));
		}
	}
	return PlayerVersion;
}
deconcept.PlayerVersion = function(arrVersion){
	this.major = arrVersion[0] != null ? parseInt(arrVersion[0]) : 0;
	this.minor = arrVersion[1] != null ? parseInt(arrVersion[1]) : 0;
	this.rev = arrVersion[2] != null ? parseInt(arrVersion[2]) : 0;
}
deconcept.PlayerVersion.prototype.versionIsValid = function(fv){
	if(this.major < fv.major) return false;
	if(this.major > fv.major) return true;
	if(this.minor < fv.minor) return false;
	if(this.minor > fv.minor) return true;
	if(this.rev < fv.rev) return false;
	return true;
}
/* ---- get value of query string param ---- */
deconcept.util = {
	getRequestParameter: function(param) {
		var q = document.location.search || document.location.hash;
		if (param == null) { return q; }
		if(q) {
			var pairs = q.substring(1).split("&");
			for (var i=0; i < pairs.length; i++) {
				if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
					return pairs[i].substring((pairs[i].indexOf("=")+1));
				}
			}
		}
		return "";
	}
}
/* fix for video streaming bug */
deconcept.SWFObjectUtil.cleanupSWFs = function() {
	var objects = document.getElementsByTagName("OBJECT");
	for (var i = objects.length - 1; i >= 0; i--) {
		objects[i].style.display = 'none';
		for (var x in objects[i]) {
			if (typeof objects[i][x] == 'function') {
				objects[i][x] = function(){};
			}
		}
	}
}
// fixes bug in some fp9 versions see http://blog.deconcept.com/2006/07/28/swfobject-143-released/
if (deconcept.SWFObject.doPrepUnload) {
	if (!deconcept.unloadSet) {
		deconcept.SWFObjectUtil.prepUnload = function() {
			__flash_unloadHandler = function(){};
			__flash_savedUnloadHandler = function(){};
			window.attachEvent("onunload", deconcept.SWFObjectUtil.cleanupSWFs);
		}
		window.attachEvent("onbeforeunload", deconcept.SWFObjectUtil.prepUnload);
		deconcept.unloadSet = true;
	}
}
/* add document.getElementById if needed (mobile IE < 5) */
if (!document.getElementById && document.all) { document.getElementById = function(id) { return document.all[id]; }}

/* add some aliases for ease of use/backwards compatibility */
var getQueryParamValue = deconcept.util.getRequestParameter;
var FlashObject = deconcept.SWFObject; // for legacy support
var SWFObject = deconcept.SWFObject;

/*
 * Debug functions
 */
function fE (){
	if( console ) console.error( arguments );
}

/*
 * a is the user logged in test
 */
function isLoggedIn (){ return (loggedInID != -1); }

/*
 * Error checking inputs
 * 
 * integer	default 0
 * boolean	default false
 * string	default ""
 * 
 */
function booleanValue ( value, defaultVaule ){
	if( isEmpty(value) ) {				//no vaule? try a defult?
		if( !defaultVaule ) return false;
		else return defaultVaule;
	}
	if( typeof(value) == 'string' ){ return (parseInt(value) == 0) ? false : true; }
	else return (value);
}
function integerValue ( value, defaultVaule ){
	if( isEmpty(value) ) { 				//no vaule? try a defult?
		if( !defaultVaule ) return 0;
		else return defaultVaule;
	}
	value = parseInt(value);
	if( typeof(value) == 'number' ){ return value; }
	else return 0;
}
function stringValue ( value, defaultVaule ){
	if( isEmpty(value) ) {				//no vaule? try a defult?
		if( !defaultVaule ) return "";
		else return defaultVaule;
	}
	if( typeof(value) == 'string' ){ return value; }
	else return "";
}
		
/*
 * basic cookie functions
 */
function deleteCookie(name, path, domain) {
	if (getCookie(name)) document.cookie = name + "=" + ((path)? ";path=" + path : "") + ((domain)? ";domain=" + domain : "" ) + ";expires=Thu, 01-Jan-1970 00:00:01 GMT";
}

function getCookie(name) {
	var start = document.cookie.indexOf(name + "=");
	var len = start + name.length + 1;
	if ((!start) && (name != document.cookie.substring(0, name.length))) return null;
	if (start == -1) return null;
	var end = document.cookie.indexOf(";", len);
	if (end == -1) end = document.cookie.length;
	return unescape(document.cookie.substring(len, end));
}

/*
 * Activity
 */
var activityTimers = {};
function resetActivity (timerKey, activityTimeout, timeoutCallback ){
	try{ clearTimeout( activityTimers[timerKey] ); } catch (ex){}
	activityTimers[timerKey] = setTimeout(timeoutCallback, activityTimeout);
}
function cancelActivityTimer(timerKey){
	try{ clearTimeout( activityTimers[timerKey] ); } catch (ex){}
	delete activityTimers[timerKey];
}

/*
 * User Prompts
 */
function userNotice 	( title, message ){  }
function userWarning 	( title, message ){  }
function userError 		( title, message ){  }
/***********************************************
 *
 * AJAX Functionality
 *
 * 		{
 * 			successful: false,
 * 			messages:
 * 				[
 * 					{ code:		1564, message: 	'Email Address Invalid' },
 * 					{ code:		1562, message: 	'No Zip Code' },
 * 					{ code:		1564, message: 	'Yo momz is too crazy' }
 * 				]
 * 		}
 *
 *
 *
 *
 *
 *		ajax.post('/' + path + '/Hookup.cmd',
 *			{
 *				type : 'Hookup',
 *				id1: id1,
 *				id2: id2,
 *				msg: text
 *			},
 *			function (connectionInstance){
 *				var response = connectionInstance.responseObject;
 *				if( response ){
 *					if(response.successful){
 *						if( response.messages ){
 *							displayResponseObject( response );
 *						} else {
 *							showMsg("Cirkit Connect", "Your Cirkit Connect has been sent." , false);
 *							endHookup();
 *						}
 *					} else {
 * 						//here we can return false, and ajax will call the onError function for us
 * 						// but for this instance that is only used for system errors.
 *						displayResponseObject(response);
 *					}
 *
 *				} else {
 *					showMsg("Cirkit Connect", "The server returned no data. Please try again." , true);
 *				}
 *			},
 *			function (connectionInstance){
 *				showMsg("Cirkit Connect", "There was an unexpected error while processing your request." , true);
 *			}
 *		);
 *	}
 *
 *
 ***********************************************/
var GET = 'get';
var POST = 'post';
var ajax;
function Ajax() {
	this.connections = [];
	this.currentRequest = null;
}
Ajax.prototype = {
	get: function(url, requestObject, onSuccess, onError, dataWindow, showLoadingIcon){
		var req = new HTTP( GET, url, requestObject, onSuccess, onError, dataWindow, showLoadingIcon  );
		
		//every ajax request gets a thread
		setTimeout ( function (){ req.commit(); }, 0);
	},
	post: function (url, requestObject, onSuccess, onError, dataWindow, showLoadingIcon){
		var req = new HTTP( POST, url, requestObject, onSuccess, onError, dataWindow, showLoadingIcon  );
		
		//every ajax request gets a thread
		setTimeout ( function (){ req.commit(); }, 0);
	}
}

function HTTP( method, url, requestObject, onSuccess, onError, dataWindow, showLoadingIcon ){
	//all defaults
	this.key = 				this.makeKey();
	this.method = 			method;
	this.url = 				url;
	this.httpStatus = 		null;
	this.requestObject = 	(requestObject) ? requestObject : null;
	this.serverResponse = 	"";
	this.responseObject = 	null;
	this.onError = 			onError;
	this.onSuccess =		onSuccess;
	this.dataWindow = 		dataWindow;
	this.showLoadingIcon = 	( isEmpty(showLoadingIcon) ) ? true : false ;

	return this;
}
HTTP.prototype = {
	/*********************************
	 * AJAX Functions - Doc comming soon
	**********************************/
	createHTTP: function (){
		if(typeof XMLHttpRequest != "undefined"){ return new XMLHttpRequest(); }
		else if( window.ActiveXObject ) {
			var testObj = [
				"MSXML2.XMLHttp.5.0",
				"MSXML2.XMLHttp.4.0",
				"MSXML2.XMLHttp.3.0",
				"MSXML2.XMLHttp",
				"Microsoft.XMLHttp.5.0"
			];
			for( var i = 0; i < testObj.length; i++){
				try{
					var xmlObj = new ActiveXObject(testObj[i]);
					return xmlObj;
				}
				catch( err ){  }
			}
		}
		return false;
		//return new XMLHttpRequest;
	},
	
	//ajax connection key generator
	makeKey: function(){
		var date = new Date();
		return 	date.getHours() + "" + date.getMinutes() + "" + date.getSeconds() + "" + date.getMilliseconds();
	},

	commit: function() {
		var ohttp = this.createHTTP();
		var connectionInst = this;
		this.request = this.serializeData(this.requestObject);	//serialized request
		
		try{
			if(this.dataWindow && this.showLoadingIcon ) this.dataWindow.setLoading(true);

			ohttp.open( this.method, this.url, true );

			if(this.method == POST){ 	//posting requires some headers
				ohttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
				ohttp.setRequestHeader("Content-length", this.request.length);
				ohttp.setRequestHeader("Connection", "close");
			}

			ohttp.onreadystatechange = function () {
				var success = true;
				switch (ohttp.readyState){
					case 0: //Uninitialized
						break;
					case 1: //Open
						if(connectionInst.dataWindow) connectionInst.dataWindow.setStatus("Connected");
						break;
					case 2: //Sent
						if(connectionInst.dataWindow) connectionInst.dataWindow.setStatus("Sending request");
						break;
					case 3: //Receiving
						if(connectionInst.dataWindow) connectionInst.dataWindow.setStatus("Receiving Data");
						break;
					case 4: //Loaded
						if(connectionInst.dataWindow) connectionInst.dataWindow.setStatus("Reading Result");
						connectionInst.httpStatus = ohttp.status;
						
						if(connectionInst.httpStatus == 200) {
							
							//gathering info
			                connectionInst.serverResponse = ohttp.responseText;
							connectionInst.responseObject = JSON.parse(ohttp.responseText);

							//disable the loading icon
			              	if(connectionInst.dataWindow){
		              			if( connectionInst.showLoadingIcon ) connectionInst.dataWindow.setLoading(false);
			               		connectionInst.dataWindow.setStatus("Idle");
			               	}
							
							//server error check
							if( connectionInst.responseObject ){
								if( connectionInst.responseObject.success == false ){
									//there was a server error response.
									try{ client.processError(connectionInst.responseObject); }
									catch ( ex ) {}
									success = false;
								}
							}
						}

						if( success ) {
			               	//call onSuccess,
			               	// if we get a false, go to
							if(connectionInst.onSuccess){
								if( !connectionInst.onSuccess(connectionInst) ) {
								}
							}

			           	} else {

			              	if(connectionInst.dataWindow){
		              			if( connectionInst.showLoadingIcon ) connectionInst.dataWindow.setLoading(false);
			               		connectionInst.dataWindow.setStatus("Server Error");
								setTimeout( function () { connectionInst.dataWindow.setStatus('Idle'); }, 5000 );
			               	}
			            	if(connectionInst.onError){
			            		connectionInst.onError(connectionInst);
			            	}

						}
						
						break;
					default:
						break;
				}
		    };

		    //send the post data if posting
		    ohttp.send(
		    	(this.method == POST) ?
		    		"&" + this.request:
		    		null //otherwise null
		    );
			return true;
		} catch(ex) {
			if( isString(ex) ){
				//alert(ex);
				return false;
			}

			
		}
	    return false;
	},

	/*************************************************
		Encodes text for url and removes javascript
	**************************************************/
	setData : function (newData){
		this.requestObject = this.serializeData(newData);
	},
	
	serializeData: function (dataObject){
		var data = "";
		var amp = "";
		for(var valueID in dataObject){
			data += amp + valueID +  "=" + this.encode( dataObject[valueID] );
			amp = "&";
		}

		return data;
	},
	encode: function(val){
		return prepMessage(val);
	},
	decode: function(rootElement){
		if(rootElement == dhNull){
			rootElement = this.responseObject; //start from the bottom up
		}
		for(var valueID in rootElement){
			var elem = rootElement[valueID];
			switch( typeof(elem) ){
				case 'string':
					elem = prepMessage( elem, true);
					rootElement[valueID] = elem;
					break;
				case 'object':
				case 'array':
					if(elem != null) this.decode(elem);
					break;
				default:
					break;
			}
		}
	},
	cleanJavascript: function(str){
		str = str.replace(/\<script.*?\>.*?\<\/script\>/g, '');
		str = str.replace(/<[^>]*="javascript:[^"]*"[^>]*>/g, '');
		return str;
	},
	makeUrlsClickable : function (str){
		return str.replace(/(https:\/\/|http:\/\/|ftp:\/\/|www\.)([^\s]*)/gi,'<a href="http://$2" target="_blank">$1$2</a>');
	}
}

/*************************************************
	Makes email/bulletin/comment
	message proper for storage and display
**************************************************/
function prepMessage(msg, decode, formatUrls){
	if (isEmpty(msg)) return "";
	msg = String(msg);
	if (decode){
		while (msg != unescape(msg)) msg = unescape(msg);
		msg = unescape(msg);
		try {
			msg = decodeURIComponent(msg);
		} catch (ex) {
        	//?
		}
		//if(!isEmpty(formatUrls)) msg = makeUrlsClickable(msg);
	}else{
		// replace all <br /> tags generated by fckEditor
		msg = msg.replace(/<br \/>/g, '');

		// convert all new lines/carriage returns to a line break
		msg = msg.replace(/\r\n|\r|\n/g, '<br />');
		//msg = msg.replace(/\n|\r\n/g, '<br />');

		// strip all javascript
		msg = cleanJavascript(msg);

		// escape the result
		msg = escape(msg);
	}
	return msg;
}

function htmlspecialchars_decode( input ){
	input = input.replace( /&amp;/gi, "&");
	input = input.replace( /&quot;/gi,"\"");
	input = input.replace( /&#039;/gi,"'");
	input = input.replace( /&lt;/gi, 	"<");
	input = input.replace( /&gt;/gi, 	">");
	return input;
}
function htmlspecialchars_encode( input ){
	input = input.replace( "&",  "&amp;");
	input = input.replace( /"/g, "&quot;");
	input = input.replace( /'/g, "&#039;");
	input = input.replace( "<",  "&lt;");
	input = input.replace( ">",  "&gt;");
	return input;
}
function htmlspecialchars_bitcode( input ){
	input = input.replace( "&",  "&amp;");
	input = input.replace( /"/g, "\\&quot;");
	input = input.replace( /'/g,	 "\\&#039;");
	input = input.replace( "<",  "&lt;");
	input = input.replace( ">",  "&gt;");

	return input;
}
/**********************************************
	Functions for cleaning all text elements
	* Both encoding and decoding
**********************************************/
function cleanJavascript(str){
	str = str.replace(/\<script.*?\>.*?\<\/script\>/g, '');
	str = str.replace(/<[^>]*="javascript:[^"]*"[^>]*>/g, '');
	return str;
}
function makeUrlsClickable(str){
	var index = parseInt(str.search(/(&lt;|<)([aA].*)([^\s]*)/));

	if(index >= 0){
		return parseAnchorTag(str,index);
	}

	return str.replace(/(https:\/\/|http:\/\/|ftp:\/\/|www\.)([^\s]*)/gi,'<a href="http://$2" target="_blank">$1$2</a>');
}
function parseAnchorTag(str,startTag){
	var endTag = parseInt((str.search(/(&lt;|<)\/a(&gt;|>)/)))+10;
	var formerStr = makeUrlsClickable(str.substring(0,startTag-1));
	var latterStr = makeUrlsClickable(str.substring(endTag));

	var anchorTag = str.substring(startTag,endTag).replace(/(&lt;|<)[aA].*href=&quot;((https:\/\/|http:\/\/|ftp:\/\/|www\.)([^\s]*))&quot;.*(&gt;|>)(.*)(&lt;|<)\/a(&gt;|>)/,"<a href='http://$4'>$6</a>");
	return formerStr+anchorTag+latterStr;
}
function cleanMarkup(html) {
	html = html.replace(/<o:p>\s*<\/o:p>/g, "") ;
	html = html.replace(/<o:p>.*?<\/o:p>/g, "&nbsp;") ;

	// Remove mso-xxx styles.
	html = html.replace( /\s*mso-[^:]+:[^;"]+;?/gi, "" ) ;

	// Remove margin styles.
	html = html.replace( /\s*MARGIN: 0cm 0cm 0pt\s*;/gi, "" ) ;
	html = html.replace( /\s*MARGIN: 0cm 0cm 0pt\s*"/gi, "\"" ) ;
	html = html.replace( /\s*TEXT-INDENT: 0cm\s*;/gi, "" ) ;
	html = html.replace( /\s*TEXT-INDENT: 0cm\s*"/gi, "\"" ) ;
	html = html.replace( /\s*TEXT-ALIGN: [^\s;]+;?"/gi, "\"" ) ;
	html = html.replace( /\s*PAGE-BREAK-BEFORE: [^\s;]+;?"/gi, "\"" ) ;
	html = html.replace( /\s*FONT-VARIANT: [^\s;]+;?"/gi, "\"" ) ;
	html = html.replace( /\s*tab-stops:[^;"]*;?/gi, "" ) ;
	html = html.replace( /\s*tab-stops:[^"]*/gi, "" ) ;

	// Remove Class attributes
	html = html.replace(/<(\w[^>]*) class=([^ |>]*)([^>]*)/gi, "<$1$3");

	// Remove empty styles.
	html = html.replace( /\s*style="\s*"/gi, '' );
	html = html.replace( /<SPAN\s*[^>]*>\s*&nbsp;\s*<\/SPAN>/gi, '&nbsp;' );
	html = html.replace( /<SPAN\s*[^>]*><\/SPAN>/gi, '' );

	// Remove Lang attributes
	html = html.replace(/<(\w[^>]*) lang=([^ |>]*)([^>]*)/gi, "<$1$3");
	html = html.replace( /<SPAN\s*>(.*?)<\/SPAN>/gi, '$1' );
	html = html.replace( /<FONT\s*>(.*?)<\/FONT>/gi, '$1' );

	// Remove XML elements and declarations
	html = html.replace(/<\\?\?xml[^>]*>/gi, "");
	html = html.replace(/<\/?\w+:[^>]*>/gi, "");

	// Remove comments [SF BUG-1481861].
	html = html.replace(/<\!--.*-->/g, "");
	html = html.replace( /<H\d>\s*<\/H\d>/gi, '' );
	html = html.replace( /<H1([^>]*)>/gi, '<div$1><b><font size="6">' );
	html = html.replace( /<H2([^>]*)>/gi, '<div$1><b><font size="5">' );
	html = html.replace( /<H3([^>]*)>/gi, '<div$1><b><font size="4">' );
	html = html.replace( /<H4([^>]*)>/gi, '<div$1><b><font size="3">' );
	html = html.replace( /<H5([^>]*)>/gi, '<div$1><b><font size="2">' );
	html = html.replace( /<H6([^>]*)>/gi, '<div$1><b><font size="1">' );
	html = html.replace( /<\/H\d>/gi, '<\/font><\/b><\/div>' );

	// Remove empty tags (three times, just to be sure).
	html = html.replace( /<([^\s>]+)(\s[^>]*)?>\s*<\/\1>/g, '' );
	html = html.replace( /<([^\s>]+)(\s[^>]*)?>\s*<\/\1>/g, '' );
	html = html.replace( /<([^\s>]+)(\s[^>]*)?>\s*<\/\1>/g, '' );

	// Transform <P> to <DIV>
	var re = new RegExp( "(<P)([^>]*>.*?)(<\/P>)", "gi" );	// Different because of a IE 5.0 error
	html = html.replace( re, "<div$2<\/div>" );

	// Fix relative anchor URLs (IE automatically adds the current page URL).
	re = new RegExp( window.location + "#", "g" );
	html = html.replace( re, '#');
	return html;
}




/*
Copyright (c) 2005 JSON.org

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The Software shall be used for Good, not Evil.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

/*
    The global object JSON contains two methods.

    JSON.stringify(value) takes a JavaScript value and produces a JSON text.
    The value must not be cyclical.

    JSON.parse(text) takes a JSON text and produces a JavaScript value. It will
    return false if there is an error.
*/
var JSON = function () {
    var m = {
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        },
        s = {
            'boolean': function (x) {
                return String(x);
            },
            number: function (x) {
                return isFinite(x) ? String(x) : 'null';
            },
            string: function (x) {
                if (/["\\\x00-\x1f]/.test(x)) {
                    x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) {
                        var c = m[b];
                        if (c) {
                            return c;
                        }
                        c = b.charCodeAt();
                        return '\\u00' +
                            Math.floor(c / 16).toString(16) +
                            (c % 16).toString(16);
                    });
                }
                return '"' + x + '"';
            },
            object: function (x) {
                if (x) {
                    var a = [], b, f, i, l, v;
                    if (x instanceof Array) {
                        a[0] = '[';
                        l = x.length;
                        for (i = 0; i < l; i += 1) {
                            v = x[i];
                            f = s[typeof v];
                            if (f) {
                                v = f(v);
                                if (typeof v == 'string') {
                                    if (b) {
                                        a[a.length] = ',';
                                    }
                                    a[a.length] = v;
                                    b = true;
                                }
                            }
                        }
                        a[a.length] = ']';
                    } else if (x instanceof Object) {
                        a[0] = '{';
                        for (i in x) {
                            v = x[i];
                            f = s[typeof v];
                            if (f) {
                                v = f(v);
                                if (typeof v == 'string') {
                                    if (b) {
                                        a[a.length] = ',';
                                    }
                                    a.push(s.string(i), ':', v);
                                    b = true;
                                }
                            }
                        }
                        a[a.length] = '}';
                    } else {
                        return;
                    }
                    return a.join('');
                }
                return 'null';
            }
        };
    return {
        copyright: '(c)2005 JSON.org',
        license: 'http://www.crockford.com/JSON/license.html',
/*
    Stringify a JavaScript value, producing a JSON text.
*/
        stringify: function (v) {
            var f = s[typeof v];
            if (f) {
                v = f(v);
                if (typeof v == 'string') {
                    return v;
                }
            }
            return null;
        },
/*
    Parse a JSON text, producing a JavaScript value.
    It returns false if there is a syntax error.
*/
        parse: function (text) {
            try {
                return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
                        text.replace(/"(\\.|[^"\\])*"/g, ''))) &&
                    eval('(' + text + ')');
            } catch (e) {
                return false;
            }
        }
    };
}();

function login(){
	//save in autocompelte
	getObject('loginForm').submit();

	var username = getObject("login_email").value;
	if (isEmpty(username)) {
		alert('Invalid username');
		return false;
	}

	var pass = getObject("login_pass").value;
	if (isEmpty(pass)){
		alert('Please enter password.');
		return false;
	}

	var rememberMe = getObject("rememberMe");
	if (rememberMe.checked){
		rememberMe = 'true';
	}else{
		rememberMe = 'false';
	}

	var seed = '';
	// get the seed first
	ajax.post('/api/processors/login',
		{
			a: 's'
		},

		function (connectionInstance){

			// we got the seed, lets attempt to log in
			var seed = connectionInstance.serverResponse;
			ajax.post('/api/processors/login',
				{
					a: 'login',
					hash: hex_sha1(hex_sha1(pass) + seed),
					s: seed,
					user: username,
					rme: rememberMe
				},

				function (connectionInstance){
					if(connectionInstance.responseObject){
						var res = connectionInstance.responseObject;
						if( res.profile_info.url_name ){
							window.location.href = "/" + res.profile_info.url_name;
						} else {
							window.location.href = "/user/" + res.profile_info.user_id;
						}
					}else if (connectionInstance.serverResponse == 'false'){
						alert("Invalid username and/or password.");
						//client.userError("Log In", "Invalid username and/or password.");
					}else{
						alert(connectionInstance.serverResponse);
						//client.userError("Log In", connectionInstance.serverResponse);
					}
					return true;
				},

				function (connectionInstance){
					alert("Login request failed, please try again.");
					//client.userError("Log In", "Login request failed, please try again.");
				}
			);
			return true;
		},

		function (connectionInstance){
			alert("Login key request failed. Please try again.");
			//client.userError("Log In", "Login key request failed. Please try again.");
		}
	);

}

function logout(){

	ajax.post('/api/processors/login',
		{
			a: 'logout'
		},

		function (connectionInstance){
			//client.userNotice("Log out", "You have been logged out of eCirkit.com successfully.");
			deleteCookie("ecsid", "/");
			// delete remember me cookie
			// this is the only time this gets deleted
			deleteCookie("ecrme", "/");
			loggedInID = -1;
			login_logout();
			return true;
		},
		function (connectionInstance){
			alert("Log out request failed. Please try again.");
			//client.userError("Log out", "Log out request failed. Please try again.");
		}
	);

}

function login_logout ( ){
	//some after we login / logout checks
	if( this.isLoggedIn() ){
		//if the login window is up, we're waiting for SOMETHING

		//update the log in / log out button
		hideObject(getObject('form_login'));
		showObject(getObject('form_loggedin'));
		//dh.nodes.loggedInAsCaption.write("<strong>" + this.data.userInfo.profile_info.display_name + "</strong>'s toolbar. <a href='#' onclick='client.login_logout(true); return false;' class='logout'>click here to log out.");
		//dh.nodes.login.write("Log Out");

	//login failed or was cancelled
	} else {
		//if the login window is up, we're waiting for SOMETHING

		//update the log in / log out button
		showObject(getObject('form_login'));
		hideObject(getObject('form_loggedin'));
		
		document.location.href = "http://"+document.domain+"/";
		//dh.nodes.loggedInAsCaption.write("<a href='#' onclick='client.login_logout(true); return false;' class='logout'>Click here to log in.");
		//dh.nodes.login.write("Log In");
	}
}

var ajax;
var cC;

function init( email ){

	ajax = new Ajax();
	cC = new cClient();

	//add the upodates flash display
   	var so = new SWFObject("/flash/frontpage-rtmp.swf", "billboardswf", "475", "225", "8");
   	so.addParam("wmode", "transparent");
   	so.write("billboard");
	
	if(email && email != ''){
		openRegister();
		getObject('reg_email').value = email;
		getObject('reg_email').onkeyup();
	}
}

function openForm( formName ){
	var form = getObject(formName)
	showObject(form);
	X( form, parseInt((cC.viewportW - getW(form)) / 2 ) + cC.scrollLeft);
	Y( form, parseInt((cC.viewportH - getH(form)) / 2 ) + cC.scrollTop);
	showObject(form);
}

	//registration functions
	function openRegister(){
		cC.showMatte( false, closeRegister );
		openForm('registrationForm')
	}

	function closeRegister() {
		hideObject(getObject('registrationForm'));
		return true; //this is a closeMatte callback, return true to continue
	}

	function openInvite(){
		cC.showMatte( false, closeInvite );
		openForm('inviteForm')
	}

	function closeInvite() {
		hideObject(getObject('inviteForm'));
		return true; //this is a closeMatte callback, return true to continue
	}

	function register(){
		var email = getObject('reg_email');
		var pass =	getObject('reg_pass');
		var cpass = getObject('reg_cpass');
		var tos = getObject('reg_tos');

		if( !email || !pass || !cpass ) return; //some sort of bizarre error would cause this

		if(!email.valid){
			email.focus();
			email.select();
			return;
		}

		if(!cpass.valid){
			cpass.focus();
			cpass.select();
			return;
		}

		if( isEmpty(email.value) ){
			setFieldStatus(email, 'above', 'error', 'No email address specified.');
			return;
		}

		if( trim(pass.value) == "" || trim(cpass.value) == "" ){
			setFieldStatus(cpass, 'below', 'error', 'Please confirm your password.');
			return;
		}

		if(pass.value != cpass.value ){
			setFieldStatus(cpass, 'below', 'error', 'Passwords do not match');
			return;
		}

		if( !tos.checked ){
			alert("You must agree to the terms of service and verify your age to continue.");
			//client.userError('Registration Error', "You must agree to the terms of service and verify your age to continue.")
			return;
		}

		document.body.style.cursor = 'wait';

		ajax.post('/api/processors/registration',
			{
				action : 'register',
				email :	email.value,
				password : hex_sha1(cpass.value)
			},
			function ( connectionInstance ) {
				if( connectionInstance.serverResponse != 'false' ) {
					window.newUserID = parseInt(connectionInstance.serverResponse);
					email.value = '';
					cC.closeMatte();
					document.body.style.cursor = 'default';
					window.location.href = "/user/" + window.newUserID + "?layer=webtop";
				} else {
					//getObject('registrationFormError').innerHTML = connectionInstance.serverResponse
					//client.userError("Request Error","There has been an error in processing your invitation request. Please Try Again.");
					alert("There has been an error in processing your registration request. Please Try Again.");

				}
				return true;
			},
			function ( connectionInstance ) {}
		)
		return false;
	}

	function invite(){
		var email = getObject('inv_email');

		if( !email ) return; //some sort of bizarre error would cause this

		if(!email.valid){
			email.focus();
			email.select();
			return;
		}

		if( isEmpty(email.value) ){
			setFieldStatus(email, 'above', 'error', 'No email address specified.');
			return;
		}



		ajax.post('/api/processors/registration',
			{
				action : 'invite',
				email :	email.value
			},
			function ( connectionInstance ) {
				if( connectionInstance.serverResponse == 'true' ) {

					window.newUserID = parseInt(connectionInstance.serverResponse);
					email.value = '';
					cC.closeMatte();

					alert("We have received your invitation request. When it is approved you will receive an e-mail containing your login information.");


				} else {
					alert("There has been an error in processing your invitation request. Please Try Again.");
				}
				return true;
			},
			function ( connectionInstance ) {}
		)
		return false;
	}

	/*--------------------------
	 * Forgot PW section
	 ---------------------------*/
	function forgotpw(){
		cC.showMatte( false, closeForgotPW );
		openForm('forgotPWForm')
	}

	function closeForgotPW() {
		hideObject(getObject('forgotPWForm'));
		return true; //this is a closeMatte callback, return true to continue
	}

	function sendNewPassword(){

		var emailField = getObject('pw_email');

		if( emailField.value == "" ){
			setFieldStatus( getObject('pw_email') , getObject('pw_icon'), getObject('pw_label'), 'error', 'You must enter an e-mail address.');
			return;
		}

		setFieldStatus( getObject('pw_email') , getObject('pw_icon'), getObject('pw_label'), 'loading', 'Sending request...');

		ajax.post(
			'/api/processors/registration',
			{
				action : 'forgotPass',
				email : emailField.value
			},
			function ( connectionInstance ){
				if( connectionInstance.serverResponse != 'true' ){
					//user's an ass
					setFieldStatus( getObject('pw_email') , getObject('pw_icon'), getObject('pw_label'), 'error', connectionInstance.serverResponse);
				} else {

					//reset the email field
					emailField.value = "";
					setFieldStatus( getObject('pw_email') , getObject('pw_icon'), getObject('pw_label'), 'default', 'Enter an e-mail address below');

					//hide the forgot pass form
					cC.closeMatte();

					//show a notice
					//client.userNotice("Forgotten Password", "A new password has been created and sent to your e-mail address.");
					alert("A new password has been created and sent to your e-mail address.");
				}
			},
			function ( connectionInstance ){
			}
		);
	}



	/**
		API Key Request
	*/
	function openApiKeyRequest(){

		//click to exit version
		cC.showMatte( false, closeApiKeyRequest );
		openForm('apiKeyRequestForm');
	}

	function closeApiKeyRequest(){
		hideObject(getObject('apiKeyRequestForm'));
		return true; //this is a closeMatte callback, return true to continue
	}

	function sendApiKey(){

		var email = getObject('api_email');
		var website = getObject('api_website');

		if( !email /*|| !pass || !cpass*/ ) return; //some sort of bizarre error would cause this

		if( isEmpty(email.value) ){
			//client.userNotice("API Registration", "Please enter your e-mail address.");
			alert("Please enter your e-mail address.");
			return;
		}

		if( isEmpty(website.value) ){
			//client.userNotice("API Registration", "Please enter the website you wish to use the eCirkit API on.");
			alert("Please enter the website you wish to use the eCirkit API on.");
			return;
		}

		ajax.post('/api/processors/registration',
			{
				action : 'apiRegistration',
				email :	email.value,
				website: website.value
			},
			function ( connectionInstance ) {
				if( connectionInstance.serverResponse == 'true' ) {
					cC.closeMatte();
					//client.userNotice("API Request Sent","An e-mail containing your eCirkit API Key has been sent to the e-mail address you provided.");
					alert("An e-mail containing your eCirkit API Key has been sent to the e-mail address you provided.");
				} else {
					//client.userError("API Request Error", connectionInstance.serverResponse);
					alert(connectionInstance.serverResponse);
				}
				return true;
			},
			function ( connectionInstance ) {

			}
		)

		return false;
	}



	/*
	 * elementsToColor may be a single object
	 */
	function setFieldStatus( elementsToColor , iconNode, labelNode, status, labelText){

		var bgColor = "";
		var labelClass = "";
		var iconClass = "";
		var valid = false;

		switch(status){
			case 'default':
				iconClass = 'a statusIcon';
				labelClass = 'a gtm';
				break;
			case 'loading':
				iconClass = 'a statusIcon statusLoading';
				labelText = "checking..."
				labelClass = 'a gtm';
				break;
			case 'ok':
				iconClass = 'a statusIcon statusOk';
				labelText = "OK";
				labelClass = 'a clG gtm b'
				bgColor = '#d9ffd9';
				valid = true;
				break;
			case 'error':
				iconClass = 'a statusIcon statusError';
				labelClass = 'a clR gtm b'
				bgColor = '#ffd9d9';
				break;
		}

		if( isArray(elementsToColor) ){
			for( var elemID in elementsToColor ){
				var elem = elementsToColor[elemID];
				elem.style.backgroundColor = bgColor;
				elem.valid = valid;
			}
		} else {
			elementsToColor.style.backgroundColor = bgColor;
			elementsToColor.valid = valid;
		}

		if(iconNode){
			iconNode.className = iconClass;
			showObject(iconNode);
		}

		if(labelNode){
			labelNode.className = labelClass;
			if(labelText){
				labelNode.innerHTML = labelText;
			}
			showObject(labelNode);
		}


	}

	//form field testing functions
	function testEmail(){
		//function fieldValidatior(fieldName, elementsToColor , iconNode, labelNode){
		 fieldValidatior( 'email', getObject('reg_email'), getObject('email_icon'),  getObject('email_label') );
	}

	//form field testing functions
	function testInvEmail(){
		//function fieldValidatior(fieldName, elementsToColor , iconNode, labelNode){

		 fieldValidatior( 'email', getObject('inv_email'), getObject('email_inv_icon'),  getObject('email_inv_label') , true );
	}

	function testPasswords(){
		var p = getObject('reg_pass');
		var cp = getObject('reg_cpass');

		var elements = [];
		elements[0] = p;
		elements[1] = cp;

		//function setFieldStatus( elementsToColor , iconNode, labelNode, status, labelText)

		if( trim(p.value) == "" ){
			setFieldStatus( [p,cp] , getObject('pass_icon'), getObject('pass_label'), 'error', 'You must enter a password.')
			return;
		}

		if( trim(cp.value) == "" ){
			setFieldStatus( [p,cp] , getObject('pass_icon'), getObject('pass_label'), 'error', 'You must confirm your password.')
			return;
		}

		if(p.value != cp.value) {
			setFieldStatus( [p,cp] , getObject('pass_icon'), getObject('pass_label'), 'error', 'Passwords do not match.')
			return;
		}

		setFieldStatus( [p,cp] , getObject('pass_icon'), getObject('pass_label'), 'ok')
	}

	function testTos (){
		var t = getObject('reg_tos');

		if( t.checked == false ){
			setFieldStatus( t , getObject('tos_icon'), getObject('tos_label'), 'error', 'You must agree to the terms of service.')
			return;
		} else {
			setFieldStatus( t , getObject('tos_icon'), getObject('tos_label'), 'ok')
		}
	}

	function popUp(URL) {
		day = new Date();
		id = day.getTime();
		eval("page" + id + " = window.open(URL, '" + id + "', 'toolbar=0,scrollbars=1,location=0,statusbar=0,menubar=0,resizable=0,width=325,height=300,left = 690,top = 375');");
	}

	function fieldValidatior(fieldName, elementsToColor , iconNode, labelNode){

		setFieldStatus(elementsToColor , iconNode, labelNode, 'loading', 'checking...');

		ajax.post('/api/processors/registration',
			{
				action : 'testField',
				field: fieldName,
				value : elementsToColor.value
			},
			function( connectionInstance ) {
				if(connectionInstance.serverResponse == 'ok'){
					setFieldStatus( elementsToColor , iconNode, labelNode, 'ok');
				} else {
					setFieldStatus( elementsToColor , iconNode, labelNode,  'error', connectionInstance.serverResponse);
				}
			},
			function( connectionInstance ) {
				//setFieldStatus(srcElement , 'error', 'Unknown error.');
			}
		);
	}

	var dhNull;
	var undefined;
	var ns = !!(document.layers && typeof document.classes != dhNull);
	var px = (ns) ? '' : 'px'; //px suffix only for browsers that need it

	//__________________________________________
	/** Global prototypes **/
	Function.prototype.bind = function(obj) {
		var method = this,
		temp = function() {
	   		return method.apply(obj, arguments);
		};
	 	return temp;
	}

	//__________________________________________
	/** A series of quick tests
	 * returns bool
	 */
	function inArray(hay, needle){ for(var a in hay) if(hay[a] == needle) return a; return false; }
	function isArray(obj){ return(typeof(obj.length) == "undefined")? false : true; }
	function isEmpty(str){ str = trim(str); return (str == null) || (str == 'null') || (str.length == 0) || (str == dhNull);}
	function isFunction(a) { return typeof a == 'function'; }
	function isObject(a) { return (a && typeof a == 'object') || isFunction(a); }
	function isString(a) { return typeof a == 'string'; }

	//-----------------------------------------------
	// Info functions
	//-----------------------------------------------
	/**	
	 * Core code from - quirksmode.com
	 * Edit for Firefox by pHaez
	 * 
	 * getPageSize()
	 * returns array with page width, height and window width, height
	 */	
	function getPageSize(){
		
		var xScroll, yScroll;

		var docBody = (document.compatMode && document.compatMode.toLowerCase() != "backcompat")?
			document.documentElement : (document.body || null);
		
		if (window.innerHeight && window.scrollMaxY) {	
			xScroll = window.innerWidth + window.scrollMaxX;
			yScroll = window.innerHeight + window.scrollMaxY;
		} else if (docBody.scrollHeight > docBody.offsetHeight){ // all but Explorer Mac
			xScroll = docBody.scrollWidth;
			yScroll = docBody.scrollHeight;
		} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
			xScroll = document.body.offsetWidth;
			yScroll = document.body.offsetHeight;
		}
		
		var windowWidth, windowHeight;

		if (self.innerHeight) {	// all except Explorer
			if(document.documentElement.clientWidth){
				windowWidth = document.documentElement.clientWidth; 
			} else {
				windowWidth = self.innerWidth;
			}
			windowHeight = self.innerHeight;
		} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
			windowWidth = document.documentElement.clientWidth;
			windowHeight = document.documentElement.clientHeight;
		} else if (document.body) { // other Explorers
			windowWidth = document.body.clientWidth;
			windowHeight = document.body.clientHeight;
		}	
		
		// for small pages with total height less then height of the viewport
		if(yScroll < windowHeight){
			pageHeight = windowHeight;
		} else { 
			pageHeight = yScroll;
		}

		// for small pages with total width less then width of the viewport
		if(xScroll < windowWidth){	
			pageWidth = xScroll;		
		} else {
			pageWidth = windowWidth;
		}

		var arrayPageSize = new Array(pageWidth, pageHeight, windowWidth, windowHeight) 
		return arrayPageSize;
	}
	
	/**	
	 * Core code from - quirksmode.com
	 * getPageScroll()
	 * returns array with x,y page scroll values.
	 */	
	function getPageScroll(){
	
		var xScroll, yScroll;
	
		if (self.pageYOffset) {
			yScroll = self.pageYOffset;
			xScroll = self.pageXOffset;
		} else if (document.documentElement && document.documentElement.scrollTop){	 // Explorer 6 Strict
			yScroll = document.documentElement.scrollTop;
			xScroll = document.documentElement.scrollLeft;
		} else if (document.body) {// all other Explorers
			yScroll = document.body.scrollTop;
			xScroll = document.body.scrollLeft;	
		}
	
		var arrayPageScroll = new Array(xScroll, yScroll) 
		return arrayPageScroll;
	}

	//__________________________________________
	/** Removes leading and trailing whitespace
	 *
	 * @param {string} value		string to clean up
	 *
	 * returns string
	 */
	function trim(value) {
		if( !isString(value) ) return value; //we can only trim strings
		var temp = value;
		var obj = /^(\s*)([\W\w]*)(\b\s*$)/;
		if (obj.test(temp)) { temp = temp.replace(obj, '$2'); }
		var obj = / +/g;
		temp = temp.replace(obj, " ");
		if (temp == " ") { temp = ""; }
		return temp;
	}

	/*--------------------
	 * Create Object
	 * 	preconditions:
			tag is not null and a valid html tag
			id is  'none'  or string
			classname is  'none'  or string
			parent is parent element objref or  'none'
			innerHTML = any html to be inserted
			type = if input type is a form object, supply it's type
	 * usage: var newobj = createObject("div", "mnu1", "menuItem", menuDiv , "Help");
	 * or: var newobj = createObject("input", "id", "class", parent, "", "hidden");
	 */
	function createObject(tag, id, classname, parent, innerHTML, type){
		try{
			var tmpObject = document.createElement(tag);
			if (tag == "input" && type != dhNull) tmpObject.type = type;
			if(classname != dhNull) tmpObject.className = classname;
			if(id != dhNull){
				tmpObject.id = id;
				tmpObject.name = id;
			}
			parent = ensureObject(parent);
			if(parent != dhNull) parent.appendChild(tmpObject);

			if (tag == "input" && type != dhNull){
				tmpObject.value = innerHTML
			}else if(innerHTML != dhNull) {
				tmpObject.innerHTML = innerHTML;
			}
		}
		catch(e) { /*alert("createObject Error");*/ }
		return tmpObject;
	}

	/**	returns a DOM element based on an ID
	 *
	 * getObject
	 * @param {element} objectID	DOM id of object to be found
	 *
	 * if an object refence is passed, it will be returned back immediately
	 *
	 * returns HTMLElement
	 */
	function getObject(objectID){
		if(isObject(objectID)) return objectID; //in the event the object was passed
		try	{
		  if (document.getElementById) { return document.getElementById(objectID); }
		  else if (document.all) { return document.all[objectID]; }
		  else if (document.layers) { return document.layers[objectID]; }
		} catch(e) { alert("Error: "+objectID+"\n"+e); }
	}

	/**	ensures that a paramter is an object, 
	 * if it's not and it is a string. a getObject will be attempted
	 *
	 * getObject
	 * @param {element} objectID	DOM id of object to be found
	 *
	 * if an object refence is passed, it will be returned back immediately
	 *
	 * returns HTMLElement
	 */
	function ensureObject(obj){
		return (
			isObject(obj) ? obj : getObject(obj)
		);
	}

	/**  displays all properties and functions for an object
	 *
	 * @param {object}	obj		string to clean up
	 * @param {bool} 	html	newlines to be displayed as br or \n
	 * @param {int}		indent	level of indentation for recursion
	 *
	 * returns string
	 */
	function dumpObj( obj , html, indent){
		if(indent == dhNull) indent = 0;
		var thisLevel = ""; var indentText = "";
		for(var x = 0 ; x < indent ; x++) { indentText += "  "; }
		for(var a in obj) {
			var tmpO = obj[a];
			thisLevel += indentText + a + ": " + tmpO;
			thisLevel += (html) ? "<br />" : "\n";
		}
		return thisLevel;
	}


	/**	removes an element from the DOM - warning
	 * deleteObject
	 * @param {element} objectID	DOM id of object to be deleted from the dom
	 *
	 * returns true on success / false on error
	 */
	function destroyObject(HTMLElement){
		try{ HTMLElement.parentNode.removeChild(HTMLElement);
		} catch(e) { return false; }
		return true;
	}


	/** gets an array of all flash objects in the dom
	 * getFlashObjects
	 * returns array
	 */
	function getFlashObjects(){
		var arrObj = document.getElementsByTagName("object");
		var arrEmb = document.getElementsByTagName("embed");

		if( !isArray(arrObj) || !isArray(arrEmb) ) return false;

		var allObj = [];
		
		if( arrObj.length > 0 && arrEmb.length > 0 ){
			for( var a = 0 ; a < arrObj.length; a++ ) allObj[ allObj.length ] = arrObj[a];
			for( var b = 0 ; b < arrEmb.length; b++ ) allObj[ allObj.length ] = arrEmb[b];
		} else if( arrObj.length > 0 ){
			allObj = arrObj;
		} else if( arrEmb.length > 0 ){
			allObj = arrEmb;
		}

		return ( allObj.length > 0 ) ? allObj : false ;
	}


	/** set all visible flash objects to invisible
	 *
	 * hideFlashObjects
	 *
	 * returns nothing
	 */	
	function hideFlashObjects(){
		var flashObjects = getFlashObjects();
		if( flashObjects ) for (i = 0; i < flashObjects.length; i++) disappear( flashObjects[i] ); 
	}

	/** set visibility to al hidden flash objects
	 *
	 * showFlashObjects
	 *
	 * returns nothing
	 */	
	function showFlashObjects(){
		var flashObjects = getFlashObjects();
		if( flashObjects ) for (i = 0; i < flashObjects.length; i++) reappear( flashObjects[i] ); 
	}


	/** sets an elements parent
	 *
	 * setParent
	 * @param {object} obj						element to move
	 * @param {string | object } newParent		ID or object reference of new parent element
	 *
	 * returns true on success / false on error
	 */
	function setParent(obj, newParentID){
		try{ var elementRef = obj.parentNode.removeChild(obj);
			 var t = getObject(newParentID);
			 var o = t.appendChild(elementRef);
		} catch (e){ return false; }return true;
	}
	
	//-----------------------
	// Event Handling
	//-----------------------
	function invoke( elem, ev, param){
		try { return elem['on' + ev](param); }
		catch (ex){ }
		return true;
	}
		
	/**
	 *
	 * setStyle
	 * @param {object} obj						element to style
	 * @param {string | object } name	ID or object reference of new adjacent element
	 * @param {string | object } value
	 *
	 * returns true on success / false on error
	 */	
	function setStyle(element, name, value) {
		eval('element.style.' + name + ' = value;');
	}
	
	//-----------------------------------------------
	// Graphical Functions
	//-----------------------------------------------
	/** Visually and computationally hides an element
	 *
	 * hideObject
	 * @param {object} obj		element to hide
	 * returns true on success / false on error
	 */
	function hideObject(obj) {
		try {
			if(!isObject(obj) ) return false;
			obj.style.visibility = 'hidden';
			obj.style.display = 'none';
		} catch (e) { return false; }
		return true;
	}

	/** Visually and computationally shows an element
	 *
	 * showObject
	 * @param {object} obj		element to show
	 * returns true on success / false on error
	 */
	function showObject(obj) {
		try{
			if(!isObject(obj) ) return false;
			obj.style.visibility = 'visible';
			obj.style.display = 'block';
		} catch (e) { return false; }
		return true;
	}

	/** computationally hides an element
	 *
	 * hideBlock
	 * @param {object} obj		element to hide
	 * returns true on success / false on error
	 */
	function hideBlock( element ){
		return setStyle( element, 'display', 'none');
	}

	/** computationally shows an element
	 *
	 * showBlock
	 * @param {object} obj		element to show
	 * returns true on success / false on error
	 */
	function showBlock( element ){
		return setStyle(element, 'display', 'block');
	}

	/** visually hides an element
	 *
	 * invisible
	 * @param {object} obj		element to show
	 * returns true on success / false on error
	 */
	function disappear( element ){
		return setStyle(element, 'visibility', 'hidden');
	}

	/** visually shows an element
	 *
	 * visible
	 * @param {object} obj		element to show
	 * returns true on success / false on error
	 */
	function reappear( element ) {
		return setStyle(element, 'visibility', 'visible');
	}

	function setOpacity(element , opacity){
		try{
			if(typeof element.style.MozOpacity != undefined){	element.style.MozOpacity = opacity / 100; }
			if(typeof element.style.filter != undefined){	element.style.filter = "Alpha(opacity="+parseInt(opacity)+")";	}
			element.style.opacity = opacity / 100;
		} catch (e) { return false; } return true;
	}


	//------------------------
	// Sizing Functions
	//------------------------
	function W (element, value) {
		if( value == dhNull ) return getW( element );
		value = parseInt(value);
		if( element.minw ) value = Math.max( value, ( element.minw || 0) );
		try{ element.style.width = value + px; }
		catch (e){}
		return parseInt(value);
	}
	function H (element, value) {
		if( value == dhNull ) return getH( element );
		value = parseInt(value);
		if( element.minh ) value = Math.max( value, ( element.minh || 0) );
		try{ element.style.height = value + px; }
		catch (e){}
		return parseInt(value);
	}
	
	/**	gets the visible width of an element
	 * getvW
	 * @param {element} element		dom element to calculate for
	 * returns number
	 */
	function getW( element ) {
		try{
		return (ns) ?
			(element) ?	element.clip.width : 0
			: (element) ? (element.offsetWidth || element.style.pixelWidth || element.style.width || 0) : 0;
		} catch (e){ } return false;
	}


	/**	gets the visible height of an element
	 * getH
	 * @param {element} element		dom element to calculate for.
	 * returns number
	 */
	function getH( element ) {
		try{
		return (ns) ?
			(element) ? element.clip.height : 0
			: (element) ? (element.offsetHeight || element.style.pixelHeight || element.style.height || 0) : 0;
		} catch (e) {} return false;
	}

	/**	gets the client(inner) width of an element ( scrollbars not included )
	 * getvW
	 * @param {element} element		dom element to calculate for
	 * returns number
	 */
	function getInnerW( element ) {
		try{
		return (element.clientWidth || 0);
		} catch (e) {} return false;
	}


	/**	gets the client(inner) height of an element ( scrollbars not included )
	 * getH
	 * @param {element} element		dom element to calculate for.
	 * returns number
	 */
	function getInnerH( element ) {
		try{
		return (element.clientHeight || 0);
		} catch (e) {} return false;
	}
		
	//------------------------
	// Positioning Functions
	//------------------------
	function X(element, value){
		if( value == dhNull ) return getX( element );
		value = parseInt(value);
		if( element.minx ) value = Math.max( value, ( element.minx || 0) );
		try{ element.style.left = value + px; }
		catch (e){}
		return parseInt(value);
	}
	
	function Y(element, value){
		try{
			if(value != dhNull && value != "NaN") {
				element.style.top = parseInt(value) + px;
			} else if( value == dhNull ){
				return getY(element);
			}
		} catch (e){
			return 0;
		}
		return parseInt(value);
	}

	function Z(element, value){
		try{
			if(value != dhNull && value != "NaN") {
				element.style.zIndex = parseInt(value);
			} else if( value == dhNull ){
				return getZ(element);
			}
		} catch (e){
			return false;
		}
		return parseInt(value);
	}
	
	/**	gets the X position of any element to it's offsetParent
	 * getX
	 * @param {element} element		dom element to calculate for.
	 * returns number
	 */
	function getX( element ){
		var curleft = 0;
		if (element.offsetParent) { curleft += element.offsetLeft; }
		else if (element.x) curleft += element.x;
		return curleft;
	}

	/**	gets the Y position of any element to it's offsetParent
	 * getY
	 * @param {element} element		dom element to calculate for.
	 * returns number
	 */
	function getY(element){
		var curtop = 0;
		if (element.offsetParent) { curtop += element.offsetTop; }
		else if (element.y)	curtop += element.y;
		return curtop;
	}

	/**	gets the Y position of any element to it's offsetParent
	 * getY
	 * @param {element} element		dom element to calculate for.
	 * returns number
	 */
	function getZ(element){
		return (element.style.zIndex || 0);
	}

	/**	gets the absolute X position of any element to the origin
	 * getAbsX
	 * @param {element} element		dom element to calculate for.
	 * returns number
	 */
	function getAbsX( element ){
		var curleft = 0;
		var tmpobj = element;
		if (tmpobj.offsetParent) {
			while (tmpobj.offsetParent) {
					curleft += tmpobj.offsetLeft;
					if( tmpobj.tagName.toLowerCase() == 'div' && element != tmpobj ){ curleft -= tmpobj.scrollLeft; }
					tmpobj = tmpobj.offsetParent;
				}
		}
		else if (tmpobj.x) { curleft += tmpobj.x; }
		return curleft;
	}
	
	/**	gets the absolute Y position of any element to the origin
	 * getAbsX
	 * @param {element} element		dom element to calculate for.
	 * returns number
	 */
	function getAbsY(element){
		var curtop = 0;
		var tmpobj = element;
		if (tmpobj.offsetParent) {
			while (tmpobj.offsetParent) {
				curtop += tmpobj.offsetTop
				if( tmpobj.tagName.toLowerCase() == 'div' && element != tmpobj ){ curtop -= tmpobj.scrollTop; }
				tmpobj = tmpobj.offsetParent;
			}
		}
		else if (tmpobj.y) { curtop += tmpobj.y; }
		return curtop;
	}
	
	
	/**	gets the absolute X position of any element to the origin
	 * getAbsX
	 * @param {element} element		dom element to calculate for.
	 * returns number
	 */
	function getRelativeAbsX( elementA, elementB ){
		var curleft = 0;
		var tmpobj = elementA;
		if (tmpobj.offsetParent) {
			while (tmpobj.offsetParent && tmpobj != elementB) {
					curleft += tmpobj.offsetLeft;
					if( tmpobj.tagName.toLowerCase() == 'div' && elementA != tmpobj ){ curleft -= tmpobj.scrollLeft; }
					tmpobj = tmpobj.offsetParent;
				}
		}
		else if (tmpobj.x) { curleft += tmpobj.x; }
		return curleft;
	}

	/**	gets the absolute Y position of any element to the origin
	 * getAbsX
	 * @param {element} element		dom element to calculate for.
	 * returns number
	 */
	function getRelativeAbsY(elementA, elementB){
		var curtop = 0;
		var tmpobj = elementA;
		if (tmpobj.offsetParent) {
			while (tmpobj.offsetParent && tmpobj != elementB) {
				curtop += tmpobj.offsetTop
				if( tmpobj.tagName.toLowerCase() == 'div' && elementA != tmpobj ){ curtop -= tmpobj.scrollTop; }
				tmpobj = tmpobj.offsetParent;
			}
		}
		else if (tmpobj.y) { curtop += tmpobj.y; }
		return curtop;
	}
var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */

/*
 * These are the functions you'll usually want to call
 * They take string arguments and return either hex or base-64 encoded strings
 */
function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}


/*
 * Bitwise rotate a 32-bit number to the left.
 */
function rol(num, cnt)
{
  return (num << cnt) | (num >>> (32 - cnt));
}

/*
 * Convert an array of big-endian words to a hex string.
 */
function binb2hex(binarray)
{
  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i++)
  {
    str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
           hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8  )) & 0xF);
  }
  return str;
}

/*
 * Calculate the SHA-1 of an array of big-endian words, and a bit length
 */
function core_sha1(x, len)
{
  /* append padding */
  x[len >> 5] |= 0x80 << (24 - len % 32);
  x[((len + 64 >> 9) << 4) + 15] = len;

  var w = Array(80);
  var a =  1732584193;
  var b = -271733879;
  var c = -1732584194;
  var d =  271733878;
  var e = -1009589776;

  for(var i = 0; i < x.length; i += 16)
  {
    var olda = a;
    var oldb = b;
    var oldc = c;
    var oldd = d;
    var olde = e;

    for(var j = 0; j < 80; j++)
    {
      if(j < 16) w[j] = x[i + j];
      else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
      var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
                       safe_add(safe_add(e, w[j]), sha1_kt(j)));
      e = d;
      d = c;
      c = rol(b, 30);
      b = a;
      a = t;
    }

    a = safe_add(a, olda);
    b = safe_add(b, oldb);
    c = safe_add(c, oldc);
    d = safe_add(d, oldd);
    e = safe_add(e, olde);
  }
  return Array(a, b, c, d, e);

}

/*
 * Perform the appropriate triplet combination function for the current
 * iteration
 */
function sha1_ft(t, b, c, d)
{
  if(t < 20) return (b & c) | ((~b) & d);
  if(t < 40) return b ^ c ^ d;
  if(t < 60) return (b & c) | (b & d) | (c & d);
  return b ^ c ^ d;
}


/*
 * Determine the appropriate additive constant for the current iteration
 */
function sha1_kt(t)
{
  return (t < 20) ?  1518500249 : (t < 40) ?  1859775393 :
         (t < 60) ? -1894007588 : -899497514;
}


/*
 * Convert an 8-bit or 16-bit string to an array of big-endian words
 * In 8-bit function, characters >255 have their hi-byte silently ignored.
 */
function str2binb(str)
{
  var bin = Array();
  var mask = (1 << chrsz) - 1;
  for(var i = 0; i < str.length * chrsz; i += chrsz)
    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
  return bin;
}

/*
 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
 * to work around bugs in some JS interpreters.
 */
function safe_add(x, y)
{
  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
  return (msw << 16) | (lsw & 0xFFFF);
}


function cClient (){
	var thisInstance = this;
	
	//Client Data
	this.data = {};
	
	//Client Windows
	this.windows = {};
	
	//Javascript libraries
	// cC.require('nameoflib');
	// cc.sB.nameoflib;
	this.sB = {};

	//stateful client-side info
	this.currentWindow = '';		//currently focused windowname
	
	//client wide storage
	this.highZ =	 1000;
	this.documentW = 0;
	this.documentH = 0;
	this.viewportW = 0;
	this.viewportH = 0;
	this.scrollLeft = 0;
	this.scrollTop = 0;
	
	//client wide events
	window.onresize = function (e) { thisInstance.__resize(e); };
	window.onscroll = function (e) { thisInstance.__scroll(e); };	
	document.onmousemove = function (e) { thisInstance.__mouseMove(e); };
	document.onmouseup = function (e) { thisInstance.__mouseUp(e); };
	
	this.__resize();
	this.__scroll();
}

cClient.prototype = {

	__resize : function  (){
	 	var pageSizes = getPageSize();
		this.documentW = pageSizes[0];
		this.documentH = pageSizes[1];
		this.viewportW = pageSizes[2];
		this.viewportH = pageSizes[3];
	},
	
	__scroll : function  (){
		var scrollValues = getPageScroll();
		this.scrollLeft = scrollValues[0]
		this.scrollTop = scrollValues[1];
	},

	/*
	 * Mouse Events
	 */
	__mouseMove : function (e){
		//build event object
		if(!e) e = window.event;
		e = this.fixEventObject(e);

		if( this.dragObject ) {
			this.__drag(e);
		}
		
		if( this.resizeObject && this.resizeFunc ) {
			this.resizeFunc( e );
			this.stopEvent(e.event);
		}
	},
	
	__mouseUp : function ( e ){
		
		//build event object
		if(!e) e = window.event;
		e = this.fixEventObject(e);
		
		//stop drag if we're dragging anything
		if( this.dragObject )	this.stopDrag(e);
		
		//stop resizing anything if we're resizing.
		if( this.resizeObject ) this.endResize( e );
		
	},
	
	//drag innerworkings
	//incomming call to move our currently dragging object
	__drag : function ( e ){

		var newX = e.mouseX - this.dragObject.oX;
		var newY = e.mouseY - this.dragObject.oY;
		
		//captureToParent
		if( this.dragObject.captureToParent ) {
			newX = Math.min( Math.max( newX , 0 ), getInnerW( this.dragObject.offsetParent ) - this.dragObject.dsw );
			newY = Math.min( Math.max( newY , 0 ), getH( this.dragObject.offsetParent ) - this.dragObject.dsh );
		}

		X( this.dragObject, newX );
		Y( this.dragObject, newY );
		
		this.stopEvent(e.event);							//stop normal event operation, c'mon! we're draggin

	},
	
	//-----------------------
	// Event Objects
	//-----------------------
	fixEventObject : function (e) {
		if(!e) e = window.event;
		
		newEvent = {};
		
		try{
			newEvent.targetElement = e.srcElement || e.target;
			newEvent.targetID = newEvent.targetElement.id || newEvent.targetElement.name;
			
			//update general mouse movement stats
			//this will only use scrollX and y ifthey are filled
			newEvent.mouseX = (e.pageX || e.clientX + this.scrollLeft);
			newEvent.mouseY = (e.pageY || e.clientY + this.scrollTop);
	
			//mouse placement overan element
			newEvent.offsetX  = (e.offsetX || e.layerX);
			newEvent.offsetY = (e.offsetY || e.layerY);
			
			newEvent.event = e;
		}
		catch ( ex ){ alert(dumpObj(ex)); }
		return newEvent; //don;t know if this is necessary
	},

	stopEvent : function  (e){
		if(!e) e = window.event;
		try{ e.cancelBubble = true;	}catch(ex){ }
		try{ e.stopPropagation();	}catch(ex){ }
		try{ e.preventDefault();	}catch(ex){ }
		try{ e.returnValue = false;	}catch(ex){ }
    },
	
	/* ***********************************************************************************
	 * Drag control (public)
	 *********************************************************************************** */
	dragObject : null,		//currently dragging object
	setDraggable : function ( HTMLElement, draggable ){
		HTMLElement.draggable = 		draggable;		
		if( !draggable ) {
			HTMLElement.isDragHandle = null;
		}
	},
	addDragHandle : function ( HandleHTMLElement, DestHTMLElement ){
		HandleHTMLElement.isDragHandle = DestHTMLElement;
		//this.setDraggable( DestHTMLElement , true );

		//HandleHTMLElement.onmousedown = function(e){ dD.startDrag( e, HandleHTMLElement ); };
	},
	startDrag : function( e, HTMLElement, captureToParent ) {
		//build event object
		if(!e) e = window.event;
		e = this.fixEventObject(e);
		
		//are we a drag handle for something else or are we a drag object
		if( HTMLElement.isDragHandle ){
			//isDragHandle will be missing or an object which should be dragged

			//switch the drag object
			HTMLElement = HTMLElement.isDragHandle;
			
		//we're supposed to be draggable?
		} else {

			//make sure the event was given directly to this element
			if( e.targetElement != HTMLElement ) return true;
			

		}

		//now set the values
		HTMLElement.oX = e.offsetX;
		HTMLElement.oY = e.offsetY;
		HTMLElement.dsx = getAbsX(HTMLElement);
		HTMLElement.dsy = getAbsY(HTMLElement);
		HTMLElement.dsw = getW(HTMLElement);
		HTMLElement.dsh = getH(HTMLElement);
		
		HTMLElement.captureToParent = 	captureToParent;
		
		this.dragObject = HTMLElement;
				
		if ( this.dragObject.__startDrag ) this.dragObject.__startDrag();
		
		this.stopEvent(e.event);
	},
	startDragFromHandle : function ( e, dragHandle ){
		
	},
	stopDrag : function( ) {

		if( this.dragObject ){
			
			//can't stop now, already let go of the mouse.
			//so ignore return values
			if ( this.dragObject.__stopDrag ) this.dragObject.__stopDrag();

			//clear drag info
			this.dragObject.oX = 	null;
			this.dragObject.oY = 	null;
			this.dragObject.dsx = 	null;
			this.dragObject.dsy = 	null;
			this.dragObject.dsw = 	null;
			this.dragObject.dsh = 	null;
			
			this.dragObject = null;
 		}
	},
	

	/* ***********************************************************************************
	 * Resize control (public)
	 *********************************************************************************** */
	//relative parent will remove the ABS X and Y or the relative parent
	//from the result before setting
	startResize : function ( HTMLElement, resizeEdge ){

		var windowspace = getObject('windowspace');
		
		//store the beginnings
		HTMLElement.rsx = getRelativeAbsX( HTMLElement, windowspace );	//resize start x
		HTMLElement.rsy = getRelativeAbsY( HTMLElement, windowspace );	//resize start y
		HTMLElement.rsw = getW(HTMLElement);
		HTMLElement.rsh = getH(HTMLElement);

		//create a nicely sizeable layer
		var resizeAnimation = createObject('div', 'resizeAnimation', 'a bgLB a50 highZ', windowspace );

		if( HTMLElement.minw ) resizeAnimation.minw = HTMLElement.minw;
		if( HTMLElement.minh ) resizeAnimation.minh = HTMLElement.minh;

		//prepare our animation
		X( resizeAnimation , HTMLElement.rsx );							//X
		Y( resizeAnimation , HTMLElement.rsy );							//Y
		W( resizeAnimation , HTMLElement.rsw );							//W
		H( resizeAnimation , HTMLElement.rsh );							//H
		
		//bring to front
		this.resizeEdge = 		resizeEdge;
		this.resizeFunc = 		this.getResizeFunc( resizeEdge );		//get the appropiate perPixelFunction
		this.resizeAnimation = 	getObject('resizeAnimation');
		this.resizeObject = 	HTMLElement;
	},
	
	//return a proper per pexel resizer for a specific edge	
	getResizeFunc : function ( resizeEdge ) {
		switch( resizeEdge ) {
			case resizeEdges.topLeft :
				return resizeFunctions.topLeft;
				break;
			case resizeEdges.top :
				return resizeFunctions.top;
				break;
			case resizeEdges.topRight :
				return resizeFunctions.topRight;
				break;
			case resizeEdges.right :
				return resizeFunctions.right;
				break;
			case resizeEdges.bottomRight :
				return resizeFunctions.bottomRight;
				break;
			case resizeEdges.bottom :
				return resizeFunctions.bottom;
				break;
			case resizeEdges.bottomLeft :
				return resizeFunctions.bottomLeft;
				break;
			case resizeEdges.left:
				return resizeFunctions.left;
				break;
		}
		return false;	//thats an error!
	},
	
	endResize : function ( e ){
		var windowspace = 		getObject('windowspace');		//default positioning container
		var resizeAnimation = 	getObject('resizeAnimation');
/*
		X( this.resizeObject , getRelativeAbsX( resizeAnimation, windowspace ) - getAbsX( this.resizeObject.offsetParent ) );		//X
		Y( this.resizeObject , getRelativeAbsY( resizeAnimation, windowspace ) - getAbsY( this.resizeObject.offsetParent ) );		//Y
		W( this.resizeObject , getW( resizeAnimation ) )	;								//W
		H( this.resizeObject , getH( resizeAnimation ) );									//H
*/	
		resizeFunctions.applyResize( resizeAnimation, this.resizeObject, windowspace, this.resizeEdge );
		
		this.resizeEdge = null;
		this.resizeFunc = null;
		
		//if the element has a resize handler call it.
		if( this.resizeObject.__resize ) this.resizeObject.__resize();
		
		destroyObject( resizeAnimation );
		this.resizeObject = null;
	},


	/* ***********************************************************************************
	 * Matte control (public)
	 *********************************************************************************** */
	showMatte : function ( clickToExit, onClose ){
		hideFlashObjects();
		var matte = getObject('matte');
		
		W( matte, this.viewportW );
		H( matte, this.documentH );
		showObject(matte);
		
		if( clickToExit ) onClose = matte.onmousedown = closeMatte;
		if( onClose ) matte.onClose = onClose;
	
	},

	closeMatte : function (){
		var matte = getObject('matte');
		
		hideObject(matte);
		
		if( matte.onClose ) matte.onClose();
		matte.onClose = null;
		showFlashObjects();
	},

	startDestroyAnimation : function ( srcElement ){

		var windowspace = getObject('windowspace');

		//create a nicely sizeable layer
		var destroyAnimation = createObject('div', 'destroyAnimation', 'a bgLB', windowspace );
		
		//prepare our animation
		X( destroyAnimation , getRelativeAbsX( srcElement, windowspace ) );		//X
		Y( destroyAnimation , getRelativeAbsY( srcElement, windowspace ) );		//Y
		Z( destroyAnimation , 999999 );
		W( destroyAnimation , getW(srcElement) );								//W
		H( destroyAnimation , getH(srcElement) );								//H
		
		setTimeout( function(){	setOpacity( destroyAnimation, 85 );	},0);
		setTimeout( function(){ setOpacity( destroyAnimation, 70 ); },33);
		setTimeout( function(){ setOpacity( destroyAnimation, 55 ); },66);
		setTimeout( function(){ setOpacity( destroyAnimation, 40 ); },100);
		setTimeout( function(){ setOpacity( destroyAnimation, 25 ); },133);
		setTimeout( function(){ destroyObject( destroyAnimation ); }, 166);

	},

	/* ***********************************************************************************
	 * Code control (public)
	 *********************************************************************************** */
	/* Download a code library from the server
	 * ex. 	cC.require( 'window.frontECirkit', 	callbackFunc );
	 * 		cC.require( 'new_splash.*',			callbackFunc );
	 */
	require : function ( nameSpace, callback ){

		//can't download nothing
		if( isEmpty(nameSpace) ) return false;
		
		//we need todownload it
		//build an api command
		var url = 		'/api/servlets/script?';
		var classname = nameSpace.split( '.' );
		
		//either no classname or just 1 file.
		if( classname.length == 1 ) {
			if( isEmpty( classname[0] ) ) {
				
				//namespace is empty
				return false;
				
			} else {
				
				if( this.sB[classname[0]] ) return true; //already got it
				
				url += 'name=' + classname[0];
			}
		
		//either a while folder or a file in a folder
		} else if( classname.length == 2 ) {
			if( classname[1] == '*' ) {
				if( this.sB[classname[0]] ) return true; //already got it
				url += 'method=folder&name=' + classname[0];
			} else {
				if( this.sB[classname[1]] ){
					return true; //already got it
				}
				url += 'type='+classname[0]+'&name=' + classname[1];
			}
			
		//shit's not valid
		} else {
			return false;
		}

		//download
		ajax.post(
			url,
			{},
			function require_onSuccess ( connectionInstance ){
				try{
					//insert the code
					eval(connectionInstance.serverResponse);
					
					//continue along our way
					if( callback ) callback();
					
				} catch ( ex ){
					
				}
			},
			function require_onError ( connectionInstance ){
				console.log(  'aww crap',  connectionInstance );
				
				//callback
				if( callback ) callback();
			}
		);
		
		return false; //downloading
		
	},
	
	/* ***********************************************************************************
	 * Window control (public)
	 *********************************************************************************** */
	//download the code necessary to initialize a window and then initialize the window.
	//
	// usage
	//	if( !requireWindow(windowname, LoopCallback) ) return false;
	//	where loopcallback will also call the containing function with the same parameters
	//
	//	contiune from here
	requireWindow : function ( windowName, callback ){
				
		//make sure we got the scripts, and reutrn false so parent functions know to wait.
		if( !this.require( 
				//download a class named after our window
				'window.' + windowName, 
				//get back to initWindow after we download the script with our orignal callback
				function requireWindow_delegate (){ cC.requireWindow( windowName, callback ); }	
			)
		)  return false;	//let other functions wait.		
				
		//init the window by calling it's init function.
		var windowClass = this.sB[windowName];

		try{
			windowClass.init();
		} catch ( ex ){ }
		
		//success by default
		return true;
	},
	
	//auto init window / client side window focus control
	focusOnWindow : function ( windowID, callback ){
		
		//download and install the window if necessary
		if( !this.requireWindow( 
				windowID,
				function ( ){ cC.focusOnWindow(windowID, callback); }
			)
		) return false;	//let other functions wait.		
		
		//highlight the selected window
		if( this.currentWindow != windowID ){
			this.currentWindow = windowID;
			
			if( this.windows[ windowID ].visible == true ){
				this.windows[ windowID ].__focus();	
			} else {
				this.windows[ windowID ].show();	
			}
		} 
		
		if( callback ) callback();
	},

	/* ***********************************************************************************
	 * DHTML positioning and such that also requires tracking
	 *********************************************************************************** */
	cascadeCount : 0,
	cascadeStartX : 100,
	cascadeStartY : 100,
	cascadePosition : function (){
		this.cascadeCount++;
		this.cascadeCount = this.cascadeCount %15;
		
		return [ this.cascadeStartX + (this.cascadeCount * 30), this.cascadeStartY + (this.cascadeCount * 30) ];
	},

	getHighZ : function (){
		this.highZ++;
		return this.highZ;
	},
	/* ***********************************************************************************
	 * Window control (private)
	 *********************************************************************************** */
	//Create a window and begin client side tracking
	//this should never really need to be called except from the newly downloaded windowClass
	//eg/ cC.sB.myContats.init() would call this functions to register this window into the client.
	createWindow : function ( windowID, parentElement, windowSettings ){

		//create the the class instance. by omitting windowSettings to the constructor, the
		// window will not be built automatically. the manual build process is as follows.
		// this should look very similar to the automatic way inside the constructor, but allows more control here.
		var newWnd = new cWin( windowID, parentElement );
		
		//read the remaining settings
		newWnd.readSettings( windowSettings );
		
		//load window's user settings. here.
		var userSettings = false;	//for testing
				
		if( !userSettings ) {
			var newPos = this.cascadePosition();
			newWnd.settings.X = newPos[0];
			newWnd.settings.Y = newPos[1];
		}
		
		//build process
		newWnd.buildWindow();
		
		//window events
		newWnd.enableEvents();
		
		
		//window layout
		//shouldn't have to do this
		//newWnd.reflowWindowElements();
		
		newWnd.__focus();
		
		//store it.
		this.windows[ windowID ] = newWnd;
		
		//return it
		return newWnd;
	}

};

//an editable list of resizeedges
var resizeEdges = {

	topLeft : 1,
	top : 2,
	topRight : 3,
	right : 4,
	bottomRight : 5,
	bottom : 6,
	bottomLeft : 7,
	left: 8
	
};

/*
 * These functinos will resize a window representation for each pixel moved.
 */
var resizeFunctions = {

	topLeft : function( e ){
		//figure it out
		var diffX = e.mouseX - cC.resizeObject.rsx;
		var diffY = e.mouseY - cC.resizeObject.rsy;

		var newX = cC.resizeObject.rsx + diffX;
		var newY = cC.resizeObject.rsy + diffY;
		var newW = cC.resizeObject.rsw - diffX;
		var newH = cC.resizeObject.rsh - diffY;

		//show the results
		W(cC.resizeAnimation, newW);
		H(cC.resizeAnimation, newH);

		if( cC.resizeAnimation.minh ) 
			if( newH < cC.resizeAnimation.minh ) newY = cC.resizeObject.rsy + (cC.resizeObject.rsh - cC.resizeObject.minh);
			
		if( cC.resizeAnimation.minw ) 
			if( newW < cC.resizeAnimation.minw ) newX = cC.resizeObject.rsx + (cC.resizeObject.rsw - cC.resizeObject.minw);


		X(cC.resizeAnimation, newX);
		Y(cC.resizeAnimation, newY);


		},
	top : function( e ){
		//figure it out
		var diffY = e.mouseY - cC.resizeObject.rsy;
		var newY = cC.resizeObject.rsy + diffY;
		var newH = cC.resizeObject.rsh - diffY;
		
		//show the results
		H(cC.resizeAnimation, newH);
		
		//minimum size fixes for wandering resize animations
		//this will adjust the y value so it doesn't drift
		if( cC.resizeAnimation.minh ) 
			if( newH < cC.resizeAnimation.minh ) newY = cC.resizeObject.rsy + (cC.resizeObject.rsh - cC.resizeObject.minh);
			
		Y(cC.resizeAnimation, newY);
		
		},
	topRight : function( e ){
		var diffY = e.mouseY - cC.resizeObject.rsy;
		
		var newY = cC.resizeObject.rsy + diffY;
		var newH = cC.resizeObject.rsh - diffY;
		var newW = e.mouseX - cC.resizeObject.rsx;
		
		//show the results
		W(cC.resizeAnimation, newW);
		H(cC.resizeAnimation, newH);

		if( cC.resizeAnimation.minh ) 
			if( newH < cC.resizeAnimation.minh ) newY = cC.resizeObject.rsy + (cC.resizeObject.rsh - cC.resizeObject.minh);
				
		Y(cC.resizeAnimation, newY);

	},
	right : function( e ){
		//figure it out
		var newW = e.mouseX - cC.resizeObject.rsx;

		//show the results
		W(cC.resizeAnimation, newW);
		},
	bottomRight : function( e ){
		var newW = e.mouseX - cC.resizeObject.rsx;
		var newH = e.mouseY - cC.resizeObject.rsy;

		//show the results
		W(cC.resizeAnimation, newW);
		H(cC.resizeAnimation, newH);
		},
	bottom : function( e ){
		//figure it out
		var newH = e.mouseY - cC.resizeObject.rsy;

		//show the results
		H(cC.resizeAnimation, newH);
	},
	bottomLeft : function( e ){
		//figure it out
		var diffX = e.mouseX - cC.resizeObject.rsx;
		var newX = cC.resizeObject.rsx + diffX;
		var newW = cC.resizeObject.rsw - diffX;
		var newH = e.mouseY - cC.resizeObject.rsy;
		
		//show the results
		W(cC.resizeAnimation, newW);
		H(cC.resizeAnimation, newH);

		if( cC.resizeAnimation.minw ) 
			if( newW < cC.resizeAnimation.minw ) newX = cC.resizeObject.rsx + (cC.resizeObject.rsw - cC.resizeObject.minw);

		X(cC.resizeAnimation, newX);

		},
	left: function( e ){
		var diffX = e.mouseX - cC.resizeObject.rsx;
		var newX = cC.resizeObject.rsx + diffX;
		var newW = cC.resizeObject.rsw - diffX;

		W(cC.resizeAnimation, newW);
		
		if( cC.resizeAnimation.minw ) 
			if( newW < cC.resizeAnimation.minw ) newX = cC.resizeObject.rsx + (cC.resizeObject.rsw - cC.resizeObject.minw);

		X(cC.resizeAnimation, newX);
		
	},
	
	/* one last function to apply the results */
	applyResize : function ( srcElement, destElement, relativeTo, resizeEdge ) {

		switch( resizeEdge ) {

			case resizeEdges.topLeft :
			
				//show the results
				W(destElement, getW( srcElement ));
				H(destElement, getH( srcElement ));		
				X(destElement, getAbsX( srcElement ));
				Y(destElement, getAbsY( srcElement ));
			
				break;
			case resizeEdges.top :
			
				H(destElement, getH( srcElement ));		
				Y(destElement, getAbsY( srcElement ));
			
				break;
			case resizeEdges.topRight :

				Y(destElement, getAbsY( srcElement ));			
				W(destElement, getW( srcElement ));
				H(destElement, getH( srcElement ));	

				break;
			case resizeEdges.right :
				
				W(destElement, getW( srcElement ));
			
				break;
			case resizeEdges.bottomRight :
	
				W(destElement, getW( srcElement ));
				H(destElement, getH( srcElement ));
			
				break;
			case resizeEdges.bottom :
			
				H(destElement, getH( srcElement ));
			
				break;
			case resizeEdges.bottomLeft :
			
				W(destElement, getW( srcElement ));
				H(destElement, getH( srcElement ));		
				X(destElement, getAbsX( srcElement ));
			
				break;
			case resizeEdges.left:
			
				X(destElement, getAbsX( srcElement ));
				W(destElement, getW( srcElement ));
			
				break;
		}

	}
};