
/**
 * @author jw5987
 * 
 * CLM Layout - controls page creation and layout properties. 
 * Also includes shared general functionality. 
 * NOTES: fix init process... include css and script imports on xsl file (not 
 * 	as part of method calls)
 */

/* ########## Global Variables ########## */ 
var objRequest = createRequestObject();
var clm_servlet = "CLMServlet";
Ext.BLANK_IMAGE_URL = "themes/common/images/clear.gif";
frmwrk_rm.set("servletURL", clm_servlet);
frmwrk_rm.set("grid_maxRecordsPerPage", 25);
var isLogRequestEnabled = true;

if(isLogRequestEnabled){
	if (Ext.KeyMap) {
		var map = new Ext.KeyMap(document.body, {
			key: Ext.EventObject.PAGEUP,
			fn: function(){showLastRequest();},
			ctrl: true,
			shift: true,
			alt: true
		});
	}
}
/*
   Variables used for finding the script
   tags in the Ajax response.
*/	
var useXBrowserRE = false;
var xBrowserRE = /<[ ]*script\b[^>]*>([^>]*)<\/script>/ig;
var ScriptFragment = '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)';
var ieRE = new RegExp(ScriptFragment, 'img');	

//Im guessing that these will somehow be put into the resource manager after it is loaded.
//I haven't done that yet because Im not sure if there is an onCLMloaded() function or something similar.
//Look to formatDate.js for the definitions of the format strings.
var localizedDateFormat = "MM/dd/yyyy hh:mm a";      //this is a hardcoded date format
													 //This will eventually be coming from OrgPrefrences.
var CLMSystemDefaultDateFormat = "dd-NNN-yyyy HH:mm";//this is the format coming back from 
													 //a date field in oracle.
var CLMSystemDefaultDateFormat2 = "yyyy-MM-dd HH:mm:ss.0";//this is the format coming back from 
													 //a date field in oracle.
var CLMSystemDefaultDateFormat3 = "yyyy-MM-dd HH:mm";//this is the format coming back from 
													 //a date field in oracle.

var CLM_dateFormats = {
	short:"m/d/Y"
};
			 
var CLMSystemDefaultDateFormat_Short="MM-dd-yyyy";
var localizedDateFormat_Short = "MM/dd/yyyy";														 
/* ########## UI Utilities ########## */

/**
 * Append the returned content to the existing content in the 
 * specified UI location.
 * 
 * @param {string} target The name of the DIV to append the content to
 * @param {string} content The content to append to the target DIV
 * @param {boolean} prepend If true, append the new content before the old 
 * 		(defaults to true)
 */
function appendContent(target, content, prepend)
{
	//need to check for existance of div first...
	var existingContent = "";
	var newLineChar = "<br />";
	var taretEl = document.getElementById(target);
	
	if (taretEl != null)
	{
		existingContent = taretEl.innerHTML;
		if ((existingContent == ""))
		{
			newLineChar = "";
		}
		
		if (prepend == undefined)
		{
			prepend = true;
		}
	
		switch (prepend)
		{
			case true:
				content = content + newLineChar + existingContent;
				break;
			case false:
				content = existingContent + newLineChar + content;
				break;
		}
		writeContent(target, content);
	}
	else
	{
		//target div does not exist
		var msg = "Error: appendContent(\'" +  target + "\', " + content 
				+ "\', " + prepend + ")\n\n" + "Unable to find target: " 
				+ target + "!";
		ErrorHandler(msg, "debug");
	}	
}

/**
 * Dynamically append a CSS file to the document.
 *
 * @param {string} file The file name of the CSS file (relative to the web 
 * 		content root)
 * @param {string} target The name of the link element to append the CSS 
 *		reference to (optional)
 * @param {boolean} create If set to true, a new element will be created and appended 
 *		to the DOM (if the target does not exist)
 */
function appendCSS(file, target, create)
{
	var oCssImportEl = document.getElementById(target);
	var bCreate = false;
	
	if (create)
	{
		bCreate = true;
	}

	if (oCssImportEl)
	{
		//apply the CSS import to the named link element
		oCssImportEl.href = file;
	}
	else if (bCreate)
	{
		//create a new link element
		
		//iterate through existing script imports and if it already exists 
		//	remove it and re-import it.  this ensures that code to be executed 
		//	at runtime is fired each time and prevents the same scripts from 
		//	being added multiple times.
		var listCSSImports = document.getElementsByTagName('link');
		for (var i = 0; i < listCSSImports.length; i++)
		{
			if(listCSSImports[i].getAttribute("href") == file)
			{
				//if the file we are trying to import already exists, remove it
				//alert("remove: " + listScripts[i]);
				var x = document.body.removeChild(listCSSImports[i]);
			}
		}

		var oScript = document.createElement("link");
			oScript.setAttribute("rel", "stylesheet");
			oScript.setAttribute("type", "text/css");
			oScript.setAttribute("href", file);
		document.body.appendChild(oScript);

		oScript = null;	
	}
	else
	{
		//Call ErrorHandler, the CSS target was not found and the create flag was not set.
		ErrorHandler("CSS Import Failed!");
	}
}

/**
 * Dynamically appends an external javascript file to the document.
 *
 * @param {string} file The file name of the script file (relative to the web 
 *			content root)
 */
function appendScriptFile(file, target)
{ 
	//iterate through existing script imports and if it already exists remove 
	//	it and re-import it. this ensures that code to be executed at runtime
	//	is fired each time and prevents the same scripts from being added 
	//	multiple times.
	var listScripts = document.getElementsByTagName('script');

	for (var i=0; i<listScripts.length;i++)
	{
		if(listScripts[i].getAttribute("src") == file)
		{
			//if the file we are trying to import already exists, remove it
			var x = document.body.removeChild(listScripts[i]);
		}
	}

	var oScript = document.createElement("script");
		oScript.setAttribute("type", "text/javascript");
		oScript.src = file;
	var s = document.body.appendChild(oScript);
	
	return s;
}

