var GL_tableHighlightedRow;
function GL_insertRow(tableId, whichRow, numOfDataPerRow, newDataParameterName) {
	var table = findObject("GL_Table" + tableId);
	var rows = table.getElementsByTagName("tr");
	var row;
	if ( !rows ) {
		return;
	}
	
	row = rows[1];
	var numberOfItems = (rows.length - 1) * numOfDataPerRow;
	var tbody = table.getElementsByTagName("tbody")[0];
    var newRow = document.createElement("tr");        	
    var cols = row.getElementsByTagName("td");
    var i;
    
	for (i=0; i<cols.length; i++) {
		var newTD = document.createElement("td");
		if ( i==0 ) {		
			newTD.innerHTML = '<center><lable>' + rows.length + '. </label></center>'; 
			var j;
			newTD.innerHTML += '<INPUT TYPE=\"hidden\" NAME=\"' + newDataParameterName + '\" VALUE=\"'+ numOfDataPerRow + '\"/>';		
		} else {	
			if ( numOfDataPerRow == 1 ) {
				if ( i == 1 ) {
					numberOfItems++;
				}			
			} else {
				if ( (cols.length - 1) ==  numOfDataPerRow ) {
					numberOfItems++;
				} else {
					var numOfTDPerData = (cols.length - 1) / numOfDataPerRow;
					if ( (i-1)%numOfTDPerData == 0 ) {
						numberOfItems++;
					}					
				}
			}
							
			var inputNameLabels = cols[i].getElementsByTagName("label");
			var inputName = 'Error';
			for (j=0; j<inputNameLabels.length; j++) {
				if ( inputNameLabels[j].id == 'GL_inputNamePrefix' ) {
					inputName = inputNameLabels[j].innerHTML + '[' + numberOfItems + ']';
				}
				if ( inputNameLabels[j].id == 'GL_inputNameSuffix' ) {
					inputName += '.' + inputNameLabels[j].innerHTML;
				}				
			}	
			GL_addTDField(newTD, inputName);						
		}
		newRow.appendChild(newTD);	
	}
	
//	tbody.insertBefore(newRow, rows[whichRow-1]);
	GL_tableHighlightedRow = rows.length;
	tbody.appendChild(newRow);
		
	GL_resetTable(rows);
}

function GL_addTDField(newTD, id) {
	var name = "_pD_" + id;
//	newTD.innerHTML +=name +'<br>';
	newTD.innerHTML += '<INPUT TYPE=\"text\" NAME=\"' + name + '\" VALUE=\"\" SIZE=\"4\"/>';
}

function GL_deleteRow(tableId, whichRow) {
	var table = findObject("GL_Table" + tableId);
	var rows = table.getElementsByTagName("tr");
	var tbody = table.getElementsByTagName("tbody")[0];
	tbody.removeChild(rows[whichRow]);
	
	GL_resetTable(rows);
	
}

function GL_resetTable(rows) {
	var i;	
	for (i=0; i<rows.length; i++) {
	   GL_resetRow(rows[i], i);
	} 

}
function GL_resetRow(row, rowIndex) {
	var cols = row.getElementsByTagName("td");
	var i;
	for (i=0; i<cols.length; i++) {
	   GL_resetCell(cols[i], rowIndex, i);
	} 	
}
function GL_resetCell(cell, rowIndex, colIndex) {
	if ( rowIndex == (GL_tableHighlightedRow) ) {
		cell.className = 'highlighted';
	} else {
		cell.className = 'withinBody';	
	}
	
	GL_resetCellInput(cell, rowIndex, colIndex);
	GL_resetCellLabel(cell, rowIndex, colIndex);	
}

function GL_resetCellLabel(cell, rowIndex, colIndex) {
	var label = cell.getElementsByTagName("label");
	if ( label ) {
		label.innerHTML = rowIndex + '. '; 
		
	}	 
}

function GL_resetCellInput(cell, rowIndex, colIndex) {
	var fields = cell.getElementsByTagName("INPUT");
	if ( !fields ) {
		return;
	}
	if ( fields.length ) {
		var i;
		for (i=0; i<fields.length; i++) {
			GL_resetField(fields[i], rowIndex, colIndex);
		}
	} else {
		GL_resetField(fields, rowIndex, colIndex);
	}	 
}
function GL_resetField(field, rowIndex, colIndex) {
//	field.value = rowIndex + " " + colIndex;
}


