//***************************************************************************************
// 		This file contains the "CGNET Checkbox Catalog" JavaScript library routines
//***************************************************************************************
// Version 1.2
// Date: 8/14/01
// Author: Rick Hoffman
//***************************************************************************************

//***************************************************************************************
//	Variables
//***************************************************************************************
// 	GLOBAL variables for checkbox module
var MAX_CHECKBOX_ROWS = 199;					// maximum size for rows of checkboxes
var MAX_CHECKBOX_COLS = 9;						// maximum size for columns of checkboxes
var TOTAL_ROWS		= 0							// total number of rows defined
var TOTAL_COLUMNS	= 0							// total number of columns defined
var checkbox_entry = new Array(MAX_CHECKBOX_ROWS);	// data structure matrix to checkbox entries 
var backup_checkbox_entries;					// backup array of main form checkbox data
//***************************************************************************************
// Define an array containing entry information for each checkbox to be displayed
var MAX_CATEGORY_ENTRY_SIZE = 3;				 	// size of a checkbox array entry below (matches array below)
// The CATEGORY_ENTRY array below has the following information: CATALOG_ENTRY("SuperCategory", "SubCategory", "Checked_Flag");
// "SuperCategory" 		= 	Parent of the "SubCategory" in the display tree
// "SubCategory"		=	Catalog name to be displayed
// "Checked_Flag"		= 	[CHECKED|UNCHECKED|DISABLED] : State flag for this catalog entry
var CATEGORY_ENTRY = new Array(0, 0, 0);		// Initialize with NULL entries
//***************************************************************************************

//***************************************************************************************
// Name:	 		Initialize_Checkbox_Matrix()
// Description:  	This function initalizes the checkbox array to default values
//					It creates a 2 dimensional matrix and stores a NULL entry of the
//					CATEGORY_ENTRY array[] in each slot.
// Arguments: 		none
//***************************************************************************************
function Initialize_Checkbox_Matrix() {

	for (i=0; i < MAX_CHECKBOX_ROWS; i++) {  
		 checkbox_entry[i] = new Array(MAX_CHECKBOX_COLS);		// Setup 2 dimensional array
		for (j=0; j < MAX_CHECKBOX_COLS; j++) {						// 
			 checkbox_entry[i][j] = new Array(MAX_CATEGORY_ENTRY_SIZE);
 			 for (k=0; k < MAX_CATEGORY_ENTRY_SIZE; k++) {		 	
			 	checkbox_entry[i][j][k] = CATEGORY_ENTRY[k];		// initialize NULL entries in the entire matrix
			}
	 	}
	}
	return;
}

//***************************************************************************************
// Name:	 		SetupCheckboxEntry(SuperCategory, SubCategory, CHECKED_FLAG, DISABLE_FLAG) 
// Description:  	This function enters a new category entry into the display matrix.
// Arguments: 		SuperCategory 	= Category Name
//					SubCategory		= Category Name
//					CHECKED_FLAG	= State Flag
//***************************************************************************************
function SetupCheckboxEntry(SuperCategory, SubCategory, CHECKED_FLAG) {
	var result = 0;	

	// See if this is the top level entry, i.e. [0][0] in the matrix
	if (CheckHighestLevelEntry(SuperCategory, SubCategory, CHECKED_FLAG)) {
		return;
	}
	// See if there is a SuperCategory entry in the array tree already with this name
	if (CheckExistingEntry(SuperCategory, SubCategory, CHECKED_FLAG)) {
		return;		// Found existing entry and made this one a subcategory of it
	} 
	else {
		// Must be error - No SuperCategory found for this entry
		alert("ERROR - Found no SuperCategory match for: " + SuperCategory + " - " + SubCategory);
	}
	return;
}