/**
 * Parses the response text returned from the server for any script tags
 * and executes the contined code.
 *
 * @param {string} responseText The raw content returned by the server
 */
function executeScript(responseText) 
{
	//TODO:  in order to get cross browser functionality we need to get a regular expression that
	// 	works cross browser.  currently the regex that we use, only works on IE, which is why we 
	//  can't use Firefox/others right now.
	//var scripts = responseText.match(/((<[\s\/]*script\b[^>]*>)([^>]*)(<\/script>))/img);
	
	// RegExp from prototype.sonio.net
	/*var ScriptFragment = '(?:<script.*?>)((\n|.)*?)(?:</script>)';
	var match = new RegExp(ScriptFragment, 'img');
	var scripts = responseText.match(match);
	*/

	var scripts;
	
	if(useXBrowserRE == true){
		scripts = [];
		while((myArray = xBrowserRE.exec(responseText)) != null){
			scripts.push(myArray[1]);
		}
	}else{
		scripts = responseText.match(ieRE);		
	}
	
	if(scripts)
	{
		var js = '';
		
		if(useXBrowserRE == true){
			for(var s = 0; s < scripts.length; s++){
				js += scripts[s];
			}
		}else{
			for(var i = 0; i < scripts.length; i++){
				var match = new RegExp(ScriptFragment, 'im');
				js += scripts[i].match(match)[1];
			}
		}
		//wrapping the script in the CDATA tag changes these characters (<, >), 
		//this converts them back
		js = js.replace('&lt;', '<');
		js = js.replace('&gt;', '>');

		try
		{
			eval(js);
		}
		catch(e)
		{
			var msg = "ERROR: executeScript()\n\n"
					+ e.description + "\n\n" + js;
			ErrorHandler(msg,"debug");
		}
	}
}

function updateUIOverlay()
{
	if(objRequest.readyState != 4)
	{
			if (Ext.get('body') && Ext.get('loading'))
			{
				var pos = [];
				pos[0] = 0;
				pos[1] = getResourceManager(true).get('viewport_height')-(Ext.get('loading').getHeight());
			}
	}
	if(objRequest.readyState == 4)
	{
		var response = objRequest.responseText;
				
		if (objRequest.status == 200) 
		{	
			updateUIComponent();
			getOverlay();
		}
	}
}
/**
 * Process server response and call the function to write the 
 * returned content to the specified UI region.  
 * If the region specified is 'processGridData' then the data will
 * be processed as XML data to be loaded into the data grid control.
 * If the region specified is 'redirectBrowser' then the browser will
 * be redirected to the specified page.
 */
function updateUIComponent()
{
	if(objRequest.readyState != 4)
	{
			if (Ext.get('body') && Ext.get('loading'))
			{
				var pos = [];
				pos[0] = 0;
				pos[1] = getResourceManager(true).get('viewport_height')-(Ext.get('loading').getHeight());
			}
	}
	
	if(objRequest.readyState == 4)
	{
		var response = objRequest.responseText;
		
		if (objRequest.status == 200) 
		{	
			var rm = getResourceManager(true);
			var response_array = response.split("|");
			var target = response_array[0];
			var content = "";
			
			if (response_array.length > 2)
			{
				content = response.substring(response.indexOf("|")+1, response.length);
			}
			else
			{
				content = response_array[1];
			}
			
			//hide loading indicator
			if (Ext.get('body') && Ext.get('loading'))
			{
				Ext.get('body').setStyle("cursor","");
				Ext.get('loading').hide();
			}
			
			rm.set('lastUiTarget',target);
			//filter out special responses (redirects, errors, grid data - 
			//	should not come through standard UI updater)
			if (target == "redirect")
			{
				location.href = content;
			}
			else if (target == "processGridData")
			{
				alert("Grid Processor called: " + content);
			}
			else if (target == "messages")
			{
				if ( content.indexOf( "<message>" ) >= 0 ){
					var message_content = "";
					if ( content.indexOf( "<message_content>" ) >= 0 ){
						message_content =  content.substring( content.indexOf( "<message_content>" ) + "<message_content>".length, content.indexOf( "</message_content>" )  );
						
					}
					message_content = message_content.replace("<![CDATA[", "");
					message_content = message_content.replace("]]>", "");
					var message_type = "";
					if ( content.indexOf( "<message_type>" ) >= 0 ){
						message_type =  content.substring( content.indexOf( "<message_type>" ) + "<message_type>".length, content.indexOf( "</message_type>" )  );
					}
					

					MessageHandler( message_content, message_type );
				}else{
					MessageHandler(content);
				}			}
			
			else if (target == "script")
			{
				executeScript(content);
			}
			
			//if the servlet has set the target to empty string, it comes to the ui as a
			//carriage return and a new line feed.  so the target is actually 2 characters long. 
			//do a charCodeAt and only write the content if the target is not a carriage 
			//return and a new line feed
			else if(target.charCodeAt(0) != "13" && target.charCodeAt(1) != "10")
			{
				writeContent(target, content);
			}
			
			return;
		}
		else
		{
			ErrorHandler(response);
		}
    }
}

/**
 * Write the returned content to the specified UI region.
 *
 * @param {string} target The name of the DIV to write the content to
 * @param {string} content The content to append to the target DIV
 */
function writeContent(target, content)
{	 
	var oTarget = document.getElementById(target);//getEl(target);
  
	if (!oTarget)
	{
		var msg = "ERROR:  UI target region '" + target
				+ "' does not exist in this layout!<br />";
		msg += "Error caught in UI - function: writeContent()<br />";
		msg += "================Server Response================<br /><pre>" 
				+ objRequest.responseText + "</pre>";
		ErrorHandler(msg);
	}
	else
	{	
		oTarget.innerHTML = content;
	
		executeScript(content);
	}	
}