function GL_addArrayColumn(arrayUpdateUrlSpanId) {
    var newColumnName = prompt('Please enter a column name', '');
    if ( newColumnName && newColumnName.length > 1 ) {
    	var transForm = GL_findForm('transactionForm');
	    GL_findField(transForm, 'newColumnName').value = newColumnName;
		GL_submitUpdateArrayForm(arrayUpdateUrlSpanId, 'addArrayColumn', -1, -1, -1);
    }
}

function GL_deleteArrayColumn(arrayUpdateUrlSpanId, deleteColumnId) {
	var go = confirm('Are you sure you want to delete the column?');
	if ( go == true) {
		var transForm = GL_findForm('transactionForm');
	    GL_findField(transForm, 'deleteColumnId').value = deleteColumnId;
	    GL_submitUpdateArrayForm(arrayUpdateUrlSpanId, 'deleteArrayColumn', -1, -1, -1);	
	}
}

function GL_addArrayElements(arrayUpdateUrlSpanId, arrayRowIndex, arrayColSize) {
	GLUpdateArrayAsync.submitUpdateArrayAsync(arrayUpdateUrlSpanId, 'addArrayElements', arrayRowIndex, arrayColSize, 1);
}

function GL_addArrayRows(arrayUpdateUrlSpanId, arrayRowIndex, arrayColSize, rowsName) {
    var rows = prompt('Number of ' + rowsName + ' to be added', '');
    if ( rows > 100 ) {
    	alert('Maximum to be added at one time is 100');
    	return;
    }
    if ( rows != null && (rows * 1) > 0 ) {
    	GLUpdateArrayAsync.submitUpdateArrayAsync(arrayUpdateUrlSpanId, 'addArrayElements', arrayRowIndex, arrayColSize, rows*1);
    }
}

function GL_deleteArrayElements(arrayUpdateUrlSpanId, arrayRowIndex, arrayColSize, rowName) {
	var go = confirm('Are you sure you want to delete the ' + rowName + '?');
	if ( go == true) {
    	GLUpdateArrayAsync.submitUpdateArrayAsync(arrayUpdateUrlSpanId, 'deleteArrayElements', arrayRowIndex, arrayColSize, 1);
	}
}

function GL_moveArrayRow(arrayUpdateUrlSpanId, from, to){
	GL_submitUpdateArrayForm(arrayUpdateUrlSpanId, 'moveArrayRow', from, -1, -1, to);
}

function GL_fileUploadSaveTransactionData(clickedFileId) {
   var transForm = GL_findForm('transactionForm');
   if ( !transForm ) {
   	return;
   }
   
   var action = GL_findField(transForm, 'action');
   if ( !action ) {
   	return;
   }
   action.value = 'fileUploadSaveTransData';
   var clickField = GL_findField(transForm, 'clickedFileId');
   if ( !clickField ) {
   	return;
   }
   clickField.value = clickedFileId;
   transForm.submit();
}