//***************************************************************************************
// Name:	 		CheckHighestLevelEntry(SuperCategory, SubCategory, CHECKED_FLAG) 
// Description:  	This function sees if this is the God of all SuperCategories at the highest level
//				 	of spiritual growth possible within the Zen mind.
// Arguments: 		SuperCategory 	= Category Name
//					SubCategory		= Category Name
//					CHECKED_FLAG	= State Flag
// Returns:		    true			= Created SuperCategory at highest level
// Returns:		    false			= Not top level SuperCategory
//
//***************************************************************************************
function CheckHighestLevelEntry(SuperCategory, SubCategory, CHECKED_FLAG) {

	if (SuperCategory == "TOPLEVEL") {
		checkbox_entry[0][0][0] = "TOPLEVEL";
		checkbox_entry[0][0][1] = SubCategory;
		checkbox_entry[0][0][2] = CHECKED_FLAG;
		TOTAL_COLUMNS = TOTAL_COLUMNS + 1;		// Advance across the matrix
		return true;
	}
return false;
}

//***************************************************************************************
// Name:	 		CheckExistingEntry(SuperCategory, SubCategory, CHECKED_FLAG) 
// Description:  	This function looks for a SuperCategory that exists already associated with this SubCategory
//				 	and places this	entry in the appropriate slot in the matrix.  It will place
//					it on the current SuperCategory row if available or else it goes down rows
//					until it finds an available spot.
// Arguments: 		SuperCategory 	= Category Name
//					SubCategory		= Category Name
//					CHECKED_FLAG	= State Flag
// Returns:		    true			= Found existing SuperCategory and placed SubCategory appropriately
// Returns:		    false			= Could not find SuperCategory = Error
//***************************************************************************************
function CheckExistingEntry(SuperCategory, SubCategory, CHECKED_FLAG) {

	// Loop through the currently used parts of the matrix looking for this SuperCategory.
	for (row = 0; row <= TOTAL_ROWS; row++) {
		for (col = 0; col <= TOTAL_COLUMNS; col++) {
			if (checkbox_entry[row][col][1] == SuperCategory) {	// Found it!
				// See if there is an existing entry to the right of this SuperCategory on this row
				if (checkbox_entry[row][col+1][0] == 0) { 	// empty column to the right so use it
					checkbox_entry[row][col+1][0] = SuperCategory;
					checkbox_entry[row][col+1][1] = SubCategory;
					checkbox_entry[row][col+1][2] = CHECKED_FLAG;
					if (col+1 > TOTAL_COLUMNS) {				// Farther to the right than before?
						TOTAL_COLUMNS = col + 1;				// Advance across the matrix					
					}
					return true;					
				}
				else {	// Something already to the right column so put it down one row at least.
					// Loop through the remaining rows looking for first one with no entries
					// to the right of it.
					for (x = row+1; x<MAX_CHECKBOX_ROWS; x++) {
						// Make sure every column is clear on this row or go to next row
						SAFE_PLACEMENT = true;		
						for (y = 0; y<=TOTAL_COLUMNS; y++) {
							if (checkbox_entry[x][y][0] != 0) {
								SAFE_PLACEMENT = false;	  // Found entry = this row is no good!
								break;
							}
						}
						// Safe row for placement because nothing is placed yet to the right
						if (SAFE_PLACEMENT) {
							checkbox_entry[x][col+1][0] = SuperCategory;
							checkbox_entry[x][col+1][1] = SubCategory;
							checkbox_entry[x][col+1][2] = CHECKED_FLAG;
						if (x > TOTAL_ROWS) {					// Farther down than before?
							TOTAL_ROWS = x;						// Advance down the matrix					
						}							
						return true;
						}
					}	// for loop
				}	// else column to right not available
			}	// found checkboxrow == SuperCategory
		}	// for column...
	} // for row...

	return false;		// Could not find this SuperCategory anywhere in the matrix = Error
}

