/*
 * Dynamic Data Grid Code
 */

var DEFAULT_ROWS = 25;
var dataGridItems = new Array();

var gridText_NextPage = 'Next Page';
var gridText_PreviousPage = 'Previous Page';
var gridText_Close = 'Close';
var gridText_Filter = 'Filter Results';
var gridText_FilterSearch = 'Search Criteria';
var gridText_FilterColumn = 'Column';
var gridText_Done = 'Done';

function showDataGrid(gridId, parentItem, ajaxResultSet, columnIds, columnStrings, numberOfRows, skin)
{
	var existingGrid = dataGridItems[gridId];
	if (null != existingGrid)
	{
		existingGrid.GridContents = ajaxResultSet;
		showElem(existingGrid.Id);
		existingGrid.LoadDataGrid(false, true);
		
		return existingGrid;
	}
	
	var newGrid 			= new DynamicDataGrid(gridId, parentItem);
	newGrid.GridContents   	= ajaxResultSet;
    newGrid.ColumnIds      	= columnIds;
    newGrid.ColumnStrings  	= columnStrings;
    
    if (null != skin)
        newGrid.Skin			= skin;
    
    if (numberOfRows)
    	newGrid.NumberOfRows	= numberOfRows;
    	
    newGrid.CreateDataGrid();
		
	showElem(newGrid.GridObject);
	dataGridItems[gridId] = newGrid;
	newGrid.LoadDataGrid(false, true);
		
	return newGrid;
}

function showFilteredGrid(gridId)
{
	var existingGrid = dataGridItems[gridId];
	if (null == existingGrid)
		return;
		
	var column = getElemValue(gridId+"_FilterColumn");
	var searchString = getElemValue(gridId+"_FilterSearchCriteria");
	
	existingGrid.Filter(column, searchString);
}

function sortDataGridColumn(gridId, column)
{
	var existingGrid = dataGridItems[gridId];
	if (null == existingGrid)
		return;
	
	existingGrid.Sort(column);
}

function dataGridNextPage(gridId, forward)
{
	var existingGrid = dataGridItems[gridId];
	if (null == existingGrid)
		return;
	
	existingGrid.LoadDataGrid(forward, false);
}

function dataGridRowClicked(gridId, rowId)
{
	var existingGrid = dataGridItems[gridId];
	if (null == existingGrid)
		return;
	
	existingGrid.HandleClickEvent(rowId);
}

function closeDataGrid(gridId)
{
	var existingGrid = dataGridItems[gridId];
	if (null == existingGrid)
		return;
	
	existingGrid.Close(true);
}

function updateItemStyle(gridId, itemNode)
{
	var existingGrid = dataGridItems[gridId];
	if (null == existingGrid)
		return;

	itemNode.className = existingGrid.Skin + "RowOver";
}

function resetItemStyle(gridId, itemNode, alternate)
{
	var existingGrid = dataGridItems[gridId];
	if (null == existingGrid)
		return;

	itemNode.className = (alternate) ? existingGrid.Skin + "RowAlternate" : existingGrid.Skin + "Row";
}

function showFilterSection(gridId)
{
	var existingGrid = dataGridItems[gridId];
	if (null == existingGrid)
		return;
		
	showElem(gridId+"_FilterSection");
}

function closeFilterSection(gridId)
{
	var existingGrid = dataGridItems[gridId];
	if (null == existingGrid)
		return;
		
	hideElem(gridId+"_FilterSection");
}


/**
 *
 * Filter helper object
 *
 **/

var FilterItems = function(columnName, searchString)
{
    this.columnName   = columnName;
    this.searchString = searchString;
    this.Results      = null;
}

FilterItems.prototype.GetResults = function()
{
    return this.Results;
}

FilterItems.prototype.GetColumnName = function()
{
    return this.columnName;
}


FilterItems.prototype.GetsearchString = function()
{
    return this.searchString;
}

/**
 *
 * DynamicDataGrid Class
 *
 **/

var DynamicDataGrid = function(gridId, parentItem)
{
    this.GridContents   = null;
    this.ColumnIds      = null;
    this.ColumnStrings  = null;
    this.Id				= gridId;
    this.ParentItem		= parentItem;
    this.NumberOfRows	= DEFAULT_ROWS;
    
    this.GridObject		= null;
    this.HeaderRow		= null;
    this.FooterRow		= null;
    this.CurrentPage	= 0;
    this.PreviousPageLink = null;
    this.NextPageLink 	  = null;
    
    this.OnItemSelected = null;
    this.OnGridClosed 	= null;
    
    this.Skin			= "dynamicDataGrid";
}

