var TableClass = "listTableBack";				// TYPE OF TABLE THAT IS ACTED UPON.
var FontClass = "listTableHeadingText";			// TYPE OF CLASS TO LOOK FOR WHEN LOOKING FOR SORTING OPERATIONS
var HeadingClass = "listTableHeadingBack";		// CLASS TO LOOK FOR WHEN CHECKING FOR SORTING
var filterType = "invert";						// FILTER TYPE TO USE

// INTERNAL VARIABLE
var Tracker = new Array();
var TrackPos = 0;

var PrevCtrl = false;

var CurrSortOrder = 'UP';
var OldCursor;

// CYCLES THROUGH THE LIST OF ELEMENTS THAT ARE SELECTED (??) AND CHECKS IF 'ELEMENT' IS THERE
function InSelectedArray(Element) {
	var Counter;
	var Found = false;
	
	//CHECKS TO SEE IF AN ELEMENT IS ALREADY SELECTED
	for (Counter = 0; Counter < TrackPos; Counter++) {
		//ASSUMES THAT NO TWO CELLS HAVE THE SAME HTML INSIDE THEM
		if (Tracker[Counter] == Element)
			Found = true;
	}

	// GIVE CALLING FUNCTION THE RESULT
	return Found;
}

// ADD AN ELEMENT TO THE LIST OF SELECTED ITEMS
function AddElement(Element) {
	var Counter;
	
	if (Element != null) {
		// CHECK IF THERE IS A CHECKBOX IN THE CELL, AND SELECT IT IF SO.
		var Found = false;
		if ((Element.children[0] != null) && (Element.children[0].tagName == 'INPUT') && ((Element.children[0].type == 'checkbox') || (Element.children[0].type == 'radio'))) {
				Element.children[0].checked  = true;
				Found = true;
		}
		
		//CHANGE THE ELEMENT FILTER REGARDLESS;
		if (!Found) {
			Element.style.filter = filterType;
		}		
		//CHECK TO SEE IF THE ELEMENT EXISTS IN THE ARRAY ALREADY;
		if (!InSelectedArray(Element)) 	{
			//IF NOT, ADD THE ELEMENT
			Tracker[TrackPos] = Element;
			TrackPos++;
		}
		 else
			RemoveElement(Element);
	}
}

// REMOVE AN ELEMENT FROM THE LIST OF SELECTED ITEMS
function RemoveElement(Element) {
	if (Element != null) {
		// FIRST FIND THE THING
		var ElCounter;
		
		// CYCLE THROUGH	
		for (ElCounter = 0; ElCounter < TrackPos; ElCounter++) {				
			// KILL IF FOUND
			if (Element == Tracker[ElCounter]) {
				// RESET ATTRIBUTES
				// CHECK IF THERE IS A CHECKBOX IN THE CELL, AND SELECT IT IF SO.
				if ((Element.children[0].tagName == 'INPUT') && ((Element.children[0].type == 'checkbox') || (Element.children[0].type == 'radio')))
						Element.children[0].checked  = false;
		
				//CHANGE THE ELEMENT FILTER REGARDLESS;
				Element.style.filter = '';
				
				// KILL THE MEMORY REFERENCE
				Tracker[ElCounter] = Tracker[TrackPos-1];
				TrackPos--;				
			}
		}
	}
}

