//j0zf 2006.3.12
//ajax.parallel.js
//my normal ajax.js library barfed on parallel requests because there was only 1 request object
/**
 * METHOD I:   ajax_get_request( ajax_url, ajax_handler, set_loading_id, forget_previous_requests )
 *	-- this method uses XMLHttpRequest() and processes commands
 *
 * METHOD II:  ajax_post_request( ajax_url, ajax_data, ajax_handler, set_loading_id, forget_previous_requests )
 *	-- this method uses XMLHttpRequest() and processes commands
 *	-- this method is better than ajax_get_request() when submitting a large amount of data
 *	-- data should be in url encoded format with escape()'d values ( e.g. variable1=value1&another_var=someother+value )
 *
 * METHOD III: ajax_call_js( unique_element_id, src_url, allow_reload_flag )
 *	-- this method immediatly runs as javascript the returned data
 *
 * AJAX CGI RETURN COMMANDS:
 *	-- Format:  ajax command|cgi returned ajax data
 *	-- by default the "ajax command" is just the "element id" who's innerHTML will be replaced 
 *	   by the "cgi returned ajax data" text or html.
 *
 * SPECIAL CGI RETURN COMMANDS:
 *	-- ajax_error : reports error string
 *		* if the "ajax_error" element id is available then it will replace it's innerHTML with 
 *		  the error text "cgi returned ajax data".
 *		* if the "ajax_error" element id is not available then it will do an alert('cgi returned ajax data / error text');
 *	-- ajax_run_script : will eval('cgi returned ajax data / javascript');
 *
 */

//USED TO SYNCHRONIZE THE PARALLEL ARRAYS
var ajax_requests_count = 0;

//AN ARRAY THAT CONTAINS THE REQUESTED AJAX OBJECTS
var ajax_requests = new Array();

//KEEP TRACK OF HANDLERS SO WE DISPATCH THE CORRECT ONE
//parallel array to ajax_requests
var ajax_handlers = new Array();

function ajax_createRequestObject( ajax_handler ) 
{
	var i = ajax_requests_count++;
    var ajax_http;
    var browser = navigator.appName;
    
	//CREATE THE AJAX REQUEST OBJECT
	if( browser == "Microsoft Internet Explorer" && window.ActiveXObject )
	{
        ajax_http = new ActiveXObject("Microsoft.XMLHTTP");
    }
	else
	{
        ajax_http = new XMLHttpRequest();
    }
	
	//SETUP THE HANDLER DISPATCHER
	ajax_http.onreadystatechange = ajax_handler_dispatcher;
	
	//ADD THE HANDLER
	if( ajax_handler == null )
	{
		ajax_handlers[i] = ajax_handler_default;
	}
	else
	{
		ajax_handlers[i] = ajax_handler;
	}
	
	//ADD THE REQUEST OBJECT
	ajax_requests[i] = ajax_http;
    return ajax_http;
}

function ajax_handler_dispatcher()
{
	var i = 0;
	var ajax_http = null;
	var ajax_handler = null;
	
	if( ajax_requests_count < 1 ) return;
	
	for( i = (ajax_requests_count - 1); i >= 0; i-- )
	{
		if( ajax_requests[i] && ajax_handlers[i] && ajax_requests[i].readyState == 4 )
		{
			ajax_http = ajax_requests[i];
			ajax_requests[i] = null;
			ajax_handler = ajax_handlers[i];
			ajax_handlers[i] = null;
			
			if ( ajax_http.status == 200 ) 
			{
				//alert( 'RESPONSE TEXT:[' + ajax_http.responseText + ']' );
				ajax_handler( ajax_http );
			} 
			else 
			{
				ajax_report_error( 'Ajax Error - Status Code: "' + ajax_http.status + '" Status Text: "' + ajax_http.statusText + '".' );
			}
		}
	}	
}

//FORGET ALL PREVIOUS AJAX REQUESTS
function ajax_forget_requests()
{
	ajax_requests_count = 0;
	ajax_requests = new Array();
	ajax_handlers = new Array();
}

//VERY SIMPLE TO USE DEFAULT HANDLER
//CUSTOM HANDLERS CAN BE SPECIFIED WHEN MAKING THE REQUESTS
//Make requests by:
//  ajax_get_request( ajax_url, ajax_handler, set_loading_id, forget_previous_requests ) 
//  or
//  ajax_post_request( ajax_url, ajax_data, ajax_handler, set_loading_id, forget_previous_requests ) 
function ajax_handler_default( ajax_http ) 
{
	var sep_loc = ajax_http.responseText.indexOf( '|' );
	var response_name = '';
	var response_value = '';
	
	if( sep_loc > 0 ) 
	{
		response_name = ajax_trim_str( ajax_http.responseText.substr( 0, sep_loc ) );
		response_value = ajax_http.responseText.substr( 1 + sep_loc );
		
		if( response_name == 'ajax_error' )
		{
			//REPORT THE ERROR
			ajax_report_error( response_value );
		}
		else if( response_name == 'ajax_run_script' )
		{
			ajax_run_script( response_value );
		}
		else
		{
			//WRITE THE RESPONSE TO THE SPECIFIED ELEMENT
			if( ajax_set_value( response_name, response_value ) )
			{
				ajax_clear_error();
			}
			else
			{
				ajax_report_error( 'Error: Ajax Element Not Found (' + response_name + ').' );
			}
		}
	}
	else
	{
		ajax_report_error( 'Error: Invalid Ajax Response.' );
	}
}