function GL_tableSetColumn(evt, currentInput, tableId, fireAsyncMethod) {
   var evt = (evt) ? evt : ((window.event) ? event : null);   
   if ( evt.type != 'keydown' ) {
		return;
   }

	var ARROW_LEFT = 37;
	var ARROW_UP = 38;
	var ARROW_RIGHT = 39;
	var ARROW_DOWN = 40;
	var key = (evt.charCode) ? evt.charCode:evt.keyCode;
	if ( !(key == ARROW_DOWN || key == ARROW_RIGHT) ) {
		return;
	}
		
	var table = findObject(tableId);
	if ( !table ) {
		return;
	}
	
	var rows = table.getElementsByTagName('tr');
	if ( !rows || !rows.length ) {
		return;
	}

	var appendIndex = false;
	if ( evt.ctrlKey || evt.altKey || evt.shiftKey ) {
		appendIndex = true;
	}
	var found = false;
	var cnt = 1;
	var foundColumn;
	var foundRow;
	var foundInput;
	var currentValue = currentInput.value;
	var isNumerical;
	
	if ( evt.altKey ) {
	 	isNumerical = true;	 	
	} else {
		isNumerical = false;
	}
	var numericalValue;
	var length = 0;
	if ( currentValue && isNumerical ) {	
		length = currentValue.length;
		for (var i=0; i<length; i++) {
			var ch = currentValue.charAt(i);
			if ( ch == '.' ) {
				continue;
			}
			if (ch < '0' || ch > '9' ) {
				isNumerical = false;
				break;
			}
		}		
		if ( isNumerical ) {
			numericalValue = parseFloat(currentValue);
			if ( isNaN(numericalValue) ) {
				isNumerical = false;
			}
		}
	}
	if ( isNumerical ) {
		appendIndex = false;
	}
	
	if (key == ARROW_RIGHT && evt.shiftKey && evt.ctrlKey){
		isNumerical = false;
		appendIndex = false;
	}
	else if (key == ARROW_RIGHT && !isNumerical &&!appendIndex)
		return;
	
	var dataList = new Array();
	dataList[dataList.length] = currentInput;
	
	//set up row or column skipping
	var labelData = findObject(tableId + 'Labels');
	var isVertical = false;
	var labelCount = 1;
	if (labelData){
		labelData = labelData.innerHTML.split(',');
		isVertical = labelData[0] == 'true';
		labelCount = parseInt(labelData[1]);
	}
	var xStart = 0;
	var yStart = 0;
	var rowInc = 1;
	var colInc = 1;

	for (var i=xStart; i<rows.length; i=i+rowInc) {	
		var cols = rows[i].getElementsByTagName('td');
		if ( !cols || !cols.length ) {
			continue;
		}
		for (var j=yStart; j<cols.length; j=j+colInc) {	
			var inputs = cols[j].getElementsByTagName('INPUT');
			if ( !inputs || inputs.length < 1 ) {
				continue;
			}
			if ( found ) {
				if ( (ARROW_DOWN == key && foundColumn == j) || (/*isNumerical && */ARROW_RIGHT == key && foundRow == i && j > foundColumn ) ) {
					if ( inputs.length > foundInput ) {
						var foundInputDom = inputs[foundInput];
						if ( appendIndex ) {
							foundInputDom.value = currentValue + '' + cnt;					
						} else {
							if ( isNumerical ) {
								var newValue = (numericalValue *1 + cnt*1)*1 + '';
								var leadingZero = '';
								for (var k=newValue.length; k<length; k++) {
									leadingZero += '0';
								}
								foundInputDom.value = leadingZero + '' + newValue;	
							} else {
								foundInputDom.value = currentValue;					
							}
						}
						dataList[dataList.length] = foundInputDom;
						cnt++;
					}
				}
			} else { 
				for (var k=0; k<inputs.length; k++) {
					if ( inputs[k].name == currentInput.name ) {
				   		found = true;	
				   		foundRow = i;
				   		foundColumn = j;	
				   		foundInput = k;
				   		if ( appendIndex ) {
				   			currentInput.value = currentInput.value + cnt;
				   			cnt++;
				   		}
				   		if (isVertical){
				   			xStart = foundRow;
				   			rowInc = labelCount;
				   		}
				   		else{
				   			yStart = foundColumn;
				   			colInc = labelCount;
						}
				   		break;	   		
					}
				}
			}
		}	
	}
	
	GLTransaction.saveDataList(dataList, fireAsyncMethod);
}

