/*
 *  AJAS - FrameWork
 *  ================
 * 
 *  Copyright (c) 2006 JM Software
 *  www.jm.cl
 * 
 * 
 * 	Description:
 * 	============
 * 
 * 	AJAS Framework is a library that allow you to introduce Asynchronous calls
 *  into a traditional webpage, just by adding javascript calls to forms and links.
 * 
 * 	AJAS stands for Asynchronous Javascript And Smarty
 * 
 * 	Altough it doesn't require Smarty (smarty.php.net) to operate, I always 
 *  use it in my projects, so it came out as a good name.
 * 
 * 	It is based on the idea that a good website is always DIVided into modules.
 *  Each module provides a certain functionality such a "poll". A poll is made
 *  traditionaly of a HTML Form which is POSTed to a server to save the 
 *  chosed preference. This call to the server makes the entire webpage to be 
 *  reloaded.
 * 
 *  AJAS make posible to just reload the HTML code of the poll into the same 
 *  place in the page, leaving the other content untouched.
 * 
 *  AJAS it's based on the prototype library (http://prototype.conio.net/).
 * 
 * 	Usage:
 *  ======
 * 
 *  Step 1: add a <div> at the beggining of the element you wish to AJAS, and a
 *          </div> at the end, so the old code is contained in the div. Give 
 * 	        this DIV an unique ID name.
 * 
 *  Step 2: Add the following code to your FORM or A HREF tag:
 * 
 *          - Form: onSubmit="return formPost(this, 'targetName')"
 *          - A href: onClick="return openLink(this, 'targetName')"
 * 	
 *          Where 'targetName' is the ID name of the element's DIV in Step 1.
 *  
 *  Step 3: Modify your server side behavior, so the output produced by that 
 *          module is just the HTML code of this element.	
 * 	
 * 
 *  AJAS Files:
 *  ===========
 * 
 * 		- ajas.js: script containing the formPost and openLink functions.
 * 		- ajas.css: stylesheet for the loading and error messages
 * 		- jmsoftware-mitlicense.txt: licence detail
 * 
 * 
 *  AJAS Licence:
 *  =============
 * 
 *  AJAS is distributed under the terms of the MIT Licence. See jmsoftware-mitlicense.txt
 *  file for licence details.
 * 
 */



/**
 * formPost
 * Makes the asynchronous call to the server.
 * Displays the "loading" msg in the middle of the container
 * @param theForm the form object to be send to the server
 * @param resultDiv id or object reference to the target DIV container
 * @return false
 */
function formPost(theForm, resultDiv) {
	
	var dest = null;

	if(typeof(resultDiv) == "string")
		dest = $(resultDiv);
	else
		dest = resultDiv

	// undefined container falls into normal form post		
	if(dest == null || typeof(dest) == "undefined")
		return true;


		
	showLoading(dest);

	var params = Form.serialize(theForm);	
	var url = theForm.action;
	
	if(url == "")
		url = document.location.href;	
	
	new Ajax.Updater(resultDiv, url, 
		{
			parameters: params, 
			asynchronous:true,
			evalScripts:true, 
			onComplete:function(response) { formPostOnComplete(response, dest); }, 
			onFailure:function(response) { formPostOnError(response, dest); },
			onException:function(ajaxReq, exception) { formPostOnException(ajaxReq, exception, dest) }
		});
	
	// to stop the onSubmit event
	return false;
	
}

/**
 * formPostOnComplete
 * Called on completion of the Asynchronous call
 * @param reponse XMLHttpRequest object
 * @param resultDiv id or object reference to the target DIV container
 */
function formPostOnComplete(response, resultDiv) {
	
	hideLoading(resultDiv);
}

/**
 * formPostOnError
 * Called on Failure of the Asynchronous call
 * @param reponse XMLHttpRequest object
 * @param resultDiv id or object reference to the target DIV container
 */
function formPostOnError(response, resultDiv) {
	
	var msg = "formPostError: error opening " + response.channel.name + ": " + response.statusText;
	showError(resultDiv, msg);
}

/**
 * formPostOnException
 * Called on a Asynchronous call Exception
 * @param reponse Ajax Request object
 * @param exception being thrown
 * @param resultDiv id or object reference to the target DIV container
 */
 function formPostOnException(ajaxReq, exception, resultDiv) {
	
	throw exception
	
	var msg = "formPostException: " + exception.name
	showError(resultDiv, msg);
}


