var elementsToScroll			= new Array();
var elementsToSnap  			= new Array();
var startingScrollOffsets		= new Array();
var maxScrollOffsets			= new Array();
window.onscroll					= scrollWindow;
window.onresize					= scrollWindow;
var previousScrollTop			= -1;
var previousScrollLeft			= -1;
var previousSnapLeft			= -1;
var previousBodyClientWidth		= -1;
var scrollWindowStarted			= false;
var altScrollingParent			= null;
var altScrollingParentOffsets	= new Array();
var elementsToScrollOffsets 	= new Array();

function scrollWindowStart()
{
	if ( scrollWindowStarted )
	    return;

    scrollWindowStarted = true;
    scrollRecalc();
    
    if ( window.createPopup ) //IE
	    document.body.onresizeend   = resizeContent;
	else
	    window.addEventListener("resize" , resizeContent, false);
}

function scrollRecalc()
{
    if ( window.createPopup ) //IE
    {
        for ( var i = 0; i < elementsToScroll.length; i++ )
	    {			
		    var elementToScroll = elementsToScroll[i];
    		
		    if ( elementToScroll.nodeName == "TR" )
		        while ( elementToScroll.nodeName != "TABLE" )
		            elementToScroll = elementToScroll.parentNode;
    		
		    elementsToScrollOffsets[i] = -nodeToPoint( elementToScroll, false ).y;
	    }
	}
	else //FF
	{
	    for ( var i = 0; i < elementsToScroll.length; i++ )
	    {
	        var floatTR     = elementsToScroll[i];
	        var baseTR      = floatTR.nextSibling.nextSibling;
            var floatPt     = nodeToPoint( floatTR, false );
            var basePt      = nodeToPoint( baseTR, false );
            
            syncTableElements( baseTR, floatTR, true );
            elementsToScrollOffsets[i] = basePt.y;
        }
	}
}

function scrollParentStart( altScrollingParentID )
{
    if ( window.createPopup ) //IE
    {
        altScrollingParent = document.getElementById( altScrollingParentID );
	
	    if ( altScrollingParent != null )
	    {
		    altScrollingParent.onscroll	= scrollWindow;
		    var altScrollingParentTop	= nodeToPoint( altScrollingParent, false ).y
    		
		    for ( var i = 0; i < elementsToScroll.length; i++ )
		    {			
			    var elementToScroll				= elementsToScroll[i];
			    altScrollingParentOffsets[i]	= nodeToPoint( elementToScroll, false ).y - 
				    altScrollingParentTop;
		    }
	    }
    	
	    scrollWindowStart();
    }
    else //FF
    {
        altScrollingParent = document.getElementById( altScrollingParentID );
	
	    if ( altScrollingParent != null )
	    {
	        //altScrollingParent.addEventListener("scroll" , scrollWindow, false);
		    var altScrollingParentTop	= nodeToPoint( altScrollingParent, false ).y
    		
    		for ( var i = 0; i < elementsToScroll.length; i++ )
		    {			
			    var elementToScroll				= elementsToScroll[i];
			    altScrollingParentOffsets[i]	= -nodeToPoint( elementToScroll, false ).y; 
				//altScrollingParentOffsets[i]    = -altScrollingParentTop;
		    }
	    }
	
        scrollWindowStart();
    }
}

function resizeContent()
{
    scrollRecalc();
    scrollWindow();
}

var scrollTimerID = -1;
function scrollWindow()
{
    setWindowScroll( 150, true );
    scrollButtons();
    doWindowScroll();
    getCoords();
}

function setWindowScroll( time, repeatTimer )
{
    if ( scrollTimerID >= 0 )
    {
        clearTimeout( scrollTimerID );
        scrollTimerID = -1;
    }
    
    scrollTimerID = window.setTimeout( 'doExpensiveScrolls(' + repeatTimer + ')', time );
}

function doExpensiveScrolls( repeatTimer )
{
    scrollSnap();
	
	if ( repeatTimer )
	{
	    //one second after the last run, make sure it synchronizes
	    setWindowScroll( 1000, false );
	}
}

