
/*	Sticky Table Row script by Steve Cochrane
	http://stevecochrane.com/sticky-table-row/ */
	
/*	Last updated: July 5, 2007
	If you would like to use this in your sites I only ask that you include the above comment.
	Suggestions, questions? hq@stevecochrane.com
*/

/*	HELPER FUNCTIONS ------------------------------------------------------------------------------- */

//	Originally by Simon Willison, found in "DOM Scripting" by Jeremy Keith
function addLoadEvent(func) {
	var oldonload = window.onload;
	if (typeof window.onload != 'function') {
		window.onload = func;
	} else {
		window.onload = function() {
			oldonload();
			func();
		}
	}
}

//	by Peter-Paul Koch & Alex Tingle
function findPosY(obj) {
	var curtop = 0;
	if (obj.offsetParent)
		while(1)
		{
		  curtop += obj.offsetTop;
		  if (!obj.offsetParent)
			break;
		  obj = obj.offsetParent;
		}
	else if (obj.y)
		curtop += obj.y;
	return curtop;
}

//	Written by Jonathan Snook, http://www.snook.ca/jonathan
//	Add-ons by Robert Nyman, http://www.robertnyman.com
function getElementsByClassName(oElm, strTagName, strClassName){
	var arrElements = (strTagName == "*" && oElm.all)? oElm.all : oElm.getElementsByTagName(strTagName);
	var arrReturnElements = new Array();
	strClassName = strClassName.replace(/-/g, "\-");
	var oRegExp = new RegExp("(^|\s)" + strClassName + "(\s|$)");
	var oElement;
	for(var i=0; i<arrElements.length; i++){
		oElement = arrElements[i];
		if(oRegExp.test(oElement.className)){
			arrReturnElements.push(oElement);
		}
	}
	return (arrReturnElements)
}

//	Adds the second array onto the end of the first, keeping its elements properly separated as before
function concatArrays(baseArray, newAddition) {
	var baseArrayLength = baseArray.length;
	for (var i = 0; i < newAddition.length; i++) {
		baseArray[baseArrayLength + i] = newAddition[i];
	}
	return baseArray;
}

/*	(END HELPER FUNCTIONS) */

/*	THE NEW STUFF -------------------------------------------------------------------------------------- */

function positionCommandBars() {
	var scrollHeight, viewportHeight, cmdbarsUnfixed, cmdbarsFixed, cmdbars, cmdbarsLength, breathingRoom,
		cmdbarParentTable, cmdbarTopLeft, cmdbarHeight, cmdbarBottomLeft, cmdbarParentTableTopLeft, bottomLeftViewport;
	
	//	Need to find the distance that the user has scrolled down the page, in pixels,
	//	and also the current height of the user's viewport
	if (typeof (window.pageYOffset) == "number") {
		// Non-IE modern browsers
		scrollHeight = window.pageYOffset;
		viewportHeight = window.innerHeight;
	} else if (document.documentElement) {
		// IE in Standards Compliance Mode
		scrollHeight = document.documentElement.scrollTop;
		viewportHeight = document.documentElement.clientHeight;
	} else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
		// DOM compliant method, IE Quirks Mode
		scrollHeight = document.body.scrollTop;
		viewportHeight = document.body.clientHeight;
	} else {
		return false;
	}

	//	In order to allow for multiple sticky table rows in the same page, I unfortunately have to double up
	//	my use of classes. First, we have to find all unfixed and fixed command bars, and combine these into one array.
	cmdbarsUnfixed = getElementsByClassName(document, "div", "cmdbar");
	cmdbarsFixed = getElementsByClassName(document, "div", "cmdbar fixed");
	cmdbars = concatArrays(cmdbarsUnfixed, cmdbarsFixed);
	cmdbarsLength = cmdbars.length;
	breathingRoom = 80;  // extra space to be allowed for before the command bar unfixes
	
	//	For each command bar in the page
	for (var i = 0; i < cmdbarsLength; i++) {
		
		//	Move up the DOM until we find the table that holds the command bar
		cmdbarParentTable = cmdbars[i].parentNode;
		while (cmdbarParentTable.nodeName != "TABLE") {
			cmdbarParentTable = cmdbarParentTable.parentNode;
		}
		
		//	Find info about the command bar
		cmdbarTopLeft = findPosY(cmdbars[i]); // The y-position of the command bar's top left corner
		cmdbarHeight = cmdbars[i].offsetHeight; // The height of the command bar
		cmdbarBottomLeft = cmdbarTopLeft + cmdbarHeight; // The y-position of the command bar's bottom left corner
	
		//	Find necessary info about the rest of the page
		//	This is the top left corner of the table, plus some extra breathing room so that the command bar
		//	never goes over the headers of the table.
		cmdbarParentTableTopLeft = findPosY(cmdbarParentTable) + breathingRoom;
		bottomLeftViewport = scrollHeight + viewportHeight; // The y-position of the lower left corner of the user's viewport

		//	Now we determine what to do with the command bar
		//	If the table isn't viewable on the page yet (entirely off the bottom edge)
		if (bottomLeftViewport < cmdbarParentTableTopLeft) {
			cmdbars[i].className = "cmdbar"; // the command bar should not be visible, so unfix it
		} else if (bottomLeftViewport > cmdbarBottomLeft) { // If the bottom corner of the user's viewport is below the bottom corner of the command bar,
			if (cmdbars[i].className == "cmdbar fixed") { // and the bar is currently fixed,
				cmdbars[i].className = "cmdbar"; // unfix it
			}
			//	If it is not currently fixed there is no change necessary for now, leave it alone
		} else { // The command bar must be off the bottom of the viewport
			if (cmdbars[i].className == "cmdbar") { // If this is true and it is not currently given fixed positioning,
				cmdbars[i].className = "cmdbar fixed"; // give it fixed positioning
			}
			//	If it is currently fixed there is no change necessary for now, leave it alone
		}
	}
}

addLoadEvent(positionCommandBars);
window.onscroll = positionCommandBars;