// SELECT A LINE OF A TABLE
function ApplySelect(ElementIn) {
	var ShiftKeyVar;

	// CHECK IF THE SCRIPT HAS BEEN FORCED
	if (ElementIn == null) {ElementIn = event.srcElement;}
		
	// MASK THE SHIFT SELECT SO THAT EVENT DOES NOT HAVE TO EXIST
	if (event != null)
		ShiftKeyVar =  event.shiftKey;
	else
		ShiftKeyVar = false;
	
	//BUBBLE THROUGH THE CLICKED-ON ELEMENT AND SEE IF IT IS OR IS SITTING ON A TD
	var Element = TestElement('TD',ElementIn);

	if (Element != null) {
		// CHECK WHAT CLASS THE TABLE THAT WE'RE ACTING ON IS, AND IF IT COMPLIES TO OUR 'ACTED ON' LIST
		if ((Element.parentElement.parentElement.parentElement.className.toUpperCase() == TableClass.toUpperCase()) && (Element.tagName != 'A')) {
			var HeadingCell = false;
			var ChildCounter;
			
			// CHECK THE FONT CLASS
			for (ChildCounter =0; ChildCounter < Element.children.length; ChildCounter++) {
				// IF IT IS THE RIGHT ELEMENT
				if ((Element.children[ChildCounter].tagName == 'FONT') && (Element.children[ChildCounter].className.toUpperCase() == FontClass.toUpperCase()))
					HeadingCell = true;
			}
			
			// CHECK IF WE NEED TO SORT THE COLUMN
			if ((Element.className.toUpperCase() == HeadingClass.toUpperCase()) || (HeadingCell)) {
				// CHECK TO SEE IF THE ITEM CLICKED ON IS NOT THE CHECKBOX
				if ((Element.children[0] != null) && (Element.children[0].tagName == "INPUT") && (Element.children[0].type != null) && (Element.children[0].type == "checkbox")) {
					// CLEAR THE FIELD FIRST
					WipeOut();
					
					// CYCLE THROUGH AND SET THE ROWS TO SELECTED OR DESELECTED
					if (Element.children[0].checked == true) {
						var Counter;
						var Counter2;
						var ColCounter;
						
						// ADD THE ACTUAL ELEMENT
						// AddElement(Element);
						
						//GRAB THE ELEMENT TABLE REFERENCE
						var TableElement = Element.parentElement.parentElement.parentElement;
	
						// GET THE NUMBER OF COLUMNS THAT WE HAVE TO RENDER
						ColCounter = Element.parentElement.cells.length;
						
						//CYCLE THROUGH ALL THE ROWS EXCEPT THE FIRST AND LAST ONE'S AND SET THEM
						for (Counter = Element.parentElement.rowIndex+1; Counter <TableElement.rows.length; Counter++) {
							// CHECK THE NUMBER OF CELLS THAT ARE IN THE ROW.
							if (TableElement.rows[Counter].cells.length == ColCounter) 	{
								for (Counter2 = 0; Counter2 < TableElement.rows[Counter].cells.length; Counter2++) {
									//SET THE ELEMENTS TO HIGHLIGHTED
									AddElement(TableElement.rows[Counter].cells[Counter2]);
								}
							}
						}					
					}
					
					// EXIT THE PROCEDURE
					return;
				}
				
				//SET THE STATUS MESSAGE
				window.status = "Please wait, sorting table...";
				
				//EMPTY THE SELECTION THAT MAY HAVE ARISEN FROM HOLDING CONTROL KEY AND CLICKING
				document.selection.empty();
		
				//CHECK IF WE'RE SORTING UP AND DOWN
				if (InSelectedArray(Element)) {
					//IF THE COLUMN IS ALREADY SELECTED, CHANGE SORT ORDER.
					if (CurrSortOrder == 'UP')
						CurrSortOrder = 'DOWN';
					else
					    CurrSortOrder = 'UP';
				}	
				else
					CurrSortOrder = 'DOWN';

				//WIPE ANY PREVIOUSLY SELECTED ELEMENTS OF THE TABLE
				WipeOut();

				//ADD THE HEADING ELEMENT TO THE SELECTED ELEMENTS ARRAY AND 
				AddElement(Element);

				// SET THE HOURGLASS TO SHOW THAT THE ELEMENT IS BEING SORTED
				document.body.style.cursor = 'wait';			
				
				//ACTUALLY SORT THE TABLE; DELAY SO THAT THE CURSOR EFFECT CAN BE SET
				setTimeout("SortColumn('" + CurrSortOrder + "')",1);
				
				// RESET THE CURSOR
				setTimeout("document.body.style.cursor = ''; document.body.focus();",50);
				
				//RELEASE THE ALT KEY BEING HELD DOWN VARIABLE
				PrevKey = false;			
				
				//SET STATUS BACK
				window.status = "Table Sorted.";
			} // HEADING CLICKED ON; TABLE SORTED.

			else {
				// CHECK IF THE CLICKED-ON ITEM IS A CHECKBOX
				if ((Element.children[0] != null) && (Element.children[0].tagName == 'INPUT') && ((Element.children[0].type == 'radio') || (Element.children[0].type == "checkbox"))) {

					// CHECK IF IT IS A RADIO BUTTON
					if (Element.children[0].type == 'radio')
						WipeOut();
						
					// CHECK FOR SHIFT SELECT
					if (ShiftKeyVar) { 
						//NOW WE NEED TO SELECT THE WHOLE ROW
						for (Counter = 0; Counter < Element.parentElement.cells.length; Counter++)
								AddElement(Element.parentElement.cells[Counter]);

						//CLEAR THE SELECTION
						document.selection.empty();

						//SELECT EVERYTHING IN BETWEEN
						ShiftSelect();
						
						//CLEAR THE HOLD-KEY VARIABLE
						PrevKey = true;

					} 
					
					else {
						//NORMAL SELECT
						
						//IF THE CTRL KEY IS NOT BEING HELD DOWN, OR THE PREVIOUS SELECT WAS DONE WITH THE ALT KEY DOWN, CLEAR EVERYTHING
						/*
						if (!event.ctrlKey)
						{
							if (!InSelectedArray(Element.parentElement.cells[0]))
								WipeOut();
						}
						else if (PrevKey)
								WipeOut();
						*/
						
						// CHECK IF WE SHOULD UNSELECT THE PARENT CHECKBOX
						if (Element.children[0].checked == false) {
							// GET THE PARENT ELEMENT
							var tCheck = findFirstCheck(Element.parentElement.parentElement.parentElement);
							if (tCheck != null)
								tCheck.checked = false;
						}
						
						//NOW WE NEED TO SELECT THE WHOLE ROW
						for (Counter = 0; Counter < Element.parentElement.cells.length; Counter++)
							AddElement(Element.parentElement.cells[Counter]);
						
						//WIPE OUT SELECTION FROM CTRL KEY 
						document.selection.empty();
						
						//NO ALT KEY BEING HELD DOWN
						PrevKey = false;
					}
				}
			}
		}  // ELEMENT TAGNAME
	}
	
	else WipeOut();   //CLICKED SOMEWHERE ELSE
}

