/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * File:    grid.js                                                            *
 * Author:  Keith Borgmann                                                     *
 * Date:    May 15, 2007                                                       *
 * Version: 1.0.2                                                              *
 * Description:                                                                *
 *   Functions for traversing tables.  Compatiable with IE & Moz.              *
 *                                                                             *
 * Function List:                                                              *
 *   getFirstGridRow    (table)                                                *
 *   readGridRow        (row, cellProperty)                                    *
 *   readGridCell       (row, cellIndex)                                       *
 *   countGridCells     (row)                                                  *
 *   getGridColumn      (table, cellIndex, cellProperty)                       *
 *   sumGridColumn      (table, cellIndex, cellProperty)                       *
 *   getGridFromChild   (child)                                                *
 *   findGridRowWith    (table, find, cellIndex, cellProperty)                 *
 *   findGridCellWith   (table, find, cellIndex, cellProperty)                 *
 *                                                                             *
 *   tagHasName         (tag, tagName)                                         *
 *   getNextTag         (tag)                                                  *
 *                                                                             *
 *   alignGridWidths    (table, table)                                         *
 *   getElementText     (element)                                              *
 *                                                                             *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

//TODO: update function list


//Func: getFirstGridRow
//Desc: Returns the first row of a table, or null on any error
//Note: Table struture is table.tbody.tr.td
function getFirstGridRow(table) {
	if (!tagHasName(table, "TABLE")) return null;

	var cursor = table.firstChild;
	while( !tagHasName(cursor, "TBODY") )	//make sure it's the body
		cursor = getNextTag(cursor);

	try { return cursor.firstChild; }
	catch (e) { return null; }
}



//Func: readGridRow
//Desc: reads all td/th data from a row into an array
//Note: cellProperty may be used to speicy a different property than innerHTML
function readGridRow(row, cellProperty) {
	var cell = 0;
	var cells = new Array();
	if (cellProperty==null)	cellProperty = "innerHTML";

	if (tagHasName(row, "TR")) {
		var cursor = row.firstChild;
		while (cursor!=null) {
			cells[cell++] = eval("cursor."+cellProperty);
			cursor = getNextTag(cursor);
		}
	}
	return cells;
}

//Func: readGridCell
//Desc: get the data stored within the specified cell
function readGridCell(row, cellIndex) {
	return getGridCell(row, cellIndex).innerHTML;
}

//Func: getGridCell
//Desc: get a reference to a cell within a row
function getGridCell(row, cellIndex) {
	var cell = 0;

	if (typeof(cellIndex)!="number")
		return null;

	if (tagHasName(row, "TR")) {
		var cursor = row.firstChild;
		while ( cursor!=null && (cell++)<cellIndex )
			cursor = getNextTag(cursor);
	} else
		alert ("function getGridCell failed" );
	return cursor;
}


//Func: getGridCellIndex
//Desc: return's the index (column#) of the cell
function getGridCellIndex(cell) {
	if ( !tagHasName(cell, "TD") && !tagHasName(cell, "TH") ) {
		alert ("function getGridCellIndex failed -- parameter must be a TD or TH object" );
		return null;
	}
	return __getChildIndex(cell);
}

//Func: getGridRowIndex
//Desc: return's the index (row#) of the row.
function getGridRowIndex(row) {
	if ( !tagHasName(row, "TR") ) {
		alert ("function getGridRowIndex failed -- parameter must be a TR object" );
		return null;
	}
	return __getChildIndex(row);
}

//Func: countGridCells
//Desc: returns the total number of cells for the specified row
function countGridCells(row) {
	var count = 0;
	if (tagHasName(row, "TR")) {
		var cursor = row.firstChild;
		while ( cursor!=null) {
			if (cursor.tagName)
				count++;
			cursor = getNextTag(cursor);
		}
	}
	return count;
}

//Func: getGridColumn
//Desc: Reads all td data from a column into an array
function getGridColumn(table, cellIndex, cellProperty) {
	var count = 0;
	var cells = new Array();
	if (cellProperty==null)
		cellProperty = "innerHTML";

	if (tagHasName(table, "TABLE")) {
		var	cursor = getFirstGridRow(table);
		while (cursor!=null) {
			var cell = getGridCell(cursor, cellIndex);
			try {
				cells[count++] = (cell==null) ? null : eval("cell."+cellProperty);
			} catch (e) { cells[count++]=null; }
			cursor = getNextTag(cursor);
		}
	}
	return cells;
}

//Func: sumGridColumn
//Desc: Adds up all values in a specific table column.
function sumGridColumn(table, cellIndex, cellProperty) {
	var a = getGridColumn(table, cellIndex, cellProperty);
	var sum = 0;

	for (var x=0; x<a.length; x++)
		sum+= __toNumeric(a[x]);

	return sum;
}

//Func: getGridFromChild
//Desc: returns the table object from any TR TD or TH
function getGridFromChild(child) {
	if ( tagHasName(child, "TR") ) {
		return child.parentNode.parentNode;
	} else if ( tagHasName(child, "TD") || tagHasName(child, "TH") ) {
		return child.parentNode.parentNode.parentNode;
	} else {
		return null;
	}
}

//Func: getGridRowWith
//Desc: Finds the first row that contains 'find'.
//Note: Optionally use search a different cell & use a different property
function findGridRowWith(table, find, cellIndex, cellProperty) {
	var found = null;
	var cells = new Array();
	if (cellProperty==null)
		cellProperty = "innerHTML";
	if (cellIndex==null)
		cellIndex = 0;

	if (tagHasName(table, "TABLE")) {
		var	cursor = getFirstGridRow(table);
		while (cursor!=null && found==null) {
			var cell = getGridCell(cursor, cellIndex);
			try {
				if (cell!=null &&  eval("cell."+cellProperty)==find )
					found = cursor;
			} catch (e) { }
			cursor = getNextTag(cursor);
		}
	}
	return found;
}