/**
 * Checks for a title element for the given target 'component' and sets it's 
 *		title if it exists.
 *
 * @param {string} uitarget The name of the DIV to write the content to
 * @param {string} title The supplied title to set
 */
function setRegionTitle(uitarget, title)
{
	//set the content panel title per the value in the link
	if ((uitarget == "maincontent_content") && (title != null))
	{
		var oTitlePanel = document.getElementById("maincontent_title");
		if (oTitlePanel)
		{
			oTitlePanel.innerHTML = title;
		}
	}
	else
	{
		//get reference to content region title
		var oTitle = document.getElementById(uitarget + '-title');

		if (oTitle)
		{
			oTitle.innerHTML = title;
		}
	}
}



/* ########## Event Handlers ########## */

/**
 * Generic handler for mouse clicks. 
 *
 * @param {} e Browser event object
 */
function clickHandler(e)
{
	var targ;
	if (!e)
	{ 
		e = window.event;
	}
	
	if (e.target) 
	{
		targ = e.target;
	}	
	else if (e.srcElement) 
	{
		targ = e.srcElement;
	}
		
	if (targ.nodeType == 3) // defeat Safari bug
	{
		targ = targ.parentNode;
	}	
}

/**
 * Generic handler for key press (using the Ext.EventManager).
 *
 * @param e Normalized yui-ext event object
 */
 
function keyPressedHandler(e)
{

	 var myDiv = Ext.get(e);
	 var keyPressed = e.getKey();
	 if (keyPressed == e.RETURN)
	{
		//figure out how to submit the form
		//alert('you pressed enter now the form should submit damnit');
	}
}

/**
 * Creates an event handler on the specified object that responds to the enter
 *	key.  The supplied function will be called with the given parameters. 
 * 
 * @param elementID {string} The ID of the element that the event handler should
 *		should be attached to.
 * @param functionName {string} The name of the function to be called when the 
 *		event is fired.
 * @param arguments {string/string or boolean array} Arguments to be passed to 
 *		the function specified when the event is fired.
 *		`	If 'this' is passed as the only argument the elementID parameter 
 *				will be passed to the called function.
 *			To specify multiple parameters pass in an array object, for example:
 *				setEnterKeyEvent('elID','fn',['string',boolean]);
 *		NOTE: only strings, numbers and booleans are supported
 */
function setEnterKeyEvent(elementID,functionName,arguments)
{
	var el = Ext.get(elementID);
	var args = "";
	
	if (arguments == 'this')
	{
		args = elementID;
	}
	else if(typeof(arguments) == 'string')
	{
		args = "'" + arguments + "'";
	}
	else if(typeof(arguments) == 'object')
	{
		//args are an array... need to wrap stings in quotes and seperate
		//	with commas	
		for (var i=0; i<arguments.length; i++)
		{
			
			if (typeof(arguments[i]) == 'string')
			{
				args += "'" + arguments[i] + "'";
			}
			else
			{
				args += arguments[i];
			}
			
			if (i < arguments.length-1)
			{
				args += ",";
			}
		}
	}
	else
	{
		args = arguments;
	}

	var fn = functionName + "(" + args + ")";

	el.addKeyListener(13, function(){eval(fn);});
}

/* ########## AJAX ########## */

/**
 * Creates the XMLHTTP object that is used to communicate with the server. 
 *
 * @return XMLHTTP Request Object
 */
function createRequestObject()
{
    var objReq = true;
    var msg = "";
    if(window.XMLHttpRequest && !(window.ActiveXObject)) 
    {
    	try 
    	{
			return new XMLHttpRequest();
        } 
        catch(e)
        {
			objReq = false;
			msg = "Error: createRequestObject()\n\n"
    			+ "An error was encountered while creating the " 
    			+ "XMLHttpRequest object.\n\n" + e.description;
        }
    }
    else if(window.ActiveXObject)
    {
    	var axO = ['Msxml2.XMLHTTP.6.0', 'Msxml2.XMLHTTP.4.0', 'Msxml2.XMLHTTP.3.0', 'Msxml2.XMLHTTP', 'Microsoft.XMLHTTP'];
		for(var i = 0; i < axO.length; i++)
		{
    		try
			{
				return new ActiveXObject(axO[i]);
			}
			catch(e)
			{
				objReq = false;
				msg = "Error: createRequestObject()\n\n"
	    			+ "An error was encountered while creating the " 
	    			+ "XMLHttpRequest object.\n\n" + e.description;
			}
    	}
    }
    else
    {
    	objReq = false;
    	msg = "Error: createRequestObject()\n\n"
    			+ "Your browser may not support the XMLHttpRequest object.";
    }
    
    //if there were exceptions, call the error handler with an error msg
    if (!objReq)
    {
    	msg = "Error: createRequestObject()\n\n"
    			+ "An error was encountered while creating the XMLHttpRequest " 
    			+ "object.\n\n" + e.description;
    	ErrorHandler(msg,"debug");
    }
}

/**
 * Generates a timestamp to append to the AJAX request call to prevent IE from 
 *		caching responses.
 *
 * @return {string} A key value pair containing the current system time (ms), 
 *		ex: &timestamp=9346593460
 */
function getTimeStamp()
{
	var D = new Date();
	var timestamp = D.getTime();

	return "&timestamp=" + timestamp;
}

/**
 * Opens an HTTP connection and makes a request to the CLM servlet.
 *
 * @param {string} resourceID URL to the CLM Servlet (or other server resource 
 *		to call)
 * @param {string} method HTTP request method ('get' or 'post')
 * @param {string} data The data to send to the server
 * @param {string} handler The callback function to pass the resonse to upon 
 *		success
 * @param async Not currently implemented 
 *		 - (supposed to be a way of making a synchronous request but it does not 
 *			seem to be working)
 */