DynamicDataGrid.prototype.CreateDataGrid = function()
{
	var dataGrid = this.CreateNewElement('TABLE');
	this.ParentItem.parentNode.insertBefore(dataGrid, this.ParentItem);
	this.GridObject = dataGrid;
	this.GridObject.id = this.Id;
	this.GridObject.className = this.Skin;
	
	var topRow 			 = this.CreateNewElement('TBODY', null, this.GridObject);
	topRow   			 = this.CreateNewElement('TR', null, topRow);
	var topRowData		 = this.CreateNewElement('TD', null, topRow);
	
	
	var linkNode = this.CreateLinkNode('#', gridText_Filter, topRowData);
	topRowData.align = 'left';
	
	if (this.ColumnIds.length > 1)
		topRowData.colSpan 	 = (this.ColumnIds.length%2 == 0) ? this.ColumnIds.length/2 : (this.ColumnIds.length-1)/2;
	
	topRowData.className = this.Skin+'TopRow';
	linkNode.className = this.Skin+'Link';
	addDynamicEvent(linkNode, 'click', 'function() {showFilterSection(\''+this.Id+'\');}');
	this.CreateDataGridFilterSection(topRowData);
	
	topRowData		 = this.CreateNewElement('TD', null, topRow);
	topRowData.colSpan 	 = this.ColumnIds.length;
	topRowData.className = this.Skin+'TopRow';
	
	linkNode = this.CreateLinkNode('#', gridText_Close, topRowData);
	topRowData.align = 'right';
	linkNode.className = this.Skin+'Link';
	
	addDynamicEvent(linkNode, 'click', 'function() {closeDataGrid(\''+this.Id+'\');}');
	
	this.CreateDataGridRow();
}

DynamicDataGrid.prototype.CreateDataGridFilterSection = function(parent)
{
	var filterTable = this.CreateNewElement('TABLE', null, parent);
	filterTable.id = this.Id + "_FilterSection";
	filterTable.className = this.Skin+"FilterSection";
	filterTable.style.display = 'none';
	
	var topRowBody 	 = this.CreateNewElement('TBODY', null, filterTable);
	var topRow   	 = this.CreateNewElement('TR', null, topRowBody);
	topRow.className = this.Skin+"FilterSectionItem";
	
	rowData		 = this.CreateNewElement('TD', gridText_FilterColumn, topRow);
	rowData		 = this.CreateNewElement('TD', null, topRow);
	var columSelector = this.CreateNewElement('SELECT', null, rowData);
	columSelector.id = this.Id + "_FilterColumn";
	addDynamicEvent(columSelector, 'change', 'function() {showFilteredGrid(\''+this.Id+'\');}');
	
	for (var i=0; i<this.ColumnIds.length; ++i)
	{
		var newOption = this.CreateNewElement('OPTION', this.ColumnStrings[i], columSelector);
		newOption.value = this.ColumnIds[i]; 
	}
	
	topRow   	 = this.CreateNewElement('TR', null, topRowBody);
	topRow.className = this.Skin+"FilterSectionItem";
	
	rowData		 = this.CreateNewElement('TD', gridText_FilterSearch, topRow);
	rowData		 = this.CreateNewElement('TD', null, topRow);
	
	var searchCriteria = this.CreateNewElement('INPUT', null, rowData);
	searchCriteria.id = this.Id + "_FilterSearchCriteria";
	searchCriteria.length = 20;
	searchCriteria.type = 'text';
	addDynamicEvent(searchCriteria, 'keyup', 'function() {showFilteredGrid(\''+this.Id+'\');}');
	
	topRow   	 = this.CreateNewElement('TR', null, topRowBody);
	rowData		 = this.CreateNewElement('TD', null, topRow);
	rowData.className = this.Skin+"FilterSectionBottom";
	rowData.colSpan = 2;
	rowData.align = "left";
	
	var closeLink = this.CreateLinkNode('#', gridText_Done, rowData);
	closeLink.className = this.Skin+'LinkFilterSection';
	addDynamicEvent(closeLink, 'click', 'function() {closeFilterSection(\''+this.Id+'\');}');
}