//***************************************************************************************
// Name:	 		DisplayMatrixContents()
// Description:  	This function is for debugging. It displays the matrix contents in the window.
// Arguments: 		none
//***************************************************************************************
function DisplayMatrixContents() {

	for (i=0; i<MAX_CHECKBOX_ROWS; i++){
		for (j=0; j<MAX_CHECKBOX_COLS; j++) {
			document.write("ROW: " + i + " COL: " + j + "  ");
			document.write(checkbox_entry[i][j] + "<br>")
		}
	}
	return;
}

//***************************************************************************************
// Name:	 		BuildTableMatrixContents()
// Description:  	This function builds the HTML table based upon the matrix contents.
// Arguments: 		none
//***************************************************************************************
function BuildTableMatrixContents() {

	// Create a form with a table within it	
//	document.write('<form name="tableform">');	
//	document.write('<input type="hidden" name="validcats" value="cgiar,cip,icarda">');

// debugging
//	alert("ValidCats: " + tableform.validcats.value.toUpperCase());
	 	
	document.write("<TABLE id=checkboxtable " + TABLE_ATTRIBUTES + " width=" + TABLE_WIDTH + "% >");

	for (row=0; row<=TOTAL_ROWS; row++){		// loop through all rows
  		document.write("<TR" + TR_ATTRIBUTES + ">");		

		for (col=0; col<=TOTAL_COLUMNS; col++) {	// loop through all columns
			if 	(checkbox_entry[row][col][0] != 0) {
				ID = row.toString() + "-" + col.toString();

				document.write("<td" + TD_ATTRIBUTES + ">");
				if (FONT_ATTRIBUTES != "") {
					xxx = "<FONT " + FONT_ATTRIBUTES + ">";
				}
				document.write(xxx);

				switch (checkbox_entry[row][col][2]) {
					case "CHECKED" : STATUS = "CHECKED"; break;
					case "UNCHECKED" : STATUS = "UNCHECKED"; break;
					case "DISABLED" : STATUS = "DISABLED";	break;
					default: STATUS = "DISABLED"; break;
				}
				
				// Check for valid catalog name from list supplied by the server.
				// If we cannot find the name we force this checkbox to be disabled.
				if (!CheckValidCatalog(checkbox_entry[row][col][1])) {
					STATUS = "DISABLED"							// Disable checkbox on screen
					checkbox_entry[row][col][2] = "DISABLED"; 	// Do not allow checking
				}
				
				idname = "checkbox" + ID;	
				// Set up the checkbox entry with the following information:
				// id 		= checkbox + row + "-" + column (i.e. "checkbox3-2")
				// value 	= SubCategoryName (i.e. CGIAR, CIP, etc...)
				// name		= "ct" 
				// status	= [CHECKED|UNCHECKED|DISABLED] (DISABLED is never checked)
				// onclick	= BoxClick(this, ID) (i.e. onclick(BoxClick(this, 3-2)) )
				xxx = "<input type=\"checkbox\" id=\"" + idname + "\" value=\"" + checkbox_entry[row][col][1] + "\" name=\"ct\" " + STATUS +  " onclick='BoxClick(this, \"" + ID + "\");'>";
				document.write(xxx);	// Generate the checkbox entry

				if (checkbox_entry[row][col+1][0] != 0) {
					FILLER = FILLER_YES;
				}
				else {
					FILLER = FILLER_NO;
				}
				document.write(checkbox_entry[row][col][1]+ FILLER);

				if (FONT_ATTRIBUTES != "") {
					document.write("</font>");
				} 

				document.write("</td>");
			} 
			else {		// blank column entry
				document.write("<td>");
				document.write("</td>");
			}
		}	// for columns
		document.write("</TR>");
	}	// for rows

	document.write("</TABLE>");
//	document.write("</form>");

	return;
}

//***************************************************************************************
// Name:	 		BackupMatrixContents()
// Description:  	This function copies the matrix to a backup array in case a user
//					resets the form at a later time.  If they do a reset we copy the
//					backup array to the original so that all checkboxes return to their 
//					original state.
// Arguments: 		none
//***************************************************************************************
function BackupMatrixContents() {

	backup_checkbox_entries = checkbox_entry;	// retain a copy of all checkbox entries
	return;
}

