	 ///////////////////////////////////////////////////////////////////////////////////////////////////////////	
	//Perform an Asynchronous submit with lots of value added functionality.
	//
	//Note: If a Div ID is passed (second param) it assumes you want it filled with the results
	//	of the async submit.  This means if both a Div ID and postJsCallback are passed in then it
	//	will fill the Div and then call the post JS function.  If you only want to have a postJsCallback
	//	do all the work (like distribute the return of a JSON object then pass '' as the id of
	//	the Div (second param to doAsyncSubmit()) and have the post function fill whatever you want.  
	//
	//Thinking of displaying a JS alert if a certain formatted return value prefix was found
	//so that client side validation could be done with an alert.
	//You could also fill an error div from within your preJsCallback for now in the place of that.
	//
	//One notable feature of this framework is that your preJsCallback can return true and force
	//the use of the HTML which called the async submit.  One example is use of HTML tabs.  Maybe on the first click of
	//a tab you want to actually go to a URL and other clicks just show the contents under the tab.
	//So your preJsCallback function will check which to do and if it is just to show the tab
	//contents then the function can return true and it will just function without the AsyncSubmit
	//which means it will just show the tab.  You just test if you really want or need to do the
	//AsyncSubmit or do the no-JS way.  
	//
	//You can also return false from your preJsCallback to stop right then and there with the Async
	//Submit and no more JS or HTML will be done. 
	//
	// TODO: fix overlay div to go over IE inputs e.g. Select
	// TODO: add selenium tests for AsyncSubmit
	//
	//Some general usages of AsyncSubmit:
	//1) onclick="return doAsyncSubmit(this, 'myDivId')"
	//2) onclick="return doAsyncSubmit(this, myDivIdGlobalVar)"
	//3) onclick="return doAsyncSubmit(this, 'myDivId', '', 'validateStuff(myForm)')"
	//4) onclick="return doAsyncSubmit(this, 'myDivId', 'coverAreaDivId', 'doJSValidation(\'someElementId\',\'anotherElementId\')', '','','')" 
	//The following examples need to be re-tested before verifying usability: 
	//4) onclick="return doAsyncSubmit(this, '', '', 'validateStuff(myForm)', 'updateAndInitCalendar(res, myDivIdGlobalVar)')"
	//5) onclick="return doAsyncSubmit(this, '', '', '', 'updateAndInitCalendar(res, myDivIdGlobalVar)')" 
	//
	//Description of above:
	//1) The this reference could be a to the button or link the async submit is set to and
	//	the 'myDivId' filled with the results
	//2) Similar to above except there are no quotes around myDivIdGlobalVar because it is a
	//	JS variable name and not a Div ID
	//3) A button or link is used to fill the 'myDivId' Div and validateStuff(...) is called before
	//	the async submit.  That JS function could do an alert or fill an error Div with validation errors.
	//	Notice that myForm has no quotes so it must be a JS variable that is in scope.
	/////////////////////////////////////////////////////////////////////////////////////////
	
	
	
	
	
	

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//"Public" function that the end user will call.  Not advisable to call the "private" helper function(s) below.  
	//
	//@param item - just pass the object reference named "this" (no quotes) if link or button; otherwise, it is assumed to be a URL w/query params 
	//@param contentId - the ID of the DIV (or alike) to be filled by the results of the Async call.  Can be an empty String if the next param is present.
	//@param divIdToOverlay - if you want to cover an area larger/separate from the Div you are filling specify the div id here
	//@param preJsCallback - optional javascript function to call prior to the asynchronous submit and if the function returns false will handle the error and not do the submit
	//@param postJsCallback - optional javascript function to call on success. 
	//@param postJsErrorCallback - optional javascript function to call on error. 
	//@param messageDivId - optional id of the div to fill with a message for things like validation errors
	//
	/*public*/ function doAsyncSubmit(item, contentId, divIdToOverlay, preJsCallback, postJsCallback, postJsErrorCallback, messageDivId) 
	{
		//debugIt('enter doAsyncSubmit()'); 

		var submitType = 'get';
		var url = '';
		var queryString = '';

		var alreadyHaveUrl = false;

		var result = callJsCallback(preJsCallback);

		//debugIt(result);

		//The next part of the condition helps with the JS paradigm to succeed when using a preJsCallback
		//Your JS function should return true if you want the HTML that was supposed to run
		//instead of the JS or return false if you want this Async Submit to stop and do no
		//more JS or HTML.  Return Nothing (or non-true/false) if you want to continue Async Submit proccessing

		if(null==result || result.length==0)
		{
			//do nothing
		}
		else if(typeof result == 'boolean')
		{
			return result;
		}
		//Special feature allowing you to create in the preJsCallback the URL to go to with the async submit
		else if((typeof result == 'string') && 
			result.indexOf('url:') == 0)
		{
			url = result.substring('url:'.length, result.length);
			alreadyHaveUrl = true;
		}

		
		//TODO: Was thinking of displaying a JS alert if a certain formatted return value prefix was found
		//so that client side validation could be done with an alert.

		
		//Is the item passed in a button for a Form or just a link?  If neither it is a URL w/query params
		if(alreadyHaveUrl)
		{
			//do nothing more here
		}
		else if(item.href) 
		{
			url = item.href;
		}
		else if(typeof item == 'string')
		{
			url = item;
		}
		else
		{ 	
			var theForm = null;
			if(item.form)
			{
				theForm = item.form;
			}
			else if(item.getAttribute('method')!=null)
			{
				theForm = item;	
			}

			if(theForm != null)
			{
				url = theForm.getAttribute('action');
				submitType = theForm.getAttribute('method')? theForm.getAttribute('method') : 'post';
				queryString = Form.serialize(theForm)
			}

		}

		//debugIt(url); 

		return doASubmit(1, item, contentId, url, queryString, submitType, postJsCallback, postJsErrorCallback, divIdToOverlay, messageDivId);
	}




	/////////////////////////////////////////////////////////////////////////////////////////////
	//Perform an Ajax submit.  Think of this as the private version of the function.  Shouldn't
	//be called from outside this .js file.
	//  
	//@param callNum - the number of times this function has been called in a setTimeOut(...) (again, this is for IE bug)
	//@param item - just pass the object reference named this whether link or button
	//@param contentId - to make known the unique portlet for which this is submitting.  The id of your div to be filled should be 'content<portlet-id>'
	//@param url - the URL prior to the querystring of where to go during the async submit
	//@param queryString - any name value pairs to pass as the query string
	//@param submitType - usually either 'post' for forms and 'get' for links
	//@param jsFunctionCallback - optional javascript function to call on success. The Ajax response can be passed as an arguement to your JS post function as: res
	//@param jsErrorFunctionCallback - optional javascript function to call on failure. The Ajax response can be passed as an arguement to your JS post function as: res
	//@param divIdToOverlay the id of the div, if any, to overlay
	//
	/*private*/ function doASubmit(callNum, item, contentId, url, queryString, submitType, jsFunctionCallback, jsErrorFunctionCallback, divIdToOverlay, messageDivId)
	{
		//The first time this function is called for each doAsyncSubmit()  
		//call it will have the "wrong" value until it is assigned in the callNum==1 condition.
		//Each call after that it will the assignment will be correct.
		//Remember that multiple calls should be rare (IE bug) 
		var overLayDivId = divIdToOverlay;

		if(callNum == 1) {
			//Tells the Servlet that async submit was used and not the usual click or form submit
			//The Servlet can then handle non-asynchronous submits differently (e.g. use returnToPortal).  Thanks CurtisB for that idea! 		
			queryString += '&async=true';
		
			//This makes sure the browser doesn't cache a page for a given URL
			queryString += ('&seed=' + new Date().getTime());
		
			//Make the interface show that work is going to be done (i.e. hour glass) in case it takes awhile
			//to do the async submit
			overlayDivId = displayCoverUp(divIdToOverlay);
		}else if(callNum == 12) {
			finishAsyncSubmitError(res, jsErrorFunctionCallback, overlayDivId, 'IE HTTPS Post Error could not be overcome (submitted request 12 times)')
		}
		
		//debugIt('url: '+url + ' qs: '+queryString); 
		
		var postJsFunctionResult = false;
		
		//The actual submit using Ajax
		new Ajax.Request( 
			url, 
			{
				method: submitType, 
				parameters: queryString,
				
				onSuccess:function t(res){ 
					postJsFunctionResult = finishAsyncSubmit(res, contentId, overlayDivId, jsFunctionCallback, messageDivId) 
				},
				
				onFailure: function t(res){ 
					//In certain cases an IE bug forces resubmittal
					switch(res.status) {
					// workaround for IE 6 SSL Ajax bug - intermittently fails witout sending the request and gives one of these codes
	                case 12029:
	                case 12030:
	                case 12031:
	                case 12152:
	                case 12159:
	                case 55517: //This is for a problem with "invalidAction is invalid" 
	                    setTimeout( function necessaryFuncWrapper(){ doASubmit(++callNum, item, contentId, url, queryString, submitType, jsFunctionCallback, jsErrorFunctionCallback, overlayDivId)} , 1000);
	                    break;
	                default:function f(res){
	                    postJsFunctionResult = finishAsyncSubmitError(res, jsErrorFunctionCallback, overlayDivId, 'Error: Server could not process request')
	                    }
	                    break;
	            	}	            													
				}
				
				//,onException: function f(res, exception){ 
				//finishAsyncSubmitException(res, jsErrorFunctionCallback, overlayDivId, exception) 
				//}
			});

		//We want to always return false from the AsyncSubmit because this
		//indicates to the HTML onclick to not continue with the HTML
		//But if the user returned true from the JS function (hopefully
		//on purpose, then we'll return that which means continue with
		//the HTML (form submit or link press)
		if(typeof postJsFunctionResult == 'boolean')
		{
			return postJsFunctionResult;
		}
		else
		{
			return false;
		}
	}




	////////////////////////////////////////////////////////////////////////////////////////////////////////
	//This is called after the asynchronous submit to do further processing.
	//Consider the method private and shouldn't be called directly by developers
	//
	//true or false can be returned as a final out to do the html from which this was called
	//
    /*private*/ function finishAsyncSubmit(res, contentId, overlayDivId, jsFunctionCallback, messageDivId)
    {
		//debugIt('enter finishAsyncSubmit()'); 
		//debugIt('res='+res.responseText); 

		hideCoverUp(overlayDivId);
	
		var returnValue = false;

		//For updates you can opt to just return "Success updating database" 
		//without having to change the page
		//Or "Error updating xyz" without having to change the page
		//because a JS alert will be done here
		var rtLen = res.responseText !=null? res.responseText.length : 0;

		if(rtLen>0 && res.responseText.indexOf('Success')==0 || 
				res.responseText.indexOf('Error')==0) 
		{
			alert(res.responseText);
		}
		else if(rtLen>"insert-message".length && 
			res.responseText.substr(0,rtLen<150?rtLen:150).indexOf("insert-message")>=0)
		{
			var messageDiv = goGetElementById(messageDivId);
			if(messageDiv != null)
			{
				messageDiv.innerHTML = res.responseText;
			}
			else
			{
				//debugIt('Found insert message but no message Div');
			} 
		}else 
		{
			//Attempt to fill the div here if one was specified
			var content = goGetElementById(contentId);

			//If a div to fill was included then it will be filled here
			if(content!=null)
			{
				content.innerHTML = res.responseText;
			}

			//Attempt to do the (success) JS post callback
			returnValue = callJsCallback(jsFunctionCallback, res);
		}
		
		//The calling function will handle the return value
		return returnValue;
	}


	/*private*/ function finishAsyncSubmitError(res, jsErrorFunctionCallback, overlayDivId, errorMessage)
	{
		//debugIt('enter finishAsyncSubmitError()'); 

		hideCoverUp(overlayDivId);
	
		//The calling function will handle the return type
		return callJsCallback(jsErrorFunctionCallback, res, errorMessage);
	}

	/*private*/ function finishAsyncSubmitException(res, jsErrorFunctionCallback, overlayDivId, exception) 
	{
		//debugIt('enter finishAsyncSubmitException()'); 
		//debugIt(exception.message); 

		hideCoverUp(overlayDivId);
	
		//The calling function will handle the return type
		return callJsCallback(jsErrorFunctionCallback, res, 'Error: An exception occurred', exception);
	}
	
	
	/////////////////////////////////////////////////////////////////////////////////////////
	//@param theFunction the string representation of the function or function itself to call
	//@param res optional response object returned by the Ajax request function (only available to the post JS calls and not the pre)
	//@param nothingToDoMessage an optional message to display in an alert if nothing is to be done i.e. no error method to get to, etc. (great for the post JS error function,  if you define a function the alert won't popup)
	//@param exception the exception as handed off from Ajax will be available to your post JS error function if set as a parameter to your function
	/*private*/ function callJsCallback(theFunction, res, nothingToDoMessage, exception)
	{
		var pResult = theFunction;
		//check if passed a string representation of function, if so, we'll eval it
		//(if it was not a string representation but an actual function 
		//then the assignment above will have made the call to it
		if(null==pResult || pResult.length==0)
		{
			if(null!=nothingToDoMessage &&  nothingToDoMessage.length>0)
			{
				alert(nothingToDoMessage);
			}
		}
		else if(typeof pResult == 'boolean')
		{
			return pResult;
		}				
		else if((typeof pResult == 'string') && 
			pResult.lastIndexOf(')') == pResult.length-1)
		{
			pResult = eval(pResult);
		}

		return pResult;
	}


	//////////////////////////////////////////////////////////////////////////////////////////////
	//Display a DIV covering another specified DIV with an animated swirly (processing) icon
	//@param contentId the "content" DIV which will be covered up if no overlayId was specified (i.e. if overlayId is null/undefined)
	//@param overlayId the id of the div to cover which will most likely be the parent of the content div
	//
	/*private*/ function displayCoverUp(overlayId)
	{	
		//The div we want to cover is either the spcified div to overlay
		//or the content area, precendence is specified overlay then content 
		var divToCoverId = overlayId;
		var contentDiv = goGetElementById( divToCoverId ); 
		if( !contentDiv )
		{
			return;
		}
		var overlayId = divToCoverId + 'Overlay'; 
		var overlayDiv = goGetElementById( overlayId ) 

		//Create the overlay only if it isn't available (from a possible prior creation)
		if( !overlayDiv ) 
		{
			overlayDiv = document.createElement( 'div' );
			overlayDiv.setAttribute( 'id', overlayId );
			overlayDiv.style.position = 'absolute';
			Element.setStyle(overlayDiv, {
				backgroundColor: '#f1f1f1', 
				opacity: 0.7
			});

			var processing = document.createElement( 'p' );
			processing.id = 'fbPID';
			processing.style.textAlign = 'center';
			var img = document.createElement( 'img' );
			img.src = '/public/imageserver/webservices/opensource.gov/progress_config.gif';
			img.alt = 'Please wait...';

			processing.appendChild( img );
			overlayDiv.appendChild( processing );

			overlayDiv.style.display = 'none';
			contentDiv.insertBefore(overlayDiv, contentDiv.firstChild);
		}

		overlayDiv.style.width = contentDiv.offsetWidth + 'px';
		overlayDiv.style.height = contentDiv.offsetHeight + 'px';
		overlayDiv.style.display = 'block';

		return overlayId;
    }


	//////////////////////////////////////////////////////////////////////////////////////////////
	//@param overlayDivId by the time this is called we'll know which one was covered and now uncover it
	function hideCoverUp(overlayDivId)
	{
		if(overlayDivId)
		{
			var overlayDiv = goGetElementById( overlayDivId );
			if( overlayDiv )
			{
				overlayDiv.style.display = 'none';
			}
		}
	}



	///////////////////////////////////////////////////////////////////////////////////////////////
	//A convenience function for starting lower (than the top) of the DOM and finding an object.
	//(Just thrown in for the heck of it)
	//
	/*public*/ function findElement(elementId, fromContentId)
	{
		return goGetElementById(fromContentId).down('#'+elementId);
	}
	
	
	//////////////////////////////////////////////////////////////////////////////
	//obviously a convenience function to assist in debugging the way you prefer:
	//console or alert or other future way
	/*public*/ function debugIt(debugStr)
	{
		alert(debugStr);
		//console.info(debugStr);
	}
	
	
	///////////////////////////////////////////////////////////////////////////////
	//A convenience wrapper function to easily use the best element finder you like to use
	//e.g. prototype.js $() or not
	/*public*/ function goGetElementById(elementId)
	{
		//find elements your preferred way here and comment the below line
		//if you don't want to use prototype.js
		return $(elementId);
	}
	
	/////////////////////////////////////////////////////////////////////
	//Clears out an input only if the text inside matches the specified text
	//So only if you have passed a string like "Enter an answer here" will 
	//it clear it out the text; otherwise, it is assumed that the text was 
	//user specified
	function clearField(item, genText)
	{
		if(item.value)
		{
			if(item.value.indexOf(genText)==0)
			{
				item.value = "";
			}
		}
	}

	//////////////////////////////////////////////////////////////////////////////
	//Convenience function in case you want to override the "automatic" alert displayed 
	//when no post JS error function is specified (so that you can have your JSP handle the
	//Exception thrown by the async submit as an example) you can always add a call
	//to this function
	function doNothing()
	{
	}
	
	////////////////////////////////////////////////////////////////////////////////////////////////////
	//Created to test if the doAsyncSumbmit(...) will work as an optional JS function callback
	//to doAsyncSubmit(...) to prove the handle to the Ajax response works 
	function testFramework(res){
		alert("Here is the response text: "+ res.responseText);
	}


