/*
	Project: Application for displaying country dropdown list that populates state/province dropdown-list on-change. state/province populates
			city dropdown-list if changed.
	Author: Chigozie (The Cat) Nduanya 
	Date:  February 04, 2009 
	Filename: processor.js
	File-Type: JavaScript Document
*/

/*
Functions
----------*/
/*
 author:   chigozie (the cat) nduanya
 function: cities(): returns the result of server-side processing for the task get_cities.
 					 tested and passed.*/
function cities()
{//Opening brace for the cities function
	if(request.readyState==4) 
	{
		if(request.status==200) 
		{//Opening brace - Request successfully processed
			var result=request.responseText, parentObject=document.getElementById('tbl_countries').rows[2].cells[0];
			writeText(parentObject,'City:');
			parentObject=document.getElementById('tbl_countries').rows[2].cells[1];
			with(parentObject)
			{
				appendChild(newDropdownList('cmb_cities','~Select One|'+result,currentValue=''));
				getElementsByTagName('select')[0].onchange=function(){getDealers(this.value);};
			}
		}//Closing brace - Request successfully processed
		else
			out('We are experiencing some technical diffculties. Please try again later.');
	}
}//Closing brace for the cities function

/* author:   chigozie (the cat) nduanya
   function: convertStringToArray(): converts a string of values concatenated with a character, into an array. requires an array-string 
   			 and the character to split string on.
			 tested and passed.*/
function convertStringToArray(arrayString,characterToSplitOn)
{//Opening brace for the convertStringToArray function
	this.properties=[];
	this.properties=arrayString.split(characterToSplitOn);
	return this.properties;
}//Closing brace for the convertStringToArray function

/*
 author:   chigozie (the cat) nduanya
 function: createRequest(): iterates through an array of image-sources and captions; this function then updates the slideshow-image with the current source,
						    while updating its caption with the current caption. expects an image-source array and an image-caption array to be both populated.
							tested and passed.*/
function createRequest()
{//Opening brace for the createRequest function
	try
	{
		request=new XMLHttpRequest();
	}
	catch(trymicrosoft)
	{
		try
		{
			request=new ActiveXObject('Msxml2.XMLHTTP');
		}
		catch(othermicrosoft)
		{
			try
			{
				request=new ActiveXObject('Microsoft.XMLHTTP');
			}
			catch(failed)
			{
				request=null;
			}
		}
	}
	if(request==null)
		out('Error creating request object!');	
}//Closing brace for the createRequest function

/*
 author:   chigozie (the cat) nduanya
 function: countries(): returns the result of server-side processing for the task get_countries
						tested and passed.*/
function countries()
{//Opening brace for the countries function
	if(request.readyState==4) 
	{
		if(request.status==200) 
		{//Opening brace - Request successfully processed
			var result=request.responseText;
			document.getElementById('txt_properties').value=result;
		}//Closing brace - Request successfully processed
		else
			out('We are experiencing some technical diffculties. Please try again later.');
	}
}//Closing brace for the countries function

/*
 author:   chigozie (the cat) nduanya
 function: dealers(): returns the result of server-side processing for the task get_dealers.*/
function dealers(){
	if(request.readyState==4){
		if(request.status==200){
			var result=request.responseText, parentObject=document.getElementById('tbl_countries'), dealerRows=convertStringToArray(result,'|'),
			numberOfRows=dealerRows.length-1, numberOfCells=convertStringToArray(dealerRows[0],'~').length-1, dealerInfo, inputField;
			
			//1) i command you to build an extra cell below for the dealer info that's just coming in from server side and insert a table into it, my son.
			if(document.getElementById('div_dealer_info')==null)
				document.forms[0].appendChild(newDiv('div_dealer_info'));
			
			parentObject=document.getElementById('div_dealer_info');			
			deleteContent(parentObject);
			with(parentObject){
				appendChild(newTable('tbl_dealers',numberOfRows,numberOfCells));
				style.marginTop='15px';
			}
			
			//2) reassign the parent-object and populate the cells with info, bitch!
			parentObject=document.getElementById('tbl_dealers');
			with(parentObject){
				cellPadding=2;
				cellSpacing=1;
				with(style){
					background='black';
					fontFamily='Tahoma';
					fontSize='12px';
				}
			}
			
			for(var x=0;x<parentObject.rows[0].cells.length;x++){
				with(parentObject.rows[0].cells[x].style){
					fontWeight='bold';
					textAlign='center';
				}
			}			
			
			for(var x=0;x<parentObject.rows.length;x++){
				dealerInfo=convertStringToArray(dealerRows[x],'~');
				for(var y=0,z=1;y<parentObject.rows[x].cells.length;y++,z++){
					writeText(parentObject.rows[x].cells[y],(dealerInfo[z]=='')?' ':dealerInfo[z]);
					parentObject.rows[x].cells[y].style.background='white';
					if(y==1){
						inputField=document.createElement('input');
						with(inputField){
							id='txt_dealer_'+y;
							type='hidden';
							value=dealerInfo[0];
						}
						parentObject.rows[x].cells[y].appendChild(inputField);
					}
				}
			}
		}//request successfully processed
		else
			out('We are experiencing some technical diffculties. Please try again later.');
	}
}//the dealers function ends here