//***************************************************************************************
// Name:	 		BoxClick(src, ID)
// Description:  	The user has clicked on a checkbox.  Use applicable rules.
// Arguments: 		src				= 'this' document
//					ID				= identifier for this checkbox (matrix array index)
//***************************************************************************************
function BoxClick(src, ID) {

	if (!src.contains(event.fromElement)) { 
		divider  = ID.search("-");
		idlen = ID.length;
		rowid = ID.substr(0, divider);
		colid = ID.substr(divider+1, idlen-divider);
	
		// Loop through the currently used parts of the matrix looking for any entries with this SuperCategory.
		SuperCategory = checkbox_entry[rowid][colid][1];  // SuperCategory name 	
		if (tableform.elements['checkbox' + ID].checked == true) {								
			TurnOnSubs(SuperCategory, "CHECKED");	// Turn ON subcategories of this entry
		}
		else {
			TurnOnSubs(SuperCategory, "UNCHECK");	// Turn OFF subcategories of this entry
		}
	}
	return;
}

//***************************************************************************************
// Name:	 		TurnOnSubs(SuperCategoryName, checkstate)
// Description:  	The user has clicked on a checkbox.  Use applicable rules to turn checkboxes
//					on or off.  Also call this routine recursively to find Subcategories down the tree.
// Arguments: 		SuperCategoryName 	= Search name
//					checkstate			= "CHECKED" or "UNCHECKED"
//***************************************************************************************
function TurnOnSubs(SuperCategoryName, checkstate) {
	var 	row = 0;
	var		col = 0;
	
	for (row = 0; row <= TOTAL_ROWS; row++) {
		for (col = 0; col <= TOTAL_COLUMNS; col++) {

			// See if SubCategory lists this SEARCH_CATEGORY as it's SuperCategory
			if ((checkbox_entry[row][col][0] == SuperCategoryName) &&
				(checkbox_entry[row][col][2] != "DISABLED") ) {  // cannot be disabled
				// found a match so turn on checkbox and call this routine recursively
				ID = row.toString() + "-" + col.toString();

					if (checkstate == "CHECKED") {
						tableform.elements['checkbox' + ID].checked = true;								
					}
					else {
						tableform.elements['checkbox' + ID].checked = false;								
					}
					// Recursive call to this function for further searches
					TurnOnSubs(checkbox_entry[row][col][1], checkstate);	// Turn on Subcategories of this entry if needed
			}	// if SuperCategoryName = found

		}	// for col..
	}	// for row...

	return;		// finished looping through all matrix entries on our search
}

//***************************************************************************************
// Name:	 		CheckValidCatalog(catalogname)
// Description:  	Check for a valid catalog name from list supplied by server.  We convert
//					both strings to upper case before doing the compare.
// Arguments: 		name = Catalog name to validate
// Returns:		    true  = Found valid catalog name
//					false = Could not find valid catalog name
//***************************************************************************************
function CheckValidCatalog(catalogname) {

	// Get all the valid catalog names in upper case
	ValidCatalogNames = document.tableform.validcats.value.toUpperCase();
	// See if this entry is in the list after converting it to upper case
	foundname  = ValidCatalogNames.search(catalogname.toUpperCase());
	if (foundname != -1) {
		return true;
	} 
	else {
		return false;
	}
}

//***************************************************************************************
// Name:	 		ResetForm()
// Description:  	Reset all controls on the current form and all restore any catalog
//					checkbox data back to it's original state.  
// Note:			When 
// Arguments: 		none
//***************************************************************************************
function ResetForm() {
	checkbox_entry = backup_checkbox_entries;	// copy the backup array over to the original
	document.tableform.reset();					// do normal form reset
	return true;
}