// THIS ONE'S PRETTY OBVIOUS
function ShiftSelect() {
	//SELECTS ALL THE ELEMENTS IN THE TABLE FROM THE FIRST SELECETED TO THE LAST SELECTED
	var FirstElement;
	var LastElement;
	var Counter;
	var Counter2;
	var TableElement;
	
	FirstElement = Tracker[0];
	LastElement = Tracker[0];
	
	//FIRST, FIND THE HIGHEST AND LOWEST ELEMENTS
	for (Counter = 0; Counter < TrackPos; Counter++) {
		if (Tracker[Counter].parentElement.rowIndex > LastElement.parentElement.rowIndex)
			LastElement = Tracker[Counter];

		if (Tracker[Counter].parentElement.rowIndex < FirstElement.parentElement.rowIndex)
			FirstElement = Tracker[Counter];
	}
	
	//GRAB THE ELEMENT TABLE REFERENCE
	TableElement = FirstElement.parentElement.parentElement.parentElement;
	
	// WIPE THE PREVIOUS RECORD
	WipeOut();
	
	//CYCLE THROUGH ALL THE ROWS EXCEPT THE FIRST AND LAST ONE'S AND SET THEM
	for (Counter = FirstElement.parentElement.rowIndex; Counter < LastElement.parentElement.rowIndex+1; Counter++) {
		for (Counter2 = 0; Counter2 < TableElement.rows[Counter].cells.length; Counter2++) {
			//SET THE ELEMENTS TO HIGHLIGHTED
			AddElement(TableElement.rows[Counter].cells[Counter2]);
		}
	}
}

