
/*
 * JS code:
 * @author Alastair Pursch [alastair < at > pursch < dot > co < dot > za]
 * @copyright 2009
 * @package inc
 * @subpackage js
 */

/*
* 
* This file is to be included in the project.
* It's purpose is to:
* - perform any config/setup necessary (e.g. jQuery AJAX, datepicker, etc.)
* - define any utility functions used on more than one page
* 
* */


/*
 * =====================================================================
 * UTILITY FUNCTIONS
 * =====================================================================
 */

function addRollover(ele){
	if(!($(ele).hasClass("rollover"))){
		$(ele).addClass("rollover");
	}
}

function removeRollover(ele){
	if(($(ele).hasClass("rollover"))){
		$(ele).removeClass("rollover");
	}
}

//TODO: convert the following functions to jqueryness	
	
function addClickable(ele){
	if (!hasClass(ele,'clickableRow')) {
		ele.className += ' clickableRow';
	}
	return true;
}

function removeClickable(ele){
	if (hasClass(ele,'clickableRow')) {
		ele.className = ele.className.replace(cssRegex('clickableRow'),' ');
	}
	return true;
}

function hasClass(ele, strClass) {
	return ele.className.match(cssRegex(strClass));
}

function cssRegex(strClass) {
	return new RegExp('(?:\\s|^)' + strClass + '(?:\\s|$)');
}


/*	Reset the HTML of a parent (enclosing) element.  All children's bindings
	will also be lost.
	Used mainly for clearing 'file' type inputs (in IE, which prevents
	manipulation for security reasons)
	NB: Provide the PARENT id in file input example above
	*/
function resetHTML(id) {
    $('#'+id).html($('#'+id).html());
}


/*
 * =====================================================================
 * AJAX
 * =====================================================================
 */

//Return boolean: whether the given HTML fragment contains application error message
function hasError(strHtml)
{
	return ($(strHtml).find('div').hasClass('errorMsg'));
}

//Return boolean: whether the given HTML fragment contains application info message
function hasInfo(strHtml)
{
	return ($(strHtml).find('div').hasClass('infoMsg'));
}

//Return boolean: whether the given HTML fragment contains application message (info or error)
function hasMessage(strHtml)
{
	return (hasError(strHtml) || hasInfo(strHtml));
}

//Return boolean: whether the given HTML fragment contains 'data' div containing data
function hasData(strHtml)
{
	var strData = getData(strHtml);
	if(strData == null){
		return false;
	}else{
		return (strData.length > 0);
	}
}

//Return DOM fragment: the 'messages' portion (if any) extracted from the HTML fragment
//- if message(s): returns html string
//- if empty message container: returns empty string
//- if no message container: returns null
function getMessage(strHtml)
{
	//Wrap the supplied fragment in a div to ensure we can search top level elements as well
	//Then search for the 'messages' container and extract the contents (messages)
	return $('<div></div>').html(strHtml).find("div[id='messages']").html();	
}

//Return DOM fragment: the 'data' portion (if any) extracted from the HTML fragment
//- if data: returns html string
//- if empty data container: returns empty string
//- if no data container: returns null
function getData(strHtml)
{
	//Wrap the supplied fragment in a div to ensure we can search top level elements as well
	//Then search for the 'data' container and extract the contents (data)
	return $('<div></div>').html(strHtml).find("div[id='data']").html();	
}

//Copy any 'messages' DOM fragment from the given HTML fragment to the specified container DOM element
//Actions:
//"replace" (default):	replace element contents with 'messages';
//"prepend":			prepend to element contents;
//"append":				append to element contents
function copyMessage(strHtml, destinationEleId, action)
{
	var strMsg = getMessage(strHtml);
	
	switch(action){
	case "append":
		$('#'+destinationEleId).append(strMsg);
		break;
	case "prepend":
		$('#'+destinationEleId).prepend(strMsg);
		break;
	case "replace":
	default:	
		$('#'+destinationEleId).html(strMsg);	
		break;
	}
}

//Copy any 'data' DOM fragment from the given HTML fragment to the specified container DOM element
//Actions:
//"replace" (default):	replace element contents with 'data';
//"prepend":			prepend to element contents;
//"append":				append to element contents
function copyData(strHtml, destinationEleId, action)
{
	var strData = getData(strHtml);
	
	switch(action){
	case "append":
		$('#'+destinationEleId).append(strData);
		break;
	case "prepend":
		$('#'+destinationEleId).prepend(strData);
		break;
	case "replace":
	default:	
		$('#'+destinationEleId).html(strData);
		break;
	}
}

/* Creates a loadingImage within a parent element */
function createloadingImage(parentEleId)
{
	return $('<div></div>').addClass("ajaxLoadingImage").prependTo('#'+parentEleId);	
}

/* Destroys the given loading image */
function destroyloadingImage(loadingImage)
{
	//safety: loadingImage may be null
	try	{
		//remove the loadingImage from the DOM
		loadingImage.remove();		
	} catch (e) { }
}

//AJAX DEFAULTS
//(Most jQuery defaults are suitable for our needs and can be used as is - no need to include here)
$.ajaxSetup({
	//Can optionally specify the element ID in which a loading image will be created.
	//Loading image default behaviour is to be destroyed at AJAX request completion. 
	loadingImageId: null,
	//Can optionally provide a (pre-setup) loading image.
	//Loading image default behaviour is to be destroyed at AJAX request completion.
	loadingImage: null,
	type: 'POST',
    dataType: 'html',
    //Default AJAX request timeout is 10 secs
    timeout: 10000,
    contentType: 'application/x-www-form-urlencoded',
    //TODO: Convert this into an app message
    //error: function(XMLHttpRequest, textStatus, errorThrown){
    //    alert('Error loading HTML document' + textStatus);		       
    //},
    beforeSend: function(XMLHttpRequest){
		//Add this directive to the request so server knows not to wrap with main page template
		this.data += '&_ajaxRequest=1';
		//If no loading bar object supplied, attempt to create one
		if(!this.loadingImage){
			//If element ID supplied for loading bar, create one
			if(this.loadingImageId){
				this.loadingImage = createloadingImage(this.loadingImageId);
			}
		}
	},
	complete: function(){
		//If we have a loading bar, destroy it and remove it from these options
    	if(this.loadingImage){
    		destroyloadingImage(this.loadingImage);
    		this.loadingImage = null;
    	}
    	
    	//Run any other JS functions necessary (e.g. clickableRows, etc.)
    	runAfterAJAXCall();
    }
});

//Run any JS functions necessary (e.g. clickableRows, etc.) after an AJAX call
//To be overridden locally in each project
function runAfterAJAXCall()
{	
}