function GL_tableSetColumnCheckbox(evt, checkbox, tableId,
		 checkedValue, uncheckedValue, fireAsyncMethod) {
   var evt = (evt) ? evt : ((window.event) ? event : null);   
   if ( evt.type != 'keydown' ) {
		return;
   }

	var ARROW_RIGHT = 39;
	var ARRAY_DOWN = 40;
	var key = (evt.charCode) ? evt.charCode:evt.keyCode;
	if ( key != ARRAY_DOWN && key != ARROW_RIGHT ) {
		return;
	}
		
	var table = findObject(tableId);
	if ( !table ) {
		return;
	}
	
	var rows = table.getElementsByTagName('tr');
	if ( !rows || !rows.length ) {
		return;
	}

	var found = false;
	var cnt = 1;
	var foundRow;
	var foundColumn;
	var foundInput;
	
	var labelData = findObject(tableId + 'Labels');
	var isVertical = false;
	var labelCount = 1;
	if (labelData){
		labelData = labelData.innerHTML.split(',');
		isVertical = labelData[0] == 'true';
		labelCount = parseInt(labelData[1]);
	}
	var xStart = 0;
	var yStart = 0;
	var rowInc = 1;
	var colInc = 1;

	var autoSaveFields = new Array();
	for (var i=xStart; i<rows.length; i=i+rowInc) {	
		var cols = rows[i].getElementsByTagName('td');
		if ( !cols || !cols.length ) {
			continue;
		}
		for (var j=yStart; j<cols.length; j=j+colInc) {	
			var inputs = cols[j].getElementsByTagName('INPUT');
			if ( !inputs || inputs.length < 1 ) {
				continue;
			}
			if ( found ) {
				if ((key == ARRAY_DOWN && foundColumn == j ) || (key == ARROW_RIGHT && foundRow == i && j > foundColumn)){
					if ( inputs.length > foundInput && !inputs[foundInput].disabled) {						
						inputs[foundInput].checked = checkbox.checked;	
						var hiddenField = GL_setCheckboxHiddenValue(evt, inputs[foundInput], inputs[foundInput].value, checkedValue, uncheckedValue);									
						if ( hiddenField ) {
							autoSaveFields[autoSaveFields.length] = hiddenField;
						}
						cnt++;
					}
				}
			} else { 
				for (var k=0; k<inputs.length; k++) {
					if ( inputs[k].name == checkbox.name ) {
				   		found = true;
				   		foundRow = i;
				   		foundColumn = j;	
				   		foundInput = k;
				   		if (isVertical){
				   			xStart = foundRow;
				   			rowInc = labelCount;
				   		}
				   		else{
				   			yStart = foundColumn;
				   			colInc = labelCount;
						}
				   		break;	   		
					}
				}
			}
		}	
	}
	if ( autoSaveFields.length > 0 ) {
		GLTransaction.saveDataList(autoSaveFields, fireAsyncMethod);
	}
}

function GL_tableSetColumnSelect(evt, currentSelect, tableId, fireAsyncMethod) {
   var mz = !!(evt);
   var evt = (evt) ? evt : ((window.event) ? event : null);   
	if ( !(evt.ctrlKey || evt.shiftKey) ) {
		return;
	}		

	
	
		
	var table = findObject(tableId);
	if ( !table ) {
		return;
	}
	
	var rows = table.getElementsByTagName('tr');
	if ( !rows || !rows.length ) {
		return;
	}

	var ARROW_UP = 38;
	var ARROW_RIGHT = 39;
	var ARROW_DOWN = 40;
	var key = (evt.charCode) ? evt.charCode:evt.keyCode;
	if ( key != ARROW_DOWN && key != ARROW_RIGHT && key != ARROW_UP) {
		return;
	}
	var selectedIndex = currentSelect.selectedIndex;
	
	if ( ARROW_DOWN == key ) {
		if ( selectedIndex + 1 < currentSelect.options.length ) {
			selectedIndex = selectedIndex + 1;
		}
	} else if (ARROW_UP == key) {
		if ( selectedIndex - 1 >= 0 ) {
			selectedIndex = selectedIndex - 1;
		}
	}
	
	var orig = currentSelect.selectedIndex;
	currentSelect.selectedIndex = selectedIndex;
	
	var found = false;
	var foundColumn;
	var foundRow;
	var foundInput;
	var autoSaveFields = [currentSelect];
		
	var labelData = findObject(tableId + 'Labels');
	var isVertical = false;
	var labelCount = 1;
	if (labelData){
		labelData = labelData.innerHTML.split(',');
		isVertical = labelData[0] == 'true';
		labelCount = parseInt(labelData[1]);
	}
	var xStart = 0;
	var yStart = 0;
	var rowInc = 1;
	var colInc = 1;
	
	for (var i=xStart; i<rows.length; i=i+rowInc) {	
		var cols = rows[i].getElementsByTagName('td');
		if ( !cols || !cols.length ) {
			continue;
		}
		for (var j=yStart; j<cols.length; j=j+colInc) {	
			var inputs = cols[j].getElementsByTagName('SELECT');
			if ( !inputs || inputs.length < 1 ) {
				continue;
			}
			if ( found ) {
				if ( ( foundColumn == j && (ARROW_DOWN == key||ARROW_UP == key) ) ||
					(ARROW_RIGHT == key && (foundRow == i) && (j > foundColumn)) ) {
					if ( inputs.length > foundInput) {						
						inputs[foundInput].selectedIndex = selectedIndex;
						autoSaveFields.push(inputs[foundInput]);
					}
				}
			} else { 
				for (var k=0; k<inputs.length; k++) {
					if ( inputs[k].name == currentSelect.name ) {
				   		found = true;	
				   		foundRow = i;
				   		foundColumn = j;	
				   		foundInput = k;				   					
				   		if (isVertical){
				   			xStart = foundRow;
				   			rowInc = labelCount;
				   		}
				   		else{
				   			yStart = foundColumn;
				   			colInc = labelCount;
						}
				   		break;	   		
					}
				}
			}
		}	
	}
	
	if (autoSaveFields.length > 0){
		GLTransaction.saveDataList(autoSaveFields, fireAsyncMethod);
	}
	
	currentSelect.selectedIndex = orig;
	
	if (mz && ARROW_RIGHT == key){
		currentSelect.blur();
		setTimeout(function(){currentSelect.focus()}, 0);
		return false;
	}
}