/**
 * openLink
 * Makes the asynchronous call to the server, displaying the produced
 * html into the given container
 * Displays the "loading" msg in the middle of the container
 * @param anchor "A" object to be opened
 * @param resultDiv id or object reference to the target DIV container
 * @return false
 */
function openLink(anchor, resultDiv) {
	
	var dest = null;
		
	if(typeof(resultDiv) == "string")
		dest = $(resultDiv);
	else
		dest = resultDiv
			
		
	// undefined container falls into normal link opening
	if(dest == null || typeof(dest) == "undefined")
		return true;
		
		
	if(typeof(anchor) == "string")
		url = anchor
	else
		url = anchor.href;
		
	showLoading(dest);
	
	new Ajax.Updater(dest, url, 
		{
			method: 'get',
			asynchronous:true, 
			evalScripts:true, 
			onComplete:function(response) { openLinkOnComplete(response, dest); }, 
			onFailure:function(response) { openLinkOnError(response, dest); },
			onException:function(ajaxReq, exception) { openLinkOnException(ajaxReq, exception, dest) }
		});
	
	// to stop the onclick event
	return false;	
}

/**
 * formPostOnComplete
 * Called on completion of the Asynchronous call
 * @param reponse XMLHttpRequest object
 * @param resultDiv id or object reference to the target DIV container
 */
function openLinkOnComplete(response, resultDiv) {
	
	hideLoading(resultDiv);
}

/**
 * openLinkOnError
 * Called on Failure of the Asynchronous call
 * @param reponse XMLHttpRequest object
 * @param resultDiv id or object reference to the target DIV container
 */
function openLinkOnError(response, resultDiv) {
	
	var msg = "openLinkError: error opening " + response.channel.name + ": " + response.statusText;
	showError(resultDiv, msg);
}

/**
 * openLinkOnException
 * Called on a Asynchronous call Exception
 * @param reponse Ajax Request object
 * @param exception being thrown
 * @param resultDiv id or object reference to the target DIV container
 */
function openLinkOnException(ajaxReq, exception, resultDiv) {
	
	var msg = "openLinkException: " + exception.name
	showError(resultDiv, msg);
}






/**
 * showLoading
 * Displays a "loading" message in the middle of the container and blocks
 * all posible clicks by placing a semi-transparent DIV above de container
 * It creates a new message and blocker for each DIV that is given. If the
 * DIV already exists, it is resized, repositioned and displayed. 
 * @param resultDiv object reference to the target DIV container to be load
 */
function showLoading(dest) {
	
	var loading = $(dest.id + "Loading");
	var msg = $(dest.id + "LoadingMessage");

	var cumulativeOffset = Position.cumulativeOffset(dest);

	var top = cumulativeOffset[1];
	var left = cumulativeOffset[0];
	var width = dest.offsetWidth;
	var height = dest.offsetHeight; 		
		
	if(typeof(loading) == "undefined") {
			
		var id = dest.id + "Loading";
		var styleLoading = "top: " + top + "px; left: " + left + "px; width: " + width + "px; height: " + height + "px";
		var styleMessage = "top: " + parseInt(height/2 - 10 + top) + "px; left: " + parseInt(width/2 - 50 + left) + "px";
		
		var html = 	"<div class='AJASloading' id='" + id + "' style='" + styleLoading + "'></div>" +
					"<div class='AJASloadingMessage' id='" + id + "Message' style='" + styleMessage + "'> Cargando </div>"

		
		new Insertion.After(dest, html);	
	}
	else {
		
		loading.style.width = width;
		loading.style.height = height;
		
		msg.style.top = parseInt(height/2 - 10 + top)
		msg.style.left = parseInt(width/2 - 50 + left);
		
		Element.show(loading);
		Element.show(msg);	
	}
}

/**
 * hideLoading
 * Just hides the "loading" message and the click blocker
 * @param resultDiv object reference to the target DIV container just loaded
 */
function hideLoading(dest) {
	
	try {
		Element.hide(dest.id + "Loading");
		Element.hide(dest.id + "LoadingMessage");	
	}
	catch(e) { }
}

/**
 * showError
 * Inserts an error message on top of the target DIV container
 * @param resultDiv object reference to the target DIV container being loaded
 */
function showError(dest, msg) {
	
	var html = "<div class='AJASError'>" + msg + "</div>"	
	new Insertion.Top(dest, html);
	
	hideLoading(dest);
}