function ajax_report_error( str )
{
	var ajerr = document.getElementById('ajax_error');
	if( ajerr )
	{
		ajerr.innerHTML = str;
	}
	else
	{
		alert( str );
	}
}

function ajax_clear_error()
{
	var ajerr = document.getElementById('ajax_error');
	if( ajerr )
	{
		ajerr.innerHTML = "";
	}
}

function ajax_run_script( str )
{
	eval(str);
}

function ajax_trim_str( str ) 
{
   str = str.replace(/^\s+/, '');
   str = str.replace(/\s+$/, '');
   return str;
}

/**
 * SET LOADING IMAGE
 */
function ajax_set_loading( loading_id )
{
	loading_id = document.getElementById( loading_id );
	if(loading_id)
	{
		loading_id.innerHTML = '<div class="ajax_loading_icon"><span class="ajax_loading_icon">Loading...</span></div>';
	}
}

/**
 * GET AN ELEMENTS VALUE.... Never mind the element's type...
 * -- add types as needed..
 * -- Not currently supported:
 *		- radio buttons
 *		- select tags with "multselect" enabled
 *		- and more...
 */
function ajax_get_value( element_id )
{
	var e = document.getElementById( element_id );
	var v = '';
	if( !e ){ return null; }
	
	switch( e.tagName.toUpperCase() )
	{
		case 'INPUT':
			switch( e.type.toUpperCase() )
			{
				case 'TEXT':
					v = e.value;
					break;
				case 'HIDDEN':
					v = e.value;
					break;	
				case 'CHECKBOX':
					v = ( e.checked ? e.value : '' );
					break;
				default:
					v = e.value;
					break;
			}
			break;
		case 'TEXTAREA':
			v = e.value;
			break;
		case 'SELECT':
			v = e.options[ e.selectedIndex ].value;
			break;
		default:
			v = e.innerHTML;
			break;
	}
	
	return v;
}

/**
 * SET AN ELEMENTS VALUE.... Never mind the element's type...
 * -- add types as needed..
 */
function ajax_set_value( element_id, v )
{
	var e = document.getElementById( element_id );
	if( !e ){ return null; }
	
	switch( e.tagName.toUpperCase() )
	{
		case 'INPUT':
			switch( e.type.toUpperCase() )
			{
				case 'TEXT':
					e.value = v;
					break;
				default:
					e.value = v;
					break;
			}
			break;
		default:
			e.innerHTML = v;
			break;
	}
	
	return v;
}

/**
 * CALL A JAVASCRIPT FILE
 *	-- yes this can have a PHP or other CGI extension ( .js not required )
 *	-- Output will be ran as Javascript
 *
 *	unique_element_id : mangle away.. make it origninal to the page
 *	allow_reload_flag : if true then unique_element_id may be replaced by a new script load
 *
 */
function ajax_call_js( unique_element_id, src_url, allow_reload_flag )
{
	if( !allow_reload_flag && document.getElementById( unique_element_id ) )return;
	
	var head = document.getElementsByTagName('head').item(0);
	var script = document.createElement('script');
	script.src = src_url;
	script.type = 'text/javascript';
	script.language = 'javascript';
	script.id = unique_element_id;
	head.appendChild(script);
}

/**
 * USE "GET" METHOD TO MAKE HTTP REQUEST
 * ajax_handler : This is the function which will handle the request when retured as success
 * set_loading_id : (optional) This is the element id who's innerHTML will be replaced by the loading icon 
 * forget_previous_requests : Destroys the handler queue before making request
 *
 */
function ajax_get_request( ajax_url, ajax_handler, set_loading_id, forget_previous_requests ) 
{
	if( !ajax_handler ){ ajax_report_error( 'Error: Invalid Ajax Handler Javascript Function.' ); return; }
	if( forget_previous_requests == true ){ ajax_forget_requests(); }
	if( set_loading_id && set_loading_id != '' ){ ajax_set_loading( set_loading_id ); }
	
	var ajax_http = ajax_createRequestObject( ajax_handler );
	
    ajax_http.open( 'get', ajax_url );
	ajax_http.send( null );
}

/**
 * USE "POST" METHOD TO MAKE HTTP REQUEST
 * ajax_data : Contains the POST data.
 *	-- this method is better than ajax_get_request() when submitting a large amount of data
 *	-- data should be in url encoded format with escape()'d values ( e.g. variable1=value1&another_var=someother+value )
 * ajax_handler : This is the function which will handle the request when retured as success
 * set_loading_id : (optional) This is the element id who's innerHTML will be replaced by the loading icon 
 * forget_previous_requests : Destroys the handler queue before making request
 *
 */
function ajax_post_request( ajax_url, ajax_data, ajax_handler, set_loading_id, forget_previous_requests )
{
	if( !ajax_handler ){ ajax_report_error( 'Error: Invalid Ajax Handler Javascript Function.' ); return; }
	if( forget_previous_requests == true ){ ajax_forget_requests(); }
	if( set_loading_id && set_loading_id != '' ){ ajax_set_loading( set_loading_id ); }
	
	var ajax_http = ajax_createRequestObject( ajax_handler );
	
    ajax_http.open( 'post', ajax_url );
    ajax_http.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
	ajax_http.send( ajax_data );
}