/**
 * Provides methods to perform asynchronous updates of displayed tables. Similar to
 * GL_submitUpdateArrayForm except that it sends a request asynchronously instead of
 * submitting a form.
 */
GLUpdateArrayAsync = {
	submitUpdateArrayAsync : function(arrayUpdateUrlSpanId, action, arrayRowIndex, arrayColSize,
			arrayAddRowSize) {
		var arrayId = findObject(arrayUpdateUrlSpanId).innerHTML;
		   
		var http = new HTTP('editTransaction.do', this, 'arrayUpdateReady');
		http.addParameter('action', action);
		http.addParameter('arrayId', arrayId);
		http.addParameter('arrayRowIndex', arrayRowIndex);
		http.addParameter('arrayColSize', arrayColSize);
		http.addParameter('arrayAddRowSize', arrayAddRowSize);

		var transForm = GL_findForm('transactionForm');
		http.addParameter('transactionOpId', transForm.transactionOpId.value);
		http.addParameter('transactionId', transForm.transactionId.value);
		http.addParameter('pmBeginTrans', 'yes');
		http.addParameter('asyncUpdate', true); //request a JSON response
		http.isCallUpdateData = true; //ensures the response is paresed as JSON
		
		http.call();
	},
	/**
	 * Called once table has been udpated. Requests the redisplay of
	 * the updated table.
	 */
	arrayUpdateReady : function(text, http){
		var tableId = http.dbNode.tableId;
		var dataRequest = {'tableId': tableId, id: 'GL_Table'+tableId};
		GLAsyncDataFetcher.fetcher.addDataRequest(dataRequest);
	}
};

function GL_submitUpdateArrayForm(arrayUpdateUrlSpanId, action, arrayRowIndex, arrayColSize,
									arrayAddRowSize, arrayToRowIndex, targetArrayUpdateUrlSpanId, additionalParams) {
   var arrayId = findObject(arrayUpdateUrlSpanId).innerHTML;
   var targetArray = findObject(targetArrayUpdateUrlSpanId);
   var targetArrayId;
   if (targetArray)
   		 targetArrayId = targetArray.innerHTML;

   var transForm = GL_findForm('transactionForm');
   GL_findField(transForm, 'action').value = action;
   GL_findField(transForm, 'arrayId').value = arrayId;
   GL_findField(transForm, 'arrayRowIndex').value = arrayRowIndex;
   GL_findField(transForm, 'arrayColSize').value = arrayColSize;
   GL_findField(transForm, 'arrayAddRowSize').value = arrayAddRowSize;
   GL_findField(transForm, 'arrayToRowIndex').value = arrayToRowIndex;
   GL_findField(transForm, 'pageScrollLeft').value = document.body.scrollLeft;
   GL_findField(transForm, 'pageScrollTop').value = document.body.scrollTop;
   GL_findField(transForm, 'targetArrayId').value = targetArrayId;
   GL_addAllScrollPositions();
   
   for (var name in additionalParams){
   		var hidden = Core.addHidden(transForm, additionalParams[name]);
   		hidden.name = name;
   }
   
   if ( GL_isIE() ) {
   	transForm.target.value = '';
   } else {
   	transForm.target = '';
   }

   transForm.submit();
   
}