function doWindowScroll()
{
    var scrollOff = 0;
	var scrollTop = ( window.createPopup ? document.body.scrollTop : window.pageYOffset );
	
	if ( altScrollingParent != null )
	{
		scrollOff = altScrollingParent.scrollTop;
		scrollTop += scrollOff;
	}//add in space between element and scrolling parent

	if ( previousScrollTop != scrollTop )
	{        
	    previousScrollTop = scrollTop;
		
		//vertical scrolling to keep elements in view
		for ( var i = 0; i < elementsToScroll.length; i++ )
		{			
			var elementToScroll = elementsToScroll[i];
			var startOffset     = elementsToScrollOffsets[i];
			var offset          = startOffset + scrollTop;
			
			if ( !window.createPopup ) //FF
			{
			    if ( scrollTop > startOffset )
			        offset -= startOffset;
			    else
			        offset = startOffset;
			        
			    if ( offset < startOffset )
			        offset = startOffset;
			}
			    
			if ( altScrollingParent != null )
			{
				offset = scrollOff - altScrollingParentOffsets[i];
				//alert( altScrollingParentOffsets[i] );
		    }
			
			var scrollParent = elementToScroll.parentNode;
			if ( scrollParent.tagName == "TBODY" )
				scrollParent = scrollParent.parentNode;
		    
		    if ( offset > 0 )
			{
				var maxOffset = scrollParent.offsetHeight - elementToScroll.clientHeight;
				
				if ( !window.createPopup ) //FF
				    maxOffset += startOffset;
				
				if ( offset > maxOffset )
					elementToScroll.style.top = maxOffset + "px";
				else
					elementToScroll.style.top = offset + "px";
			}
			else
				elementToScroll.style.top = "0px";
		}
	}
}

var previousButtonPadding	= 0;
var BASE_BUTTON_PADDING		= 4;
var hasNoButtons			= false;

function scrollButtons()
{
	if ( hasNoButtons || window.name.indexOf( "popup" ) == 0 )
		return;
		
	try
	{
		if ( buttonCellCount == undefined || buttonCellCount == null )
		{
			hasNoButtons = true;
			return;
		}
	}
	catch ( e )
	{
		hasNoButtons = true;
		return
	}
	
	if ( previousScrollLeft != document.body.scrollLeft || 
		previousBodyClientWidth != document.body.clientWidth )
	{
	    previousScrollLeft		= document.body.scrollLeft;
		previousBodyClientWidth = document.body.clientWidth;
		
		//horizontal scrolling to keep button cells barely in view
		var buttonPadding = document.body.scrollWidth - document.body.clientWidth - document.body.scrollLeft + BASE_BUTTON_PADDING - 1;
		var buttonCell;
		var buttonRelation;
		var buttonRelationWidth;
		var thisPadding;
		var paddingLeft;
		
		if ( !window.createPopup && document.body.scrollWidth - 16 <= document.body.clientWidth )
		    buttonPadding -= 16; //fix the button offsets in FF
		
		if ( buttonPadding > 0 || previousButtonPadding > BASE_BUTTON_PADDING )
		{
			if ( buttonPadding < BASE_BUTTON_PADDING )
				buttonPadding = BASE_BUTTON_PADDING;
			previousButtonPadding = buttonPadding;
			
			for ( var i = 0; i < buttonCellCount; i++ )
			{
				buttonCell = document.getElementById( "buttonCell" + i );
				
				if ( buttonCell == null || buttonCell == undefined )
					continue; //skip a lower row that did not get added
				
			    if ( buttonCell.childNodes.length == 0 )
			        continue;
			        
			    buttonRelation = buttonCell.childNodes[ buttonCell.childNodes.length - 1 ];
			    if ( buttonRelation.offsetLeft + buttonRelation.offsetWidth >= buttonRelation.offsetWidth )
			    {
			        paddingLeft = Number( buttonCell.style.paddingRight.replace( 'px', '' ) );
			        
			        if ( paddingLeft == 0 ) //the first time, let it set to whatever
			            buttonRelationWidth = buttonPadding;
			        else //after the first time, prevents crazy expansion of the page
			            buttonRelationWidth = buttonCell.childNodes[0].offsetLeft + paddingLeft;
			        
			        thisPadding = buttonPadding;
			        if ( thisPadding > buttonRelationWidth )
			            thisPadding = buttonRelationWidth - 1;
        
                    buttonCell.style.paddingRight = thisPadding;
			        continue;
			    }
				
				buttonCell.style.paddingRight = buttonPadding;
			}
		}
	}
}