/*
 author:   chigozie (the cat) nduanya
 function: deleteContent(): deletes all the child nodes from the specifed parent object. requires a parent object.
							tested and passed.*/
function deleteContent(parentObject)
{//Opening brace for the deleteContent function
	while(parentObject.hasChildNodes())parentObject.removeChild(parentObject.lastChild);
}//Closing brace for the deleteContent function

/*
 author:   chigozie (the cat) nduanya
 function: get(): performs the server-side call that returns query for specified task.
 				  tested and passed.*/
function get(task,properties)
{//Opening brace for the get function
	var url='processor.php?task='+escape(task)+'&properties='+escape(properties);	
	createRequest();
	if(task=='get_states_and_provinces')
	{
		with(request)
		{
			open('POST',url,true);
			onreadystatechange=statesAndProvinces;
			send(null);
		}
	}
	else if(task=='get_cities')
	{
		with(request)
		{
			open('POST',url,true);
			onreadystatechange=cities;
			send(null);
		}
	}
	else if(task=='get_dealers')
	{
		with(request)
		{
			open('POST',url,true);
			onreadystatechange=dealers;
			send(null);
		}
	}
}//Closing brace for the get function

/*
 author:   chigozie (the cat) nduanya
 function: getCities(): returns a list of cities from server-side for the calling state-province id.
 					    tested and passed.*/
function getCities(stateProvinceId)
{//Opening brace for the getCities function
	deleteContent(parentObject=document.getElementById('tbl_countries').rows[2].cells[1]);
	if(document.getElementById('div_dealer_info')!=null)deleteContent(document.getElementById('div_dealer_info'));
	get('get_cities',cityTable+'|'+stateProvinceId);
}//Closing brace for the getCities function

/*
 author:   chigozie (the cat) nduanya
 function: getDealers(): returns a list of cities from server-side for the calling state-province id.
 					    tested and passed.*/
function getDealers(cityId){
	get('get_dealers','dealers|'+cityId);
}//Closing brace for the getDealers function

/*
 author:   chigozie (the cat) nduanya
 function: getCountries(): initiates server-side processing for the task get_countries.
						   tested and passed.*/
function getCountries(countryTable)
{//Opening brace for the getCountries function
	createRequest();
	var url='processor.php?task=get_countries&properties='+escape(countryTable);	
	with(request)
	{
		open('POST',url,true);
		onreadystatechange=countries;
		send(null);
	}	
}//Closing brace for the getCountries function

/*
 author:   chigozie (the cat) nduanya
 function: getStatesAndProvinces(): returns a list of states and provinces from serverside for the calling country-id.
 									tested and passed.*/
function getStatesAndProvinces(countryId)
{//Opening brace for the getStatesAndProvinces function
	var parentObject=document.getElementById('tbl_countries').rows[2].cells[1];
	deleteContent(document.getElementById('tbl_countries').rows[1].cells[1]);
	if(document.getElementById('div_dealer_info')!=null)deleteContent(document.getElementById('div_dealer_info'));
	if(parentObject.getElementsByTagName('select').length>0)
	{//Opening brace - Do this only if there exists dropdown-list for cities
		writeText(document.getElementById('tbl_countries').rows[2].cells[0],'');
		deleteContent(parentObject);
	}//Closing brace - Do this only if there exists dropdown-list for cities	
	get('get_states_and_provinces',stateProvinceTable+'|'+countryId);
}//Closing brace for the getStatesAndProvinces function

/*
 author:   chigozie (the cat) nduanya
 function: getStructure(): generates the basic structure that contains this application.
 						   tested and passed.*/		
var getStructureCounter=0, getStructureTimer;
function getStructure()
{//Opening brace for the getStructure function
	if(getStructureCounter==1)
	{
		clearTimeout(getStructureTimer);
		getStructureCounter=0;
		var tableObject=document.getElementById('tbl_countries'), rowObject, cellObject;
		rowObject=tableObject.rows[0];
		writeText(rowObject.cells[0],'Country:');
		cellObject=rowObject.cells[1];	
		with(cellObject)
		{
			appendChild(newDropdownList('cmb_countries','~Select One|'+document.getElementById('txt_properties').value,currentValue=''));
			getElementsByTagName('select')[0].onchange=function(){getStatesAndProvinces(this.value);};
		}
	}
	else
	{
		getStructureTimer=setTimeout('getStructure()',500);
		getStructureCounter++;
	}
}//Closing brace for the getStructure function