var gl_sortAcending = true;
var gl_sortTable;
var gl_sortType;
var gl_sortColumnIndex;
function GL_sortColumn(tableId, sortType) {
    gl_sortTable = findObject(tableId);
    gl_sortType = sortType;
    
    var evt = (evt) ? evt : ((window.event) ? event : null);
    var clickedHeaderCell = GL_getParentByName(evt.srcElement, 'th');
    gl_sortColumnIndex = -1;
    for (var i=0; i<gl_sortTable.rows[0].cells.length; i++) {
        if ( gl_sortTable.rows[0].cells[i] == clickedHeaderCell ) {
            gl_sortColumnIndex = i;
            break;
        }
    }    
    if ( gl_sortColumnIndex < 0 ) {
        return;
    }
    
    var prevScrollLeft = document.body.scrollLeft;
    var prevScrollTop = document.body.scrollTop;
    var newRows = new Array();
    var cnt = 0;
    for (var i=1; i<gl_sortTable.rows.length; i++) {
       newRows[cnt] = gl_sortTable.rows[i]; 
       cnt++;
    }    
    newRows.sort(GL_sort);
    if ( gl_sortAcending ) {
        newRows.reverse();
    }
    
    for (var i=0; i<newRows.length; i++) {
        gl_sortTable.tBodies[0].appendChild(newRows[i]);
    } 
    
    gl_sortAcending = gl_sortAcending ? false : true;
    
    document.body.scrollLeft = prevScrollLeft;
    document.body.scrollTop = prevScrollTop;  
    
}

function GL_sort(a, b) {
    var aStr = GL_getSortValue(a, gl_sortColumnIndex);
    var bStr = GL_getSortValue(b, gl_sortColumnIndex);
    if ( gl_sortType == 'number' ) {
        var aNum = parseFloat(aStr);
        if (isNaN(aNum)) aNum = 0;
        var bNum = parseFloat(bStr); 
        if (isNaN(bNum)) bNum = 0;
        return aNum - bNum;
   } else {
        if (aStr==bStr) return 0;
        if (aStr<bStr) return -1;
        return 1;   
   }
}
function GL_getSortValue(row, columnIndex) {
    var valueSpan = GL_findDOMObjectById(row.cells[columnIndex], 'span', 'sortValue');
    if ( valueSpan ) {
        return valueSpan.innerHMTL;
    } else { 
        return ts_getInnerText(row.cells[columnIndex]);
    }
}

function ts_getInnerText(el) {
    if (typeof el == "string") return el;
    if (typeof el == "undefined") { return el };
    if (el.innerText) return el.innerText;  //Not needed but it is faster
    var str = "";
    
    var cs = el.childNodes;
    var l = cs.length;
    for (var i = 0; i < l; i++) {
        switch (cs[i].nodeType) {
            case 1: //ELEMENT_NODE
                str += ts_getInnerText(cs[i]);
                break;
            case 3: //TEXT_NODE
                str += cs[i].nodeValue;
                break;
        }
    }
    return str;
}

function GL_getParentByName(node, tagName) {
    if (node == null) return null;
    else if (node.nodeType == 1 && node.tagName.toLowerCase() == tagName.toLowerCase())  
        return node;
    else
        return GL_getParentByName(node.parentNode, tagName);
}

function FieldObject(field, top, left) {
	this.field = field;
	this.top = top;
	this.left = left;
	this.offHeight;
	this.offWidth;	
	this.newHeight;
	this.newWidth;		
}