function addElementToScroll( element )
{
	if ( element != null && element != undefined )
	{
		elementsToScroll.push( element );
		startingScrollOffsets.push( null );
	}
}

//
//Snapping Columns
//
var lastSnapHeader = null;
function addElementToSnap( tbl, colIX, linkToPrevious )
{
    if ( tbl == null || tbl == undefined )
        return;
        
    var tblID           = tbl.id;
    var addedClassName  = tblID + '_' + colIX + '_s';
    
    while ( tbl.nodeName != "TABLE" )
        tbl = tbl.parentNode;
    
    var row;
    var tblPt = nodeToPoint( tbl, false );
    for ( var i = 0; i < tbl.rows.length; i++ )
    {
        row = tbl.rows[i];
        snapTableCell( row.cells[colIX], row.cells[ row.cells.length - 1 - colIX], tblPt,
            i == tbl.rows.length - 1 );
    }
    
    var snapData = new colSnapData( tbl, addCSSClass( '.' + addedClassName ),
        addCSSClass( '.' + addedClassName + 'h' ), tbl.rows[tbl.rows.length - 1].cells[colIX],
        lastSnapHeader, ( linkToPrevious ? elementsToSnap[ elementsToSnap.length - 1 ] : null ),
        colIX, 0 );
     
    var origPt  = nodeToPoint( snapData.refCell, false );
    var width   = snapData.refCell.offsetWidth;
    
    if ( window.createPopup ) //IE
    {
        width = snapData.refCell.nextSibling.offsetLeft - snapData.refCell.offsetLeft;
        width -= 10;
        snapData.width = width;
        snapData.classS.style.left      = ( origPt.x - tblPt.x ) + 'px';
        snapData.classH.style.left      = ( origPt.x - tblPt.x ) + 'px';
    }
    else
    {
        width = snapData.refCell.nextSibling.nextSibling.offsetLeft - snapData.refCell.offsetLeft;
        width -= 6;
        snapData.width = width;
                            
        snapData.classS.style.left      = origPt.x + 'px';
        snapData.classH.style.left      = ( origPt.x - tblPt.x ) + 'px';
    }
    snapData.classS.style.width     = width + 'px';
    snapData.classH.style.width     = width + 'px';
    
    elementsToSnap.push( snapData );
}

function snapTableCell( baseCell, floatCell, tblPt, isLastRow )
{
    var basePt              = nodeToPoint( baseCell, false );
    var isInScrollHeader    = floatCell.className.indexOf( 'wLSnH' ) >= 0;
    var isUnderHeader       = floatCell.parentNode.className.indexOf( 'wLUHR' ) >= 0;
    var isFooter            = baseCell.parentNode.className.indexOf( 'wLFR' ) >= 0;
    
    if ( isInScrollHeader )
    {
        if ( !isUnderHeader )
            lastSnapHeader = floatCell;

        floatCell.style.zIndex       = ( isInScrollHeader ? ( isUnderHeader ? '-1' : '1100' ) : '700' );
        floatCell.style.position     = 'absolute';
    }
    
    if ( window.createPopup ) //IE
    {
        floatCell.style.height       = baseCell.offsetHeight + "px";
        floatCell.style.top          = ( basePt.y - tblPt.y ) + "px";
    }
    else
    {
        var hOff = ( isInScrollHeader ? 2 : ( isLastRow ? 6 : 0 ) );
        floatCell.style.height       = ( baseCell.offsetHeight - hOff ) + "px";
        floatCell.style.top          = ( isInScrollHeader ? '0px' : ( isFooter ? basePt.y - 1 : basePt.y ) + "px" );
    }
}