DynamicDataGrid.prototype.CreateDataGridRow = function()
{
	/* create the headers
	 */
	this.HeaderRow = this.CreateNewElement('TBODY', null, this.GridObject);
	this.HeaderRow = this.CreateNewElement('TR', null, this.HeaderRow);
	
	/* create the header section
	 */
	for (var i=0; i<this.ColumnIds.length; ++i)
	{
		var rowItem = this.CreateNewElement('TD', null, this.HeaderRow);
		rowItem.id = this.GetColumnId(this.ColumnIds[i]);
		rowItem.className = this.Skin+'ColumnHeader';
		
		var linkNode = this.CreateLinkNode('#', this.ColumnStrings[i], rowItem);
		linkNode.className = this.Skin+'ColumnHeader';
		addDynamicEvent(linkNode, 'click', 'function() {sortDataGridColumn(\''+this.Id+'\', \''+this.ColumnIds[i]+'\');}');
	}

	/* add the body
	 */
	for (var i=0; i<this.NumberOfRows; ++i)
	{
		var rowId 	= this.GetRowId(i+1);
		var row 	= this.CreateNewElement('TBODY', null, this.GridObject);
		row 	= this.CreateNewElement('TR', null, row);
		row.id 		= rowId;
		
		for (var j=0; j<this.ColumnIds.length; ++j)
		{
			var rowItem = this.CreateNewElement('TD', null, row);
			rowItem.id = this.GetItemId(i+1, this.ColumnIds[j]);
			rowItem.className = this.Skin+'Item';

			addDynamicEvent(rowItem, 'click', 'function() {dataGridRowClicked(\''+this.Id+'\', '+i+');}');
		}
		
		var isAlternate = (i%2 == 0);
		row.className = (isAlternate) ? this.Skin+'Row' : this.Skin+'RowAlternate';
		
		addDynamicEvent(row, 'mouseover', 'function() {updateItemStyle(\''+this.Id+'\', getElem(\''+row.id+'\'));}');
		addDynamicEvent(row, 'mouseout',  'function() {resetItemStyle(\''+this.Id+'\', getElem(\''+row.id+'\'), '+!isAlternate+');}');
	}
	
	/* create the bottom
	 */
	this.FooterRow = this.CreateNewElement('TBODY', null, this.GridObject);
	this.FooterRow = this.CreateNewElement('TR', null, this.FooterRow);
	
	/* create the header section
	 */
	var colspanLen = (this.ColumnIds.length%2 == 0) ? this.ColumnIds.length/2 : (this.ColumnIds.length/2)+1;
	var containerObj = this.CreateNewElement('TD', null, this.FooterRow);
	containerObj.colSpan = colspanLen;
	containerObj.align = 'left';
	this.PreviousPageLink = this.CreateLinkNode('#', gridText_PreviousPage, containerObj);
	this.PreviousPageLink.className = this.Skin+'Link';
	addDynamicEvent(this.PreviousPageLink, 'click', 'function() {dataGridNextPage(\''+this.Id+'\', false);}');
	 
	containerObj = this.CreateNewElement('TD', null, this.FooterRow);
	containerObj.colSpan = colspanLen;
	containerObj.align = 'right';
	this.NextPageLink = this.CreateLinkNode('#', gridText_NextPage, containerObj);
	this.NextPageLink.className = this.Skin+'Link';
	addDynamicEvent(this.NextPageLink, 'click', 'function() {dataGridNextPage(\''+this.Id+'\', true);}');
	
	this.PreviousPageLink.style.display = 'none';
	this.NextPageLink.style.display = 'none';
}

DynamicDataGrid.prototype.CreateNewElement = function(elementName, contents, toAppend)
{
	var newItem = document.createElement(elementName);
    
    if (null != contents)
    	newItem.innerHTML = contents;
    
    if (null != toAppend)
    	toAppend.appendChild(newItem);
    
    return newItem;
}

DynamicDataGrid.prototype.CreateLinkNode = function(link, text, toAppend)
{
	var linkNode = this.CreateNewElement('A', text, toAppend);
	linkNode.setAttribute('href', link);
	
	return linkNode;
}

DynamicDataGrid.prototype.AddTextNode = function(toAppend, text)
{
	var tn = document.createTextNode(text);
	toAppend.appendChild(tn);
	
	return tn;
}
	
DynamicDataGrid.prototype.HideRows = function()
{
	for (var i=0; i < this.NumberOfRows; ++i)
	{
		hideElem(this.GetRowId(i+1));
	}
}