function GL_expandtables() {
	var rootId = '_transDisplayDataRoot';
	var namePrefix = 'nameSpan';
	var valuePrefix = 'valueSpan';
	
	var root = findObject(rootId);
	if ( !root || !root.childNodes ) {
		return;
	}
	
	var children = root.childNodes;
	var fields = new Array();
	var isOff = false;
	
	for (var i=0; i<children.length; i++) {
		var field = children[i];
		if ( field.id &&
			 field.clientHeight > 0 &&
			 field.clientWidth > 0 &&
		   (field.id.indexOf(namePrefix) > -1 || field.id.indexOf(valuePrefix) > -1) ) {
			
			var fObj = new FieldObject(field, GL_trimPx(field.style.top), GL_trimPx(field.style.left));							 
			fields[fields.length] = fObj; 
			var offHeight = field.scrollHeight - field.clientHeight;
			if ( offHeight > 0 ) {
				isOff = true;
				fObj.offHeight = offHeight + (field.offsetHeight - field.clientHeight);	
				fObj.newHeight = field.clientHeight + fObj.offHeight;
			}
			var offWidth = field.scrollWidth - field.clientWidth;
			if ( offWidth > 0 ) {
				isOff = true;
				fObj.offWidth = offWidth;	
				fObj.newWidth = field.clientWidth + fObj.offWidth;
			}			
		}
	}
	
	if ( !isOff || fields.length == 0 ) {
//		window.print();	
		return;
	}
	
	for (var i=0; i<fields.length; i++) {
		var fObj = fields[i];
		var field = fObj.field;		
			
		if ( fObj.offHeight > 0) {
			field.style.height = fObj.newHeight + 'px';
		}
		if ( fObj.offWidth > 0) {
			field.style.width = fObj.newWidth + 'px';
		}		
	}	
	
	fields.sort(GL_sortFieldObjectByTop);
	
	var offTotal = 0;
	for (var i=0; i<fields.length; i++) {
		var fObj = fields[i];
		var field = fObj.field;	
		if ( offTotal > 0 ) {
			field.style.top = (fObj.top + offTotal) + 'px';	
		} 	
		if ( fObj.offHeight > 0 ) {		
			offTotal += fObj.offHeight;
		}				
	}		
	
	var mainBody = findObject('GL_mainBody');
	var maxSpan = fields[fields.length-1].field;
	var height =  (maxSpan.offsetTop - mainBody.offsetTop) + maxSpan.offsetHeight + 30;
	mainBody.style.height = height + 'px';

//	window.print();	
}

function GL_sortFieldObjectByTop(a, b) {
	return a.top - b.top;
}

function GL_trimPx(val) {
	if ( !val ) {
		return 0;
	}
	var index = val.indexOf('px');
	if ( index > -1 ) {
		return val.substring(0, index) * 1;
	} else {
		val;
	}
}

function GL_asynchTableUpdate(action, arrayId, cbObject, cbMethod, arrayRowIndex, arrayColSize, arrayAddRowSize,
								additionalParams, passThroughParams){
	var params = (additionalParams) ? additionalParams : {};
	params['arrayId'] = arrayId;
	params['arrayRowIndex'] = arrayRowIndex;
	params['arrayColSize'] = arrayColSize;
	params['arrayAddRowSize'] = arrayAddRowSize;
	
	GL_asynchUpdate(action, params, cbObject, cbMethod, passThroughParams); 
}

function GL_asynchUpdate(action, params, cbObject, cbMethod, passThroughParams) {
	var http = new HTTP('editTransaction.do', cbObject, cbMethod);
	http.addParameter('action', action);

	var transForm = GL_findForm('transactionForm');
	http.addParameter('transactionId', GL_findField(transForm, 'transactionId').value);
	http.addParameter('transactionOpId', GL_findField(transForm, 'transactionOpId').value);
	http.addParameter('pmBeginTrans', 'yes');
	http.isCallUpdateData = true;
	http.passThroughParams = passThroughParams;
	
	if (params){
		for (var name in params){
			http.addParameter(name, params[name]);
		}
	}
	
	http.call();	
}

function GL_RowMover(arrayUpdateUrlSpanId, rowIndex, table){
	this.arrayUpdateUrlSpanId = arrayUpdateUrlSpanId;
	this.rowIndex = rowIndex;
	this.table = table;
}