//Func: getGridCellWith
//Desc: Finds the first cell that contains 'find'.
//Note: Optionally use a different property
function findGridCellWith(row, find, cellProperty) {
	var found = null;
	var cells = new Array();
	if (cellProperty==null)
		cellProperty = "innerHTML";

	var cell = getGridCell(row, 0);
	while (cell!=null && found==null) {
		try {
			if ( eval("cell."+cellProperty)==find )
				found = cell;
		} catch (e) { }
		cell = getNextTag(cell);
	}

	return found;
}

//Func: getGridRow
//Desc: get a reference to a row in a table (by the row#)
function getGridRow(table, rowIndex) {
	var row = 0;

	if (typeof(rowIndex)!="number")
		return null;

	if (tagHasName(table, "TABLE")) {
		var cursor = getFirstGridRow(table);
		while ( cursor!=null && (row++)<rowIndex )
			cursor = getNextTag(cursor);
	} else
		alert ("function getGridRow failed" );
	return cursor;
}


//Func: tagHasName
//Desc: True if the tagName correct (note: HTML tagNames are required to be uppercase).
function tagHasName(tag, tagName) {
	if (tag==null)
		return false;
	return (tag.tagName == tagName);
}

//Func: getNextTag
//Desc: Get's the next valid tag (must have a .tagName attribute), or null
function getNextTag(tag) {
	var next = tag.nextSibling;
	if (typeof(next)=="undefined")
		return null;

	while ( next!=null && typeof(next.tagName)=="undefined" )
		next = next.nextSibling;
	return next;
}

//Func: alignGridWidths
//Desc: makes the widths of the cells in both tables the same
//Note: padding1&2 are the padding/boarders used for each table
function alignCellWidths(table1, table2, padding1, padding2) {
	var	cursor1, cursor2;
	if ( tagHasName(table1, "TABLE") ) {
		cursor1 = getFirstGridRow(table1).firstChild;
	} else if ( tagHasName(table1, "TR") ) {
		cursor1 = table1.firstChild;
	} else {
		alert ("Function alignCellWidths failed; parameter 1 must be tables or rows." );
		return null;
	}
	if ( tagHasName(table2, "TABLE") ) {
		cursor2 = getFirstGridRow(table2).firstChild;
	} else if ( tagHasName(table2, "TR") ) {
		cursor2 = table2.firstChild;
	} else {
		alert ("Function alignCellWidths failed; parameter 2 must be tables or rows." );
		return null;
	}

	if (!padding1) padding1=0;
	if (!padding2) padding2=padding1;

	while (cursor1!=null && cursor2!=null) {
		var width = Math.max(cursor1.offsetWidth, cursor2.offsetWidth)-1;

		cursor1.style.width= (width-padding1)+"px";
		cursor2.style.width= (width-padding2)+"px";

		//alert(cursor2.innerHTML);// = "0";

		cursor1 = getNextTag(cursor1);
		cursor2 = getNextTag(cursor2);
	}
}


//Func: setGridWidths
//Desc: similar to alignCellWidths, but instead ~table2.with=table1.width
function setCellWidths(table1, table2, padding2) {
	var	cursor1, cursor2;
	if ( tagHasName(table1, "TABLE") ) {
		cursor1 = getFirstGridRow(table1).firstChild;
	} else if ( tagHasName(table1, "TR") ) {
		cursor1 = table1.firstChild;
	} else {
		alert ("Function alignCellWidths failed; parameter 1 must be tables or rows." );
		return null;
	}
	if ( tagHasName(table2, "TABLE") ) {
		cursor2 = getFirstGridRow(table2).firstChild;
	} else if ( tagHasName(table2, "TR") ) {
		cursor2 = table2.firstChild;
	} else {
		alert ("Function alignCellWidths failed; parameter 2 must be tables or rows." );
		return null;
	}

	if (!padding2) padding2=0;

	while (cursor1!=null && cursor2!=null) {
		var width = cursor1.offsetWidth-1;

		cursor2.style.width= (width-padding2)+"px";

		cursor1 = getNextTag(cursor1);
		cursor2 = getNextTag(cursor2);
	}
}



//Func: getElementText
//Desc: returns all child text elements as one string.
function getElementText(element1) {
	var text = "";
	var cursor = element1.firstChild;

	while (cursor!=null) {
		if (cursor.nodeName=="#text" )
			text += cursor.nodeValue;

		cursor = cursor.nextSibling;
	}
	return text;
}
//Func: getElementText
//Desc: returns all child comments as one string.
function getElementComments(element1) {
	var text = "";
	var cursor = element1.firstChild;

	while (cursor!=null) {
		if (cursor.nodeName=="#comment" )
			text += cursor.nodeValue;

		cursor = cursor.nextSibling;
	}
	return text;
}

//Func: __toNumeric
//Desc: Internal.  Converts any value to a number.
function __toNumeric(value) {
	v = parseFloat(value);
	return isNaN(v) ? 0 : v;
}



//Func: __getChildIndex
//Desc: internal. return's child's index within the parent
//Use with caution: not debugged for when using an invalid 'cell'
//TODO: update variable names
function __getChildIndex(cell) {
	var index = 0;
	var row = cell.parentNode;

	var index = 0;
	var cursor = row.firstChild;
	while ( cursor!=null && (cursor!=cell)  ) {		//Note: cursor will never be null
		cursor = getNextTag(cursor);
		index++;
	}
	return index;
}