/*
 author:   chigozie (the cat) nduanya
 function: newDropdownList(): generates a new dropdown list based on the properties specified. requires an element-id, an array of properties, a classIndex,
 							  and a current-value (used to set the selected index). i expect that the last index of properties will be null so i omit it
							  from my iteration. i also expect that you would've appended the first index of this dropdown-list to its properties before 
							  sending it over to me.
							  tested and passed.*/	
function newDropdownList(elementId,properties,currentValue)
{//Opening brace for the newDropdownList function
	var elementObject=document.createElement('select'), optionObject, optionArray=convertStringToArray(properties,'|'), propertiesArray;
	if(elementId!='')elementObject.id=elementObject.name=elementId;
	//generate the options for this dropdown-list
	for(var x=0;x<optionArray.length-1;x++)
	{//Opening brace - The loop that generates the options
		propertiesArray=convertStringToArray(optionArray[x],'~');
		optionObject=document.createElement('option');
		optionObject.value=propertiesArray[0];
		writeText(optionObject,propertiesArray[1]);
		if(currentValue==propertiesArray[0])optionObject.selected=true;
		elementObject.appendChild(optionObject);
	}//Closing brace - The loop that generates the options
	
	return elementObject;
}//Closing brace for the newDropdownList function

/* author:   chigozie (the cat) nduanya
   function: newDiv(): a new div element is created, identified and inserted into the specified parent object. requires a parent object and an id for the new div.*/
function newDiv(elementId)
{//Opening brace for the newDiv function
	var divObject=document.createElement('div');
	if(elementId!='')divObject.id=elementId;
	return divObject;
}//Closing brace for the newDiv function

function newTable(tableId,tableRows,tableCells)
{//Opening brace for the newTable function
	var tableObject=document.createElement('table'), rowObject, cellObject;//create a enw table object
	
	if(tableId!='')tableObject.id=tableId;//set the id, if applicable
	for(var x=0;x<tableRows;x++)
	{//Opening brace - The loop that generates the table rows
		rowObject=tableObject.insertRow(x);
		for(var y=0;y<tableCells;y++){
			cellObject=rowObject.insertCell(y);
		}
	}//Closing brace - The loop that generates the table rows
	
	return tableObject;
}//Closing brace for the newTable function

/*
 author:   chigozie (the cat) nduanya
 function: out(): outputs a message to the user. requires a message to output.
		 		  tested and passed.*/
function out(message)
{//Opening brace for the out function
	alert(message);
}//Closing brace for the out function

/*
 author:   chigozie (the cat) nduanya
 function: processor(): initializes the application-requirements and generates the structure for the application. requires a parent-object
 					    tested and passed.*/
function processor()
{//Opening brace for the processor function
	var properties=[], inputObject=document.createElement('input');		
	with(inputObject)
	{
		type='hidden';
		id='txt_properties';
	}	
	with(parentObject)
	{
		appendChild(inputObject);
		appendChild(newTable('tbl_countries',3,2));
	}	
	getCountries(countryTable);
	getStructure();	
}//Closing brace for the processor function

/*
 author:   chigozie (the cat) nduanya
 function: statesAndProvinces(): returns the result of server-side processing for the task get_states_and_provinces; result is then generated as a dropdown-list.
 								 tested and passed.*/
function statesAndProvinces()
{//Opening brace for the statesAndProvinces function
	if(request.readyState==4) 
	{
		if(request.status==200) 
		{//Opening brace - Request successfully processed
			var result=request.responseText, parentObject=document.getElementById('tbl_countries').rows[1].cells[0];
			writeText(parentObject,'State/Prov:');
			parentObject=document.getElementById('tbl_countries').rows[1].cells[1];
			with(parentObject)
			{
				appendChild(newDropdownList('cmb_states_and_provinces','~Select One|'+result,currentValue=''));
				getElementsByTagName('select')[0].onchange=function(){getCities(this.value);};
			}
		}//Closing brace - Request successfully processed
		else
			out('We are experiencing some technical diffculties. Please try again later.');
	}
}//Closing brace for the statesAndProvinces function

/*
 author:   chigozie (the cat) nduanya
 function: writeText(): overwrites the text in an existing parent object with the specified text. requires an element-object and the 
						text to deposit in the element. 
						tested and passed.*/
function writeText(elementObject,text) 
{//Opening brace for the writeText function
	if(elementObject!=null) 
	{//Opening brace - Error checking...
		deleteContent(elementObject); 
		elementObject.appendChild(newNode=document.createTextNode(text));
	}//Closing brace - Error checking...
}//Closing brace for the writeText function