// CLEARS ALL THE SELECTED CELLS
function WipeOut() {
	var Counter;
	
	//FREE ALL THE SELECTED ROWS
	for (Counter = 0; Counter < TrackPos; Counter++) {		
		if (Tracker[Counter].style.filter != null)
			Tracker[Counter].style.filter = "";
		
		// OBJECTIFY
		var tObj = Tracker[Counter].children[0];
		if ((tObj != null) && (tObj.tagName == 'INPUT') && ((tObj.type == 'checkbox') || (tObj.type == 'radio')))
				tObj.checked  = false;
	}
			
	//RESET OUR "ELEMENTS SELECTED" COUNTER
	TrackPos = 0;
}

function Right(String, Length) {
	if (String == null)
		return (false);

    var dest = '';
    for (var i = (String.length - 1); i >= 0; i--)
		dest = dest + String.charAt(i);

	String = dest;
	String = String.substr(0, Length);
	dest = '';

    for (var i = (String.length - 1); i >= 0; i--)
		dest = dest + String.charAt(i);

	return dest;
}

function setDataType(cValue) {
	// THIS FUNCTION CONVERTS DATES AND NUMBERS FOR PROPER ARRAY
	// SORTING WHEN IN THE SORT FUNCTION
		
	var isDate = new Date(cValue.replace(/\//g, ' '))
		
	if (isDate == "NaN") {
		if (isNaN(parseFloat(cValue.replace(/R/g, '').replace(/,/g, '')))) {
			// THE VALUE IS A STRING, MAKE ALL CHARACTERS IN
			// STRING UPPER CASE TO ASSURE PROPER A-Z SORT
			cValue = cValue.toUpperCase();
			return cValue;
		}
			
		if (isNaN(cValue)) {
			// THE VALUE IS A CURRENCY
			var myCurr;
			myCurr = String.fromCharCode(48 + cValue.length) + cValue;
			return myCurr;
		}
		
		else {
			// VALUE IS A NUMBER, TO PREVENT STRING SORTING OF A NUMBER
			// ADD AN ADDITIONAL DIGIT THAT IS THE + TO THE LENGTH OF
			// THE NUMBER WHEN IT IS A STRING
			var myNum;
			myNum = String.fromCharCode(48 + cValue.length) + cValue;
			return myNum;
		}
	}

	else {
		// VALUE TO SORT IS A DATE, REMOVE ALL OF THE PUNCTUATION AND
		// AND RETURN THE STRING NUMBER
		var myDate = new String();
		myDate = isDate.getFullYear() + '';
		myDate = myDate + Right('0' + (isDate.getMonth() + 1), 2) + '';
		myDate = myDate + Right('0' + isDate.getDate(), 2);		
		return myDate ;
	}
}

// SORTS A COLUMN UP OR DOWN
function SortColumn(UpOrDown,CellElement) {
	//SETS ALL THE VARIABLES NEEDED, PERFORMS BUBBLE SORT ON TABLE ELEMENTS.
	var Counter = 0;
	var Counter1 = 0;
	var ErrorCode = 0;
	var NeedToSort = false;
	var HeadingCell = false;
	
	// GET THE ELEMENT; IE THE LAST ADDED CELL TO SORT ON.
	var CellIn;
	if (CellElement == null)
		CellIn = Tracker[TrackPos-1];
	else
		CellIn = CellElement;
			
	var LookUpCellNum = CellIn.cellIndex;
	var TableElement = CellIn.parentElement.parentElement.parentElement;
	var NofCells = CellIn.parentElement.cells.length;
	var StartPos = CellIn.parentElement.rowIndex;
	var Sort1 = new Array();
	var CorrOrder = new Array();
	var Order = new Array();
	var RowIn1 = '';
	var TableSize;
	var TempCOrder;
	var TempValue;
	var lastRow = 0;

	// var NofNumbers = TableElement.rows.length;
	var NofNumbers = StartPos;
			
	// QUICK CHECK TO SEE IF THE SORT ALL CHECKBOX IS STILL SELECTED.
	var TempValue = TableElement.rows[StartPos].cells[0].children[0];
	
	if ((TempValue.tagName == 'INPUT') && (TempValue.type == 'checkbox')) {TempValue.checked = false;}
	TempValue = 0;
					
	while (lastRow < TableElement.rows.length-1) {
		StartPos = NofNumbers;
		NofNumbers = lastRow + 1;
		
		// RUN THROUGH THE PROCEDURE AND COUNT THE NUMBER OF COLUMNS WHILE THERE ISN'T A SUB-HEADING
		while ((NofNumbers < TableElement.rows.length) && (TableElement.rows[NofNumbers].cells.length != 1))
			NofNumbers++;
		
		// CHECK IF WE NEED TO SEARCH AGAIN
		lastRow=NofNumbers;
		
		//ADD ELEMENTS TO ARRAY
		for (Counter = 0; Counter < NofNumbers;Counter++) {
			CorrOrder[Counter]=Counter;
			//RESET VARIABLE
			ErrorCode = 0;
			
			//ERROR CHECKING OF ELEMENTS
			if ((TableElement.rows[Counter] == null) || (TableElement.rows[Counter].cells[LookUpCellNum] == null) || (TableElement.rows[Counter].cells.length != NofCells))
				ErrorCode = 1;			
			else
				ErrorCode = 0;
			
			if (ErrorCode == 0) {
				TempValue = TableElement.rows[Counter].cells[LookUpCellNum].innerText;
				Sort1[Counter] = setDataType(TempValue)
			}
			else
				Sort1[Counter] = "~|:|~";

			//UPDATE THE ORDER ARRAY AND THE CORRORDER ARRAY
			Order[Counter] = Counter;
			CorrOrder[Counter] = Counter;
		}
			
		//START NEW COUNTER FOR BUBBLE SORT	
		for (Counter = StartPos+1; Counter < NofNumbers; Counter++) {
			//BUBBLE SORT PART 2 WITH ANOTHER NEW COUNTER
			for (Counter1 = Counter; Counter1 < NofNumbers; Counter1++)	 {
				//START SORTING	
				if (UpOrDown == 'UP') {
					//IF EITHER CELL IS UNDEFINED IT MUST BE REPLACED WITH A PLACE HOLDER							
					if ((Sort1[Counter] > Sort1[Counter1]) && (Sort1[Counter] != "~|:|~") && (Sort1[Counter1] != "~|:|~"))
						NeedToSort = true;
					else
						NeedToSort = false;	
				}	
				else {
					if ((Sort1[Counter] < Sort1[Counter1]) && (Sort1[Counter] != "~|:|~") && (Sort1[Counter1] != "~|:|~"))
						NeedToSort = true;
					else
						NeedToSort = false;
				}
		
				//SWAP ORDER OF SORT ARRAY AS WELL AS ORDER ARRAY			
				if (NeedToSort)	{
						// SORT OUR TEMPORARY ARRAY
						TempCell = Sort1[Counter];
						Sort1[Counter] = Sort1[Counter1];
						Sort1[Counter1] = TempCell;
						// SORT THE ORDER ARRAY	
						TempOrder = Order[Counter];
						Order[Counter] = Order[Counter1];
						Order[Counter1] = TempOrder;
				}
			}
		}

		// SAVE THE ORIGINAL SIZE OF THE TABLE
		TableSize = TableElement.rows.length;
	
		// SHIFT ALL THE ROWS THAT NEED TO BE MOVED TO THE END OF THE TABLE AND INSERT PLACEHOLDERS IN THEIR PLACE
		for (Counter = 0; Counter < Order.length; Counter++) {
			// IF THE ROWS NEED TO BE SWAPPED
			if (Order[Counter] != Counter) {
				TableElement.moveRow(Counter,TableElement.rows.length-1);
				TableElement.insertRow(Counter);
				CorrOrder[Counter] = TableElement.rows.length-1;
			}
		}
	
		// MOVE THE ROWS BACK TO THEIR RESPECTIVE PLACES IN THE TABLE
		for (Counter = 0; Counter < NofNumbers; Counter++) {
			// CHECK IF THEY MATCH
			if (Order[Counter] != Counter) {
				TempCOrder = CorrOrder[Order[Counter]];
				// ROW SWAP ROUTINE; NEEDS SMALLEST FIRST.
				if (TempCOrder < Counter) {
					// SWAP ROWS
					TableElement.moveRow(TempCOrder,Counter);
					TableElement.moveRow(Counter-1,TempCOrder);
				} 
				
				else {
					// SWAP ROWS
					TableElement.moveRow(Counter,TempCOrder);
					TableElement.moveRow(TempCOrder-1,Counter);
				} 
			}
		}
	
		// GET RID OF THE LAST COUPL'A ROWS
		while (TableElement.rows.length != TableSize) {TableElement.deleteRow(TableElement.rows.length-1);}
	}
}

// FUNCTION TO RETURN THE SPECIFIED VALUE FROM THE SELECTED ROWS
function getFromSelected(valueToGet) {
    var temp = ReturnSelected();    
    valueToGet += '=';
    temp = temp.substring(valueToGet.length);
    return temp;      
}

// FUNCTION TO RETURN THE SELECTED ROWS
function ReturnSelected(Delimiter, TableId) {
	var Counter;
	var BuildString = '';
    		
	// SORT OUT DELIMITER
	if (Delimiter == null) {Delimiter = '|*|';}
	
	// ITERATE THROUGH THE COLLECTION AND FIND THE CHECKBOX NAMES.
	for (Counter = 0; Counter < TrackPos; Counter++) {
		// CHECK IF THE ELEMENT IS A CHECKBOX
		if ((Tracker[Counter].children[0] != null) && (Tracker[Counter].children[0].type != null) && ((Tracker[Counter].children[0].type == 'checkbox') || (Tracker[Counter].children[0].type == 'radio'))) {

			// CHECK IF A TABLEID WAS SUPPLIED, AND USE IT IF SO
			if (TableId != null) {	
						
				// CHECK IF IT BELONGS TO THE CORRECT TABLE.
				if ((Tracker[Counter].parentElement.parentElement.parentElement.id != null) && (Tracker[Counter].parentElement.parentElement.parentElement.id == TableId)) {								
					// ADD THE DELIMITER
					if (BuildString != '') {BuildString+=Delimiter;}
					
					var rowParams = Tracker[Counter].parentElement.children[Tracker[Counter].parentElement.children.length -1].children[0]
					BuildString += rowParams.value;
				}
			}
			
			else {			
				// ADD THE DELIMITER
				if (BuildString != '') {BuildString+=Delimiter;}
				var rowParams = Tracker[Counter].parentElement.children[Tracker[Counter].parentElement.children.length -1].children[0]
				BuildString += rowParams.value;							
			}
		}
	}
	
	if (BuildString == '') {BuildString = 'false';}
	return BuildString;
}

function setPreSelected () {
	//check in the first column of any table if there are selected radio buttons or checkboxes
	//if so attempt to select these items

	for (i=0; i < document.forms[0].elements.length;i++) {
		var e = document.forms[0].elements[i];

		if (((e.name != 'allBox') && (e.type=='checkbox')) || ((e.name != 'allBox') && (e.type=='radio'))) {	
			if(e.checked){
				ApplySelect(e);
			}
		}
	}
}

// METHOD TO FIND THE FIRST CHECKBOX IN A TABLE, AND MAKE SURE THAT IT IS THE CORRECT ONE
function findFirstCheck(TableElement) {
	var rowCounter = 0;
	var Found = null;
	var tObj;
	
	// CYCLE THROUGH THE ROWS UNTIL FOUND, OR END OF ROWS IS REACHED
	while ((Found == null) && (rowCounter < TableElement.rows.length)) {
		// CHECK THE FIRST CELL OF THIS ROW
		tObj = TableElement.rows[rowCounter].cells[0];
		if (tObj.children.length)
			tObj = tObj.children[0];
		else
			continue;
		
		// CHECK THE TAGNAME
		if ((tObj.tagName == 'INPUT') && (tObj.type == 'checkbox'))
			Found = tObj;
		
		// INCREASE THE ROW COUNTER
		rowCounter++;
	};
	
	return tObj;
}

// TRAP THE CLICK EVENT FOR THE DOCUMENT.
AddEvent("document.onclick","ApplySelect();");	