GL_RowMover.prototype.build = function(){
	this.tbodyIndex = this.table.tBodies.length-1;
	var tbody = this.table.tBodies[this.tbodyIndex];
	this.addRowMouseOver();
	this.startRow = tbody.rows[this.rowIndex];
	Core.appendClassName(this.startRow, 'GL_tableRowToMove');
	this.setSelectedRow(this.startRow);
}

GL_RowMover.prototype.addRowMouseOver = function(){
	var rows = this.table.tBodies[this.tbodyIndex].rows;
	for (var i=0;i<rows.length;i+=1){
		Core.addEventHandler(rows[i], 'mouseover', GL_RowMover.onMouseOverRow);
		rows[i]._glIsMoveRowTarget = true;
	}
}

GL_RowMover.prototype.removeRowMouseOver = function(){
	var rows = this.table.tBodies[this.tbodyIndex].rows;
	for (var i=0;i<rows.length;i+=1){
		Core.removeEventHandler(rows[i], 'mouseover', GL_RowMover.onMouseOverRow);
		rows[i]._glIsMoveRowTarget = undefined;
	}
}

GL_RowMover.prototype.setSelectedRow = function(row){
	if (row.sectionRowIndex > this.selectedRow)
		this.table.tBodies[this.tbodyIndex].insertBefore(this.startRow, row.nextSibling);
	else
		this.table.tBodies[this.tbodyIndex].insertBefore(this.startRow, row);		
	this.selectedRow = row.sectionRowIndex;
}

GL_RowMover.prototype.endSelection = function(){
	this.removeRowMouseOver();
	Core.removeClassName(this.startRow, 'GL_tableRowToMove');
	if (this.grabImg)
		Core.removeClassName(this.grabImg, 'GL_rowMoveGrabTargetMouseOver');
	if (this.selectedRow != this.rowIndex){
		GL_submitUpdateArrayForm(this.arrayUpdateUrlSpanId, 'moveArrayRow', this.rowIndex, -1, -1, this.selectedRow);
	}
}

GL_RowMover.onMouseDown = function(arrayUpdateUrlSpanId, rowIndex, tableId, e){
	var tableSpanId = 'GL_Table' + tableId;
	var tableSpan = document.getElementById(tableSpanId);
	var tables = tableSpan.getElementsByTagName('table');
	var table = tables[0];
	var mover = new GL_RowMover(arrayUpdateUrlSpanId, rowIndex, table);
	mover.build();
	GL_RowMover.currentMoveRow = mover;
	Core.addEventHandler(document, 'mousemove', GL_RowMover.onMouseMove);
	Core.addEventHandler(document, 'mouseup', GL_RowMover.onMouseUp);
	return Core.preventDefault(e);
}

GL_RowMover.onMouseOverRow = function(e){
	var node = Core.getNode(e);
	while (!node._glIsMoveRowTarget){
		node = node.parentNode;
	}
	GL_RowMover.currentMoveRow.setSelectedRow(node);
}

GL_RowMover.onMouseMove = function(e){
	return Core.preventDefault(e);
}

GL_RowMover.onMouseUp = function(e){
	GL_RowMover.currentMoveRow.endSelection();
	GL_RowMover.currentMoveRow = null;
	Core.removeEventHandler(document, 'mousemove', GL_RowMover.onMouseMove);
	Core.removeEventHandler(document, 'mouseup', GL_RowMover.onMouseUp);
}

GL_RowMover.onGrabberMouseOver = function(img){
	if (!GL_RowMover.currentMoveRow)
		Core.appendClassName(img, 'GL_rowMoveGrabTargetMouseOver');
}

GL_RowMover.onGrabberMouseOut = function(img){
	if (GL_RowMover.currentMoveRow)
		GL_RowMover.currentMoveRow.grabImg = img;
	else
		Core.removeClassName(img, 'GL_rowMoveGrabTargetMouseOver');
}

function GL_TableSorter(){
}

GL_TableSorter.sortColumn = function(id, tableId, evt){
	var async = new GLAsyncTransaction(id, GLAsyncTransaction.EVENT_SORT_COLUMN);
	async.http.addParameter('eventParentArray', tableId);

	var evt = (evt) ? evt : ((window.event) ? event : null);
	if (evt.ctrlKey)
		async.http.addParameter('addToSort', true);
	async.call();
}