function snapTableCellY( baseCell, floatCell, tblPt )
{
    var basePt              = nodeToPoint( baseCell, false );
    var isInScrollHeader    = floatCell.className.indexOf( 'wLSnH' ) >= 0;
    var isUnderHeader       = floatCell.parentNode.className.indexOf( 'wLUHR' ) >= 0;
    var isFooter            = baseCell.parentNode.className.indexOf( 'wLFR' ) >= 0;
    
    if ( window.createPopup ) //IE
        floatCell.style.top = ( basePt.y - tblPt.y ) + "px";
    else
        floatCell.style.top = ( isInScrollHeader ? '0px' : ( isFooter ? basePt.y - 1 : basePt.y ) + "px" );
}

function colSnapData ( tbl, classS, classH, refCell, hdCell, prevData, colIX, width )
{
    this.tbl        = tbl;
    this.classS     = classS;
    this.classH     = classH;
    this.refCell    = refCell;
    this.hdCell     = hdCell;
    this.prevData   = prevData;
    this.colIX      = colIX;
    this.width      = width;
}

function resetSnapY()
{
    var snapData;
    var row;
    var tblPt;
    var tbl;
    var colIX;
    for ( var s = 0; s < elementsToSnap.length; s++ )
    {
        snapData    = elementsToSnap[s];
        tbl         = snapData.tbl;
        colIX       = snapData.colIX;
        tblPt       = nodeToPoint( tbl, false );
        for ( var i = 0; i < tbl.rows.length; i++ )
        {
            row = tbl.rows[i];
            snapTableCellY( row.cells[colIX], row.cells[ row.cells.length - 1 - colIX], tblPt );
        }
    }
}

function scrollSnap()
{
    var snapOff     = 0;
    var isIE        = ( window.createPopup ? true : false );
	var snapLeft    = ( isIE ? document.body.scrollLeft : window.pageXOffset );
	
	if ( previousSnapLeft != snapLeft )
	{        
	    previousSnapLeft = snapLeft;
		
		//horizontal scrolling to keep elements in view
		for ( var i = 0; i < elementsToSnap.length; i++ )
		{	
		    var elementToSnap   = elementsToSnap[i];
		    var tblLeft         = nodeToPoint( elementToSnap.tbl, false ).x;
			var startOffset     = nodeToPoint( elementToSnap.refCell, false ).x;
			var offset          = startOffset + snapLeft;
			var prevData        = elementToSnap.prevData;   
			
			
			if ( prevData != null )
                offset = prevData.lastOffset + startOffset -
			        nodeToPoint( prevData.refCell, false ).x;//diff between starting offsets
			else
			{
		        if ( snapLeft > startOffset )
		            offset -= startOffset;
		        else
		            offset = startOffset;
			        
		        if ( offset < startOffset )
		            offset = startOffset;
			}
		  
			if ( offset > 0 )
			{
				var maxOffset = elementToSnap.tbl.offsetWidth - elementToSnap.refCell.clientWidth;
			
				if ( !window.createPopup ) //FF
				    maxOffset += startOffset;
				
				if ( offset > maxOffset )
				{
					elementToSnap.classS.style.left = ( maxOffset - ( isIE ? tblLeft : 0 ) ) + "px";
					elementToSnap.classH.style.left = ( maxOffset - tblLeft ) + "px";
				    elementToSnap.lastOffset        = maxOffset;
				}
				else
				{
					elementToSnap.classS.style.left = ( offset - ( isIE ? tblLeft : 0 ) ) + "px";
					elementToSnap.classH.style.left = ( offset - tblLeft ) + "px";
				    elementToSnap.lastOffset        = offset;
				}
			}
			else
			{
				elementToSnap.classS.style.left = "0px";
				elementToSnap.classH.style.left = "0px";
				elementToSnap.lastOffset       = 0;
			}
		}
	}
}

//
//START Remember Scroll Position
//
var scrollX;
var scrollY;
function getCoords()
{
	var x, y;

	if (document.all)
	{
		if (!document.documentElement.scrollLeft)
			x = document.body.scrollLeft;
		else
			x = document.documentElement.scrollLeft;

		if (!document.documentElement.scrollTop)
			y = document.body.scrollTop;
		else
			y = document.documentElement.scrollTop;
	}   
	else
	{
		x = window.pageXOffset;
		y = window.pageYOffset;
	}

	scrollX = x;
	scrollY = y;
}
//
//END Remember Scroll Position
//