function doRequest(resourceID, method, data, handler, async)
{
	data = escapeExtendedSplCharsManual(data);
	var URI = resourceID;
	if (method == "get")
	{
		URI = URI + "?" + data + getTimeStamp();
		data = null;
		async = false;
		objRequest.open(method, URI, async);
	}
	else if (method == "post")
	{
		if(async == undefined){
			async = true;
		}
		
		objRequest.open(method, URI, async);
		objRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
	}
	
	if( window.XMLHttpRequest && !(window.ActiveXObject) ) 
    {
		objRequest.onload = eval(handler);
	}
	else
	{
		objRequest.onreadystatechange = eval(handler);
	}

	objRequest.send(data);
	
	if(isLogRequestEnabled){
		var command = (method == "get") ? URI : data;
		logRequestToRM(resourceID, method, command, handler, async);
	}
}
/**
 * Logs the request to the resource manager for debugging purposes.
 */
function logRequestToRM(resourceID, method, data, handler, async){
	var numRequestsToSave = 5;
	
	var loggedRequests = frmwrk_rm.get("loggedRequests");
	
	if(typeof (loggedRequests) == "undefined"){
		loggedRequests = [];
	}

	var request = {
					"resourceID": resourceID, 
					"method":method, 
					"data":data, 
					"handler":handler, 
					"async":async
				};
	
	loggedRequests.unshift(request);

	if(loggedRequests.length > numRequestsToSave){
		loggedRequests.pop();
	}
	
	frmwrk_rm.set("loggedRequests", loggedRequests);
}

function showLastRequest(){
	var debugWin;
	
	var requests = frmwrk_rm.get("loggedRequests");
	if(requests.length > 0){
	
		var string ="";
		for (var i = 0; i < requests.length; i++) {
			var	r = requests[i];
			var commandArr = requests[i].data.split("&");
			var commandString = "<div style='margin-left:20px;'>"+ commandArr.join("<br/>") +"</div>";
			
			string += "<b>resourceID:</b> "+r.resourceID
				+"<br><b>method:</b> "+r.method
				+"<br><b>data:</b> "+commandString
				+"<br><b>handler:</b> "+r.handler
				+"<br><b>async:</b> "+r.async
				+"<br><hr><br>";
		}
		debugWin = window.open("", "ShowLastRequests", "status=yes,toolbar=0,menubar=0,resizable=1,scrollbars=1");
		debugWin.document.body.innerHTML = string;
	}
}




/**
 * Parses the form being submitted and sends the data to the server to be 
 *		processed.
 *
 * @param {string/object} me The object initiating the form submission or a form 
 * 		reference (can be an element in the form, i.e. the submit button, the 
 *		form object, or the form id)
 * @param {boolean} returnCommand If set to TRUE, the function returns the 
 *		parsed form data as a command string instead of submitting it directly 
 *		to the server (this allows for elements to make their own calls to the 
 *		server, ex: grid controls request their own data from the server)
 *		Default value: FALSE
 * @param {string} newClass Style class to be applied to elements that fail form 
 *		validation
 * @param {string} alerttype The method used to alert users of validation 
 *		failure (alert or dialog)
 */
function submitForm(me, returnCommand, newClass, alerttype)
{	
	//me is the element with the onlick, find the form element
	var oForm = null;
	var method = "post";
	var handler = "updateUIComponent";
	var postData = "";
	var targetDiv = "";
	var regionTitle = "";
	var bReturnCommand = false;

	if (returnCommand)
	{
		bReturnCommand = true;
	}
	
	//alert("form passed into method: " + me.id + " " + Ext.get(me));
	
	var container = null;
	if (me == '')
	{
		container = Ext.get(document);
	}
	else
	{
		//if oForm is undefined, we may be passing the form or from name
		//itself into the function, not the submit button
		oForm = me.form;

		if(!oForm)
		{
			if(typeof(me) != 'object')
			{
				//this assumes that the form name is being passed (don't think we'll 
				//	need more validation but could)
				oForm = document.getElementById(me);
			}
			else
			{
				oForm = me;
			}
		}

		container = Ext.get(oForm);
	}

	//check for a form pre-processor (form attribute), passed as a string 
	//(eg: "preValidateForm()") and we eval the string.
	//The form pre-processor function should be used format form data
	//and to do a validation check on items not checked 
	//by validateForm() (this includes checkboxes and radio buttons).
	//the form pre-processor function should return an error string that 
	//will be passed to validate form and appear in the error dialog box.  
	var preProcessorError = null;
	/*
	//////COMMENTING FOR NOW, all forms are validated right now and it causes problems
	if(oForm.processForm)
	{
	//	preProcessorError = eval(oForm.processForm);
	}

	//if form validation fails, exit out of this function.
	if(!validateForm(me, preProcessorError, newClass, alerttype))
	{
		return;
	}
	*/
	
	//iterate through fields
	var formFields = container.dom.elements;

	var formLen = formFields.length;

	for (var f=0; f<formLen; f++) 
	{
		var fld = formFields[f];
		var fldType = fld.getAttribute("type");

		if ((fldType != "button") && (fldType != "reset") && (fldType != "submit")) 
		{	
		
			var fldId = fld.getAttribute("name");
			var fldValue = "";
			if(fld.tagName == "SELECT"){	
				if (fld.options.length > 0 && fld.selectedIndex != -1) {
					//Right now, only support single select fields
					fldValue = escape(fld.options[fld.selectedIndex].value); // Escaping for sending parameters containing special characters to the servlet jk017951
				}
			}else{
				fldValue = escape(fld.value); // Escaping for sending parameters containing special characters to the servlet jk017951
			}
			
			//alert("HERE: "+fld.tagName+" "+fldType+" "+fldId+" "+fldValue);
			//if a field does not have a "name" attribute, it will not be 
			//		returned to the server
			if ((fldId != "") && (fldId != null))
			{
				if (fldId == "uitarget")
				{
					targetDiv = fldValue;
					postData += "uitarget=" + fldValue + "&";
				}
				else if (fldId == "title")
				{
					regionTitle = fldValue;
				}
				else
				{				
					//add this conditional statement to stop sending empty pairs
					postData += fldId + "=" + fldValue + "&";
				}

			}
		}
	}	
	
	postData = postData.substr(0, postData.length - 1);
	
	if (bReturnCommand)
	{
		return postData;
	}
	else
	{
		doRequest(clm_servlet, method, postData, handler);
	}
		
	if (regionTitle != "")
	{
		setRegionTitle(targetDiv, regionTitle);
	}
}