DynamicDataGrid.prototype.GetColumnId = function(columnId)
{
	return this.Id+'_header_'+(columnId);
}

DynamicDataGrid.prototype.GetRowId = function(rowId)
{
	return this.Id+'_row_'+(rowId);
}

DynamicDataGrid.prototype.GetItemId = function(rowId, columnId)
{
	return this.Id+'_row_'+(rowId)+ '_' + columnId;
}

DynamicDataGrid.prototype.LoadDataGrid = function(pageForward, initialLoad)
{
	this.HideRows();
	
	if (true != initialLoad)
	{
		if (pageForward)
			++this.CurrentPage;
		else
			--this.CurrentPage;
	}
	else
		this.CurrentPage = 0;
		
	var start = this.NumberOfRows*this.CurrentPage;
	var end = ((start + this.NumberOfRows) > this.GridContents.ResultSet.Count) ? this.GridContents.ResultSet.Count : start + this.NumberOfRows;
	
	for (var i=start; i < end; ++i)
	{
		var rowIndex = (i - start + 1);
		var gridContent = this.GridContents.ResultSet.ItemAt(i);
		
		if (null == gridContent)
			continue;
		
		for (var j=0; j<this.ColumnIds.length; ++j)
		{
			var columnId = this.ColumnIds[j];
			var contents = gridContent[columnId];
			setElemText(this.GetItemId(rowIndex, this.ColumnIds[j]), contents);
		}
		
		showElem(this.GetRowId(rowIndex));
	}
	
	this.PreviousPageLink.style.display = (start > 0) ? '' : 'none';
	this.NextPageLink.style.display = (end < this.GridContents.ResultSet.Count) ? '' : 'none';
}

DynamicDataGrid.prototype.Sort = function(column)
{
	if (null != this.GridContents && null != this.GridContents.ResultSet)
	{
		this.GridContents.ResultSet.Sort(column);
		this.LoadDataGrid(false, true);
	}
}

DynamicDataGrid.prototype.Filter = function(column, searchString)
{
	if (null != this.GridContents && null != this.GridContents.ResultSet)
	{
	    this.GridContents.ResultSet.SortByValue(column, searchString);
		this.LoadDataGrid(false, true);
	}
}

DynamicDataGrid.prototype.Close = function(canceled)
{
	this.GridObject.style.display = 'none';
	
	if (null != this.OnGridClosed)
		this.OnGridClosed(this, canceled);
}

DynamicDataGrid.prototype.HandleClickEvent = function(rowId)
{
	var index = (this.NumberOfRows*this.CurrentPage) + rowId;
	
	var data = this.GridContents.ResultSet.ItemAt(index);
	
	if (null != this.OnItemSelected)
		this.OnItemSelected(this, data, rowId);
	else if (null != window.onDataGridItemSelected)
		onDataGridItemSelected(this.Id, data, rowId);

}

DynamicDataGrid.prototype.SetSkin = function(skinName)
{
	var oldSkin = this.Skin;
	this.Skin = skinName;
	this.UpdateDomNodeSkin(oldSkin, this.GridObject);
}

DynamicDataGrid.prototype.UpdateDomNodeSkin = function(oldSkin, node)
{
	if (null == node)
		return;
		
	var nodeClass = node.className;
	if (null != nodeClass && nodeClass.indexOf(oldSkin) == 0)
		node.className = nodeClass.replace(oldSkin, this.Skin);
			
	if (node.hasChildNodes())
		this.UpdateDomNodeSkin(oldSkin, node.firstChild);
		
	while (null != (node = node.nextSibling))
	{
		var nodeClass = node.className;
		if (null != nodeClass && nodeClass.indexOf(oldSkin) == 0)
			node.className = nodeClass.replace(oldSkin, this.Skin);
			
		if (node.hasChildNodes())
			this.UpdateDomNodeSkin(oldSkin, node.firstChild);
	}
}

function addDynamicEvent(element, type, handler) 
{
	if ('function' != typeof handler)
	{
		var converter = '';
		handler = 'converter = '+handler+';';
		eval(handler);
		handler = converter;
	}
		
    if (element.addEventListener) 
    {
        element.addEventListener(type, handler, false);
    }
    else if (element.attachEvent) 
    {
        element.attachEvent("on" + type, handler);
    }
}