/*
 * Copyright © 2005, Ashley van Gerven (ashley.v__g__@g__mail.com - remove '_')
 * All rights reserved.
 *
 * Use of this script, with or without modification, is permitted
 * provided that the above copyright notice and disclaimer below is not removed.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 */

var updateSGDivWidthsExplorerTimer = null

function log(){
	if (!document.all){
		console.log(arguments);
	}
}

function initScrollingGrid(scrollingGridID, gridID, lastRowIsPager, startScrollLeft, startScrollTop){    
	if (navigator.userAgent.toLowerCase().indexOf("opera") != -1){ 
		// opera not supported
		return;		
	}
	if (!document.getElementById){ 
		// old browsers not supported
		return;
	}

	// get tables
	var HeadTable = $(scrollingGridID + "$tblHdr");
	var PagerTable = $(scrollingGridID + "$tblPager");
	var GridTable = $(gridID);

    if (GridTable == null || GridTable == "undefined"){        
        $(scrollingGridID).style.display = "none";
        return;
    }
	
	// get the header table row
	var HeadTableBody = getTableBody(HeadTable);
	var HeadTableBodyRow = getFirstRow(HeadTableBody);

	// get the gridview table's header row
	var GridTableHead = getTableHead(GridTable);
	var GridTableHeadRow = getFirstRow(GridTableHead);
	
	// get the gridview table's body
	var GridTableBody = getTableBody(GridTable);
	
	// delete empty TR on header table
	HeadTableBody.removeChild(HeadTableBodyRow);

	// move the header row from gridview table to the header table
	HeadTableBody.appendChild(GridTableHeadRow);

	// if grid pager is last row then move it below the scrolling DIV (i.e. freeze it)	
	if (lastRowIsPager){
		// get pager table's first row
		var PagerTableBody = getTableBody(PagerTable);
		var PagerTableBodyRow = getFirstRow(PagerTableBody);

		// get datagrid table's last row
		var GridTableLastRow = getLastRow(GridTableBody);
		if (getFirstCell(GridTableLastRow).getAttribute("colspan") > 1){
		    // delete empty TR on the pager table
		    PagerTableBody.removeChild(PagerTableBodyRow);

		    // move the footer from gridview table to the pager table
		    PagerTableBody.appendChild(GridTableLastRow);

		    // set table width to match content DIV
		    PagerTable.width = $(scrollingGridID + "$divContent").offsetWidth;
		}
	}

	// make both header and content column widths the same
	setColumnWidths(scrollingGridID, gridID);

	if (window.attachEvent){  
		// IE only - resize DIVs now + on resize	
		updateSGDivWidthsExplorer();
		window.attachEvent("onresize", scheduleUpdateSGDivWidthsExplorer);
	}
}

// match up column widths
function setColumnWidths(scrollingGridID, gridID){ 
	// reset scroll positions since FF remembers them on page-refresh
	$(scrollingGridID + "$divHdr").scrollLeft = 0;
	$(scrollingGridID + "$divContent").scrollLeft = 0;
	$(scrollingGridID + "$divContent").scrollTop = 0;

	// ensure enough space to expand columns
	$(scrollingGridID + "$headerCntr").style.width = "10000";
	$(scrollingGridID + "$contentCntr").style.width = "10000";

	var widths = new Array();
	var totalWidth = 0;

	// get the tables
	var HeadTable = $(scrollingGridID + "$tblHdr");
	var PagerTable = $(scrollingGridID + "$tblPager");
	var GridTable = $(gridID);

	// get header table row
	var HeadTableBody = getTableBody(HeadTable);
	var HeadTableBodyRow = getFirstRow(HeadTableBody);

	// get content table body
	var GridTableBody = getTableBody(GridTable);
	// get the index of the second content row 
	// (changed because in my case the first often contains a group header, will return first if there's only one row)
	var GridTableBodyRowIndex = secondChildElIndex(GridTableBody, "TR");

	if (GridTableBodyRowIndex == -1){ 
		// no content rows
		$(scrollingGridID + "$contentCntr").style.width = 1;
		return;
	}
	// get the content row
	var GridTableBodyRow = GridTableBody.childNodes[GridTableBodyRowIndex];

	// get the cellpadding for the grid
	var cellPadding = parseInt(GridTable.getAttribute("cellpadding"));
	for (var i=0; i<HeadTableBodyRow.childNodes.length; i++){
		if (HeadTableBodyRow.childNodes[i].nodeName != "TD" && HeadTableBodyRow.childNodes[i].nodeName != "TH"){
			// skip #text nodes
			continue;
		}
		            
		// TD element for the header row
		var HeadTableCell = HeadTableBodyRow.childNodes[i];
		// TD element for the content row
		var GridTableCell = GridTableBodyRow.childNodes[i];

		// get width of of the header or content cell (depends which is widest)
		var width
		if (HeadTableCell.offsetWidth > GridTableCell.offsetWidth){
			width = HeadTableCell.offsetWidth;
		} else {
			width = GridTableCell.offsetWidth;
		}
		log(i, width);
		// add cell width to total width
		totalWidth += width;
		
		if (!document.all){
			// FF: subtract cellpadding from cell width
			width += -2 * cellPadding; 
		} else {
			// IE: add cellpadding to total width
			totalWidth += 2 * cellPadding; 
		}
		
		// update cell widths
		HeadTableCell.style.width = width + "px"; 
		GridTableCell.style.width = width + "px"; 
	}	

	// update the content container table width from 10000 to correct width
	$(scrollingGridID + "$contentCntr").style.width = totalWidth + "px";
	// update the header container table width from 10000 to correct width
	// add 17 pixels to account for the scrollbar
	$(scrollingGridID + "$headerCntr").style.width = totalWidth + 17 + "px";	
}

// IE resize event handler
function scheduleUpdateSGDivWidthsExplorer(){
	clearTimeout(updateSGDivWidthsExplorerTimer);
	updateSGDivWidthsExplorerTimer = setTimeout("updateSGDivWidthsExplorer()", 20);
}

// IE only - update widths for all ScrollingGrids according to their container table (since content of table is clipped)
function updateSGDivWidthsExplorer(){
	var arr = document.getElementsByTagName("TABLE");
	for (i=0; i<arr.length; i++){
		if (arr[i].getAttribute("NAME") == "ScrollingGrid"){
			var scrollingGridID = arr[i].id;
			var headerReduction = 0;
			if ($(scrollingGridID + "$divHdr").style.marginRight != ""){
				headerReduction = parseInt($(scrollingGridID + "$divHdr").style.marginRight);
			}

			var footerReduction = 0;
			if ($(scrollingGridID + "$tblPager") != null && $(scrollingGridID + "$tblPager").style.marginRight != ""){
				footerReduction = parseInt($(scrollingGridID + "$tblPager").style.marginRight);
			}

			try {
				$(scrollingGridID + "$divHdr").style.width = $(scrollingGridID).clientWidth - headerReduction;
				$(scrollingGridID + "$divContent").style.width = $(scrollingGridID).clientWidth;
				$(scrollingGridID + "$tblPager").style.width = $(scrollingGridID).clientWidth - footerReduction;
			}
			catch (err){}

			updateScroll($(scrollingGridID + "$divContent"), scrollingGridID);
		}
	}
}

function getTableHead(tbl){
	return tbl.childNodes[firstChildElIndex(tbl, "THEAD")];
}

function getTableBody(tbl){
	return tbl.childNodes[firstChildElIndex(tbl, "TBODY")];
}

function getFirstRow(section){
	return section.childNodes[firstChildElIndex(section, "TR")];
}

function getLastRow(section){
	return section.childNodes[lastChildElIndex(section, "TR")];
}

function getFirstCell(row){
    return row.childNodes[firstChildElIndex(row, "TD")];
}

// find the index of first child element (e.g. TBODY) 
function firstChildElIndex(el, searchFor){
	for (var i=0; i<el.childNodes.length; i++){
		if (el.childNodes[i].nodeName == searchFor){
			return i;
		}
	}
	return -1;
}

// find the index of the second child element (e.g. TR) 
// returns the first element if there is only one
function secondChildElIndex(el, searchFor){
    var found = false
	for (var i=0; i<el.childNodes.length; i++){
		if (el.childNodes[i].nodeName == searchFor){
			if (found){
				return i;
			} else {
				found = true;
			}
		}
	}
	return firstChildElIndex(el, searchFor);
}

// find the index of last child element
function lastChildElIndex(el, searchFor){
	for (var i=el.childNodes.length-1; i>=0; i--)	{
		if (el.childNodes[i].nodeName == searchFor){
			return i;
		}
	}
	return -1;
}

// content scroll event handler (matches the header row with the horizontal scroll position of content)
function updateScroll(divObj, scrollingGridID){
    try{
	    if ($(scrollingGridID + "$divHdr") != null){
		    $(scrollingGridID + "$divHdr").scrollLeft = divObj.scrollLeft;
	    }
	    // save scroll position to hidden input
	    $(scrollingGridID + "$hdnScrollPos").value = divObj.scrollLeft + "-" + divObj.scrollTop;
	    }
	catch (err) {}
}

function setContentScrollPos(sgID, left, top){
	var divContent = $(sgID + "$divContent");
	divContent.scrollLeft = left;
	divContent.scrollTop = top;
}


// ************************************
// *        Utility functions         *
// ************************************

// scale the content DIV height with the browser window height minus specified height [reduceBy]
function scaleHeightToBrowser(sgID, gridID, reduceBy, minHeight){    
	var newHeight = (document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight) - reduceBy;
	var grid = $(gridID);
	var gridHeight = (grid != null && grid != "undefined") ? grid.offsetHeight + 17 : 10000;
	if (gridHeight < newHeight){
	    newHeight = gridHeight;
	} else if (newHeight < minHeight){
		newHeight = minHeight;
	}
	$(sgID + "$divContent").style.height = newHeight + 'px';
}

// scroll the content by cellspacing height to get rid of double border
function adjustScrollTop(scrollingGridID, gridID){
	$(scrollingGridID + "$divContent").scrollTop = parseInt($(gridID).getAttribute("cellspacing"));
}

// reduce the height of the header div by cellspacing height to get rid of double border (alternate method to adjustScrollTop)
function cropHeader(scrollingGridID, gridID){
	$(scrollingGridID + "$divHdr").style.height = $(scrollingGridID + "$divHdr").offsetHeight - parseInt($(gridID).getAttribute("cellspacing"));
}