/**
 * formatRequest handles generic requests to be passed to the CLMServlet. 
 *		An example would be navigation requests.  3 required data elements 
 *		need to be sent to the servlet for processing: module, command, and 
 *		uitarget.
 * 
 * @param {string} link The object being clicked on (typically an <a>) 
 *		containing the necessary link attributes. 
 * @param {string} usePost - Override the default method (GET) and use 'POST'
 * @param {string} async - manually set wether to use async. Defaults: sync with GET is false, sync with POST is tryue
 */
function formatRequest(link, usePost, async, customHandler)
{
	var getData = "";
	var method = "get";
	if( typeof( usePost ) != 'undefined' && usePost != null && usePost == true )
	{
		method = "post";
	}
    var handler = (customHandler && typeof(customHandler) == 'function') ? customHandler : "updateUIComponent";
    
	while (link.getAttribute("command") == null)
	{
		link = link.parentNode;
		
		//if you get to the top of the DOM, exit out of this method.
		if (link.getAttribute("tagname") == "HTML")
		{
			return false;
		}
	}
	
	var module = link.getAttribute("module");
	var system_name = link.getAttribute("system_name");
	var command = link.getAttribute("command");
	var uitarget = link.getAttribute("uitarget");
	var title = link.getAttribute("title");
	var navigation_type = link.getAttribute("navigation_type");
	var keyvalue = link.getAttribute("keydata");
	var keydata = "";
	var isOverlay = link.getAttribute("isOverlay");
	if( isOverlay == null ) {
		isOverlay = 'false';
	}
	if( isOverlay == 'true' ) {
		handler = "updateUIOverlay";
	}
	
	if (navigation_type == "navigation_menu")
	{
		var bContinue = cleanUpOpenPages();
		if (!bContinue)
		{
			return false;
		}
	}
	
	if ((keyvalue != null) && (keyvalue != ""))
	{
		var arrKeyvalue = keyvalue.split(",");
		
		for (var i = 0; i<arrKeyvalue.length; i++)
		{
			keydata += "&" + arrKeyvalue[i] + "=" 
					+ link.getAttribute(arrKeyvalue[i]);
		}
	}

	getData = "module="+ module +"&command="+ command +"&system_name="
			+ system_name +"&uitarget="+ uitarget + "&navigation_type=" 
			+ navigation_type + keydata;

	doRequest(clm_servlet, method, getData, handler, async);	
	setRegionTitle(uitarget, title);
	
	if(link.getAttribute('DATA_SOURCE')!=null){
		var ds = link.getAttribute('DATA_SOURCE');
		if(typeof(ds)=='object'){
			ds.reload();
		}
		
	}
	
	return false;
}
/*RK015528/HS016425
	formatRequest() is not supporting post data, 
	this function is does same as formatRequest with sending data in post form 
*/
function sendRequest(link){
	var getData = "";
	var method = "post";
	var handler = "updateUIComponent";
	
	while (link.getAttribute("command") == null)
	{
		link = link.parentNode;
	}

	var module = link.getAttribute("module");
	var system_name = link.getAttribute("system_name");
	var command = link.getAttribute("command");
	var uitarget = link.getAttribute("uitarget");
	var title = link.getAttribute("title");
	var navigation_type = link.getAttribute("navigation_type");
	var keyvalue = link.getAttribute("keydata");
	var keydata = "";
	var isOverlay = link.getAttribute("isOverlay");
	if( isOverlay == null ) {
		isOverlay = 'false';
	}
	if( isOverlay == 'true' ) {
		handler = "updateUIOverlay";
	}
	
	if (navigation_type == "navigation_menu")
	{
		var bContinue = cleanUpOpenPages();
		//alert("UI shoud be clean now\ncontinue: " + bContinue);
		if (!bContinue)
		{
			return false;
		}
	}
	
	if ((keyvalue != null) && (keyvalue != ""))
	{
		var arrKeyvalue = keyvalue.split(",");
		
		for (var i = 0; i<arrKeyvalue.length; i++)
		{
			//alert(arrKeyvalue[i] + "=" + link.getAttribute(arrKeyvalue[i]));
			keydata += "&" + arrKeyvalue[i] + "=" 
					+ link.getAttribute(arrKeyvalue[i]);
		}	
	}

	getData = "module="+ module +"&command="+ command +"&system_name="
			+ system_name +"&uitarget="+ uitarget + "&navigation_type=" 
			+ navigation_type + keydata;

	//alert("command data: " + getData + "\nservlet: " + clm_servlet + " " + method);
	doRequest(clm_servlet, method, getData, handler);	
	setRegionTitle(uitarget, title);
	return false;
}
/**
 * Create the logout confirmation dialog (yui-ext dialog control).
 */
function confirmLogout(){
	o = {
		 title:"Log Off Cerner Learning Manager", 
		 width: 300,
         height: 120
	};
    
	//build the dialog and send the property overrides
	var logoutDialog = CLM_Dialog_Factory.getDialog("logout-dlg", o);
	
	//add any functions used only by this dialog (usually button actions)
	logoutDialog.logoutConfirmed = function(){
		 this.hide();
		 setTimeout(logout, 200);
	};
    
	//add buttons to the dialog.
	logoutDialog.addButton('Yes', logoutDialog.logoutConfirmed, logoutDialog);
	logoutDialog.addButton('No', logoutDialog.hide, logoutDialog);
    
	//show the dialog (the parameter is the object you want the dialog to animate from [optional])
	logoutDialog.show(Ext.get("logoutLink"));
}

/**
 * Log out of the CLM application 
 */
function logout()
{	
	var method = "get";
	var getData = "command=logout&uitarget=redirect";
	var handler = "updateUIComponent";

	doRequest(clm_servlet, method, getData, handler);
}


/**
 * Session timeout functionality.  
 */

var sessionTimeoutInterval;

function checkSessionTimeout(){
	var method = "get";
	var handler = "handleTimoutResponse";
	var async = true;
	
	var module = "security";
	var command = "checkTimeout";
	var uitarget = "someotherDiv";
	
	getData = "module="+ module +"&command="+ command +"&uitarget="+ uitarget;

	doRequest(clm_servlet, method, getData, handler);	
}

function keepSessionActive(){
	var method = "get";
	var handler = "handleTimoutResponse";
	var async = true;
	
	var module = "security";
	var command = "keepSessionActive";
	var uitarget = "someotherDiv";
	
	getData = "module="+ module +"&command="+ command +"&uitarget="+ uitarget;

	doRequest(clm_servlet, method, getData, handler);	
}

//the user is idle, display the dialog box.
function showIdleDialogBox(timeoutLen){
	
	Ext.Msg.show({
   		title:'Warning!',
		msg: 'Your session is about to be timed out as a security precaution. You may press the \'OK\' button to continue your '+
				'current session, or you will be logged out in '+timeoutLen+' minutes.',
		buttons: Ext.Msg.OK,
		fn: keepSessionActive
	});	
}

function handleTimoutResponse(){
	var timeoutLen;
	if(objRequest.readyState == 4)
	{
		if (objRequest.status == 200) 
		{
			
			var response = objRequest.responseText.split("|");
			
			target = response[0];
			status = response[1];
			clearInterval(sessionTimeoutInterval);
			if(status == "displayInactivePopup"){
				
				
				timeoutLen = response[2];
				
				if(timeoutLen == null || typeof(timeoutLen) == "undefined" || timeoutLen.length < 1){
					timeoutLen = 2;
				}else{
					timeoutLen = parseInt(timeoutLen, 10);
				}
				
				sessionTimeoutInterval = setTimeout(checkSessionTimeout, timeoutLen * 1000 * 60 );

				showIdleDialogBox(timeoutLen);
			}else if(target == "logoutUser"){
			
				clearInterval(sessionTimeoutInterval);
				var url = response[1];

				location.href = url;
			}else{
				timeoutLen = response[2];
				
				if(timeoutLen == null || typeof(timeoutLen) == "undefined" || timeoutLen.length < 1){
					timeoutLen = 28;
				}else{
					timeoutLen = parseInt(timeoutLen, 10);
				}

				sessionTimeoutInterval = setTimeout(checkSessionTimeout, timeoutLen * 1000 * 60 );
			}
		}
		else
		{
			//status is the HTTP response code, if not 200, there was a problem 
			//and we can use the response text to see the error message.
			ErrorHandler(response);
		}
    }
}

/**
 * Instantiates the yui-ext dialog control for the error dialog.  This is being 
 *		included in the core library errors can be handled even if the rest of 
 *		the UI has not been retrieved from the server and rendered.
 *
 * ***THE FOLLOWING SHOULD BE INCLUDED IN ANY PAGE THAT IMPORTS THIS SCRIPT:
 * <!-- Error Handler Dialog -->
 * <div id="error-dlg" style="visibility:hidden;position:absolute;top:0px;">
 * 	<div class="ydlg-hd">Error</div>
 * 	<div id="error-msg" class="ydlg-bd" style="background-color: white; padding: 3px;">Loading Error Message...</div>
 * </div>
 */
var errorDialog = function(){
    var dialog, animElement;
 
    return {
        init : function(){
             animElement = Ext.Element.get('header');
             if (!animElement)
             {
             	animElement = '';
             }
  
        },
        
        showDialog : function(){
            if(!dialog){
                dialog = new Ext.BasicDialog("error-dlg", { 
                        modal:true,
                        shim: true,
                        autoTabs:true,
                        draggable: true,
                        width:500,
                        height:300,
                        shadow:true,
                        minWidth:300,
                        minHeight:250,
						collapsible: false
                });
                dialog.addKeyListener(27, dialog.hide, dialog);
                dialog.addButton('Close', dialog.hide, dialog);
            }
            dialog.show(animElement.dom);
        }
    };
}();

Ext.onReady(errorDialog.init, errorDialog, true);
	
	
/**
 * ErrorHandler(responseText, messageLevel)
 * Displays the supplied message in the error dialog.  
 *
 * @param {string} responseText The message to be displayed in the dialog
 * @param {string} messageLevel Messages in the UI can be set to different 
 *		levels which can be turned on/off (i.e. if debug is set, all debugging 
 *		messages will be displayed (by default, errors will always be displayed)
 */
var arrErrors = [];
var isErrors = false;
function ErrorHandler(responseText, messageLevel)
{
	if ((responseText != null) && (responseText != ""))
	{
		//add error to arrErrors - come up with a way to view last error or all 
		//	errors
		arrErrors[arrErrors.length] = responseText;
	}
	
	var display_message = "";
	if (arrErrors.length > 0)
	{
		isErrors = true;
		display_message = arrErrors[arrErrors.length-1];
	}
	else
	{
		isErrors = false;
		display_message = "There are no errors to display.";
	}
	
	
	document.getElementById('error-msg').innerHTML = display_message;
	
	errorDialog.init();
	errorDialog.showDialog();
}

/**
 * Write messages to the 'messages' area.  Unhides the area and controls how long it takes
 *	to disappear.
 *
 * @param {string} message Text of the message to display
 * @param {sting} status Controls how to display the message (i.e. red for error, green for success).
 * TODO: maybe have an org/user preference for the messageTimeoutLength. --ms014408
 */
var messageContainer = 'message';
var messageTimeoutLength = 10000;
function messagesInit()
{
	
}

function showErrorMessageInnerHTML(){
	if( document.getElementById('error-msg') ){alert( document.getElementById('error-msg').innerHTML );}
}

function showMessageInnerHTML(){
	if( document.getElementById('message') ){alert( document.getElementById('message').innerHTML );}
}
function dialogForActivateCourse(courseID, courseName, numberOfCourses){
	showActivateCourseDialog(courseID, courseName, numberOfCourses);
}

var statusClassName = "";
function MessageHandler(message, status)
{	

	if ( message == 'null' || (message == 'null' && typeof(status) == 'undefined'))
	{
		
	}
	else
	{		
		resetMessageStyle();
		
		var oMsg = Ext.get(messageContainer);

		switch (status) {
			case 'SUCCESS':
				statusClassName = "msg-success";
				break;
			case 'INFORMATION':
				statusClassName = "msg-info";
				break;
			case 'WARNING':
				statusClassName = "msg-warning";
				break;
			case 'ERROR':
				statusClassName = "msg-error";
				break;
			default:
				statusClassName = "msg-info";
				break;
		}
		
		if(status == 'ERROR_DIALOG'){
			ErrorHandler(message);
		}else if(status == 'CONFIRM'){
			ConfirmHandler(message);
		}else if(status == 'ALERT'){
			AlertHandler(message);
		}else{
			//set the content and class of the message
			writeContent('messages', message);
			oMsg.addClass(statusClassName);
			
			showDiv(messageContainer);
			oMsg.scale(undefined, 100, {
				duration: 0.35,
				callback: function(){
					setTimeout(closeMessage, messageTimeoutLength);
				}
			});
		}
	}		
}

/*
 * Popup a confirm box from the messaging utility.  This is called as a result of the MessagingUtil on the backend.  
 * 
 */
function AlertHandler(msg){
	Ext.Msg.confirm("Duplicate courses exist", msg, callOverlaySaveFn);
}
/*
 * Popup an alert box from the messaging utility.  This is called as a result of the MessagingUtil on the backend.  
 * 
 */
function AlertHandler(msg){
	Ext.Msg.alert("", msg);
}
/*
 * Since this was designed specifically for overlays, clicking yes will call the overlay's 
 * save function with an "override" parameter of true.  Clicking no will not send call 
 * the overlay function again..
 */
function callOverlaySaveFn(answer){
	if(answer == "yes"){
		CLM_RM.getActiveOverlay().overlay_save(true);
	}else{
		CLM_RM.getActiveOverlay().overlay_save(false);
	}
}
function closeMessage()
{
	var msgDiv = Ext.get(messageContainer);
	msgDiv.scale( undefined, 1, {
		    duration: 0.35,
			callback: function(){
			hideDiv(messageContainer);
		}
	});
}
function resetMessageStyle()
{
	var oMsg = Ext.get(messageContainer);
	if (statusClassName != "")
	{
		oMsg.removeClass(statusClassName);
	}
}

/**
 * Menu functions:
 * 		toggleMenu - toggle menu options (show submenu/change selected item state/etc)
 *		setMenuItems - populate menu items array for easy access to itesm
 */
var activeSubMenu = "";
var arrSubMenus = null;
var lastActiveSubMenu = "";
var selectedMenuItem = "";
var lastSelectedMenuItem = "";
var arrMenuItems = null;
function subMenus()
{
	
}

function bringToTop()
{
	Ext.get(activeSubMenu).setStyle('z-index','100000');
}
function sendToBack()
{
	if((activeSubMenu != "") && (activeSubMenu != null))
	{
		Ext.get(activeSubMenu).setStyle('z-index','0');
	}
}

function toggleSubMenu(el, option, menu)
{
	var oMenu = Ext.get(menu);

	if(oMenu.isVisible())
	{
		resetSubMenus(menu);
	}
	else
	{
		resetSubMenus();
		oMenu.toggle(false);
	}
}


function resetSubMenus(menuToClose)
{
	var oPadCover = Ext.get('menuPadCover');
	
	//collapses menu if the menu is clicked and it is already open
	if(menuToClose != null)
	{
		var subMenu = Ext.get(menuToClose);
		if(subMenu != null && subMenu.isVisible())
		{
			subMenu.toggle(false);
		}
	}
	
	//if pad is showing, toggle it
	if(oPadCover.isVisible())
	{
		oPadCover.toggle();
	}
}


function initSubMenu(menu)
{
	var oMenu = Ext.get(menu);
	oMenu.appendTo(document.getElementsByTagName('body')[0]);
}



/**
 * Standard reusable function for toggling a button state.  The following parameters
 * 	must be provided as attributes of the object that is calling this function.
 * 
 * 	initial-class The initial class applied to the element (this needs to be 
 * 		defined in addition to the class attribute and will have the same value).
 * 	alternate-class The class that will be applied to the element to change it's
 *		appearance (i.e. state).
 *	toggle-element {optional} The id of the element to toggle the display of.
 * 	call-function {optional} The name of a function to be called after the class has been
 *		toggled.  The button element and the state of the button will be passed
 *		as parameters (0 = initial state, 1 = alternate state).
 *
 * @param {object} The element initiating the function.
 *
 * This function should be called using "this" as it's parameter, for example:
 * 		<a onclick="toggleButton(this);" ... >
 */
function toggleButton(button)
{
	//added this if statment so we can pass a string id value not just an object
	//MS014408
	if(typeof(button) == "string"){
		button = document.getElementById(button);
	}
	
	var toggleEl = button.getAttribute("toggle-element");
	var initClass = button.getAttribute("initial-class");
	var altClass = button.getAttribute("alternate-class");
	var newClass = "";
	var btnState = 0;
	
	//swap button CSS class
	if (button.className == initClass)
	{
		newClass = altClass;
		//btnState of 1 means the alt class has been applied
		btnState = 1;
	}
	else
	{
		newClass = initClass;
		//btnState of 0 means the initial class has been applied
		btnState = 0;
	}

	button.className = newClass;
	
	//toggle element if defined
	if (button.getAttribute("toggle-element") && button.getAttribute("toggle-element") != "")
	{
		var el = Ext.get(button.getAttribute("toggle-element"));
		el.enableDisplayMode();
		el.toggle();
		
		//TODO: JW: if making visible, check for the first visible form field
		//	and give it focus()
	}
	
	//call delegate function
	if (button.getAttribute("call-function") && button.getAttribute("call-function") != "")
	{
		eval(button.getAttribute("call-function") + "(button, btnState);");
	}
	
}

/**
 * Truncates a string at the specified length - 3 and adds "...".  The final length
 *	of the string including ellipses will be maxLength.
 * Usage: stringVar.ellipse(30); will return the first 27 characters of 
 *		stringVar followed by 3 periods. 
 * @param maxLength {number} the number of characters to return including ellipses
 */
String.prototype.ellipse = function(maxLength)
{
    if(this.length > maxLength)
    {
        return this.substr(0, maxLength-3) + '...';
    }
    return this;
};

String.prototype.trim = function() {
	return this.replace(/^\s+|\s+$/g,"");
};

/*============================================================================*/
/* ******************************************************************* */
/*   SCREEN FUNCTIONS                                                  */
/* ******************************************************************* */
var Screen = (function() {
  var screen = {};

  // Get a reference to the body
  // --------------------------------------------------------------------
  screen.getBody = function() {
    if (document.body) {
      return document.body;
    }
    if (document.getElementsByTagName) {
      var bodies = document.getElementsByTagName("BODY");
      if (bodies!=null && bodies.length>0) {
        return bodies[0];
      }
    }
    return null;
  };

  // Get the amount that the main document has scrolled from top
  // --------------------------------------------------------------------
  screen.getScrollTop = function() {
    if (document.documentElement && defined(document.documentElement.scrollTop) && document.documentElement.scrollTop>0) {
      return document.documentElement.scrollTop;
    }
    if (document.body && defined(document.body.scrollTop)) {
      return document.body.scrollTop;
    }
    return null;
  };
  
  // Get the amount that the main document has scrolled from left
  // --------------------------------------------------------------------
  screen.getScrollLeft = function() {
    if (document.documentElement && defined(document.documentElement.scrollLeft) && document.documentElement.scrollLeft>0) {
      return document.documentElement.scrollLeft;
    }
    if (document.body && defined(document.body.scrollLeft)) {
      return document.body.scrollLeft;
    }
    return null;
  };
  
  // Util function to default a bad number to 0
  // --------------------------------------------------------------------
  screen.zero = function(n) {
    return (!defined(n) || isNaN(n))?0:n;
  };

  // Get the width of the entire document
  // --------------------------------------------------------------------
  screen.getDocumentWidth = function() {
    var width = 0;
    var body = screen.getBody();
    if (document.documentElement && (!document.compatMode || document.compatMode=="CSS1Compat")) {
        var rightMargin = parseInt(CSS.get(body,'marginRight'),10) || 0;
        var leftMargin = parseInt(CSS.get(body,'marginLeft'), 10) || 0;
      width = Math.max(body.offsetWidth + leftMargin + rightMargin, document.documentElement.clientWidth);
    }
    else {
      width =  Math.max(body.clientWidth, body.scrollWidth);
    }
    if (isNaN(width) || width==0) {
      width = screen.zero(self.innerWidth);
    }
    return width;
  };
  
  // Get the height of the entire document
  // --------------------------------------------------------------------
  screen.getDocumentHeight = function() {
    var body = screen.getBody();
    var innerHeight = (defined(self.innerHeight)&&!isNaN(self.innerHeight))?self.innerHeight:0;
    if (document.documentElement && (!document.compatMode || document.compatMode=="CSS1Compat")) {
        var topMargin = parseInt(CSS.get(body,'marginTop'),10) || 0;
        var bottomMargin = parseInt(CSS.get(body,'marginBottom'), 10) || 0;
      return Math.max(body.offsetHeight + topMargin + bottomMargin, document.documentElement.clientHeight, document.documentElement.scrollHeight, screen.zero(self.innerHeight));
    }
    return Math.max(body.scrollHeight, body.clientHeight, screen.zero(self.innerHeight));
  };
  
  // Get the width of the viewport (viewable area) in the browser window
  // --------------------------------------------------------------------
  screen.getViewportWidth = function() {
    if (document.documentElement && (!document.compatMode || document.compatMode=="CSS1Compat")) {
      return document.documentElement.clientWidth;
    }
    else if (document.compatMode && document.body) {
      return document.body.clientWidth;
    }
    return screen.zero(self.innerWidth);
  };
  
  // Get the height of the viewport (viewable area) in the browser window
  // --------------------------------------------------------------------
  screen.getViewportHeight = function() {
    if (!window.opera && document.documentElement && (!document.compatMode || document.compatMode=="CSS1Compat")) {
      return document.documentElement.clientHeight;
    }
    else if (document.compatMode && !window.opera && document.body) {
      return document.body.clientHeight;
    }
    return screen.zero(self.innerHeight);
  };

  return screen;
})();


/**
 * Get the DOM object of an element with a specified id.
 * 
 * @param {String} id
 * @return the DOM object with the id specified.  If an element with the id doesn't exist, null is returned
 */
function getEl(id){
	return document.getElementById(id);
}
//Escaping special characters manualy which are not escaped using default escape function
function escapeExtendedSplCharsManual(pStr)
{
	if(pStr != null && pStr != 'undefined' && pStr.trim().length >0)
	{
		return pStr.replace(/\+/g,'%2B').replace(/%AE/g,'%C2%AE').replace(/%A9/g,'%C2%A9').replace(/%u2122/g,'%99');
	}
	else
	{
		return pStr;
	}
}
