function hookEvent( element, eventName, callback )
{
	if ( typeof(element) == "string" )
		element = document.getElementById(element);
	if ( element == null )
		return;
	if( element.addEventListener )
	{
		if( eventName == 'mousewheel' )
			element.addEventListener( 'DOMMouseScroll', callback, false );
		element.addEventListener( eventName, callback, false );
	}
	else if ( element.attachEvent )
	{
		element.attachEvent( "on" + eventName, callback );
	}
}

if ( !Array.indexOf ) {
	Array.prototype.indexOf = function(obj) {
		for(var i=0; i<this.length; i++)
			if ( this[i] == obj )
				return i;
		return -1;
	}
}

function clamp( value, min, max )
{
	return Math.max( min, Math.min( max, value ) );
}

function approach( cur, target, inc )
{
	inc = Math.abs( inc )

	if ( cur < target )
		return clamp( cur + inc, cur, target );
	else if ( cur > target )
		return clamp( cur - inc, target, cur );
	return target;
}

function setOpacity( element, value, display )
{
	value = clamp( value, 0, 1 );
	if ( value == 0 )
	{
		if ( display && ( element.style.display != "none" ) )
			element.style.display = "none";
	}
	else
	{
		if ( display && ( element.style.display != display ) )
			element.style.display = display;
		if ( element.style.opacity != value )
			element.style.opacity = value;
		//element.style.filter = "alpha(opacity=" + parseInt( value * 100 ) + ")";
	}
}

var Scrollers = new Array();

function Scroller( content )
{
	this.content = content;
	var base, top_shade, bot_shade;

	base = this.base = document.createElement( 'div' );
	base.className = "sx_base " + content.className;
	base.style.height = content.style.maxHeight;
	content.style.maxHeight = null;
	content.className = "sx";
	top_shade = this.top_shade = document.createElement( 'div' );
	top_shade.className = "sx_shade sx_top";
	top_shade.innerHTML = '<a href="javascript:"><img src="/uparrow.gif" width="13" height="7"></a>';
	bot_shade = this.bot_shade = document.createElement( 'div' );
	bot_shade.className = "sx_shade sx_bot";
	bot_shade.innerHTML = '<a href="javascript:"><img src="/downarrow.gif" width="13" height="7"></a>';

	var parent = content.parentNode;
	parent.insertBefore( base, content );
	parent.removeChild( content );
	base.appendChild( content );
	base.appendChild( bot_shade );
	base.appendChild( top_shade );

	content.style.position = "relative";

	this.getScrollX = function()
	{
		var pos = parseInt(this.content.style.left);
		return pos ? pos : 0;
	}

	this.getScrollY = function()
	{
		var pos = parseInt(this.content.style.top);
		return pos ? pos : 0;
	}

	this.autoX = 0;
	this.autoY = 0;
	this.autoOnX = 0;
	this.autoOnY = 0;

	var scroller = this;

	hookEvent( base, "mousewheel", function( e ) { scroller.performWheel( e ? e : window.event ) } );
	hookEvent( base, "keydown", function( e ) { scroller.performKeys( true, e ? e : window.event ) } );
	hookEvent( base, "keyup", function( e ) { scroller.performKeys( false, e ? e : window.event ) } );
	hookEvent( base, "click", function( e ) {
		var active = document.activeElement;
		if ( ( top_shade.style.display != "none" ) && ( active != bot_shade.firstChild ) ) top_shade.firstChild.focus(); 
		else if ( ( bot_shade.style.display != "none" ) && ( active != top_shade.firstChild ) ) bot_shade.firstChild.focus(); 
	} );

	hookEvent( top_shade, "mouseover", function() { scroller.autoScroll( null, 1 ); } );
	hookEvent( top_shade, "mouseout", function() { scroller.autoScroll( null, 0 ); } );
	hookEvent( top_shade, "mousedown", function() { scroller.autoY = 10; scroller.autoScroll( null, 1 ); } );
	hookEvent( top_shade, "mouseup", function() { scroller.autoScroll( null, 0 ); } );
	hookEvent( top_shade, "click", function() { scroller.autoY = 10; scroller.autoScroll( null, 0 ); if ( top_shade.style.display != "none" ) { top_shade.firstChild.focus(); }  } );

	hookEvent( bot_shade, "mouseover", function() { scroller.autoScroll( null, -1 ); } );
	hookEvent( bot_shade, "mouseout", function() { scroller.autoScroll( null, 0 ); } );
	hookEvent( bot_shade, "mousedown", function() { scroller.autoY = -10; scroller.autoScroll( null, -1 ); } );
	hookEvent( bot_shade, "mouseup", function() { scroller.autoScroll( null, 0 ); } );
	hookEvent( bot_shade, "click", function() { scroller.autoY = -10; scroller.autoScroll( null, 0 ); if ( bot_shade.style.display != "none" ) { bot_shade.firstChild.focus(); } } );

	this.scrollTo( 0, 0 );

}

Scroller.prototype.scrollBy = function( x, y )
{
	this.scrollTo( this.getScrollX() + x, this.getScrollY() + y );
}

Scroller.prototype.scrollTo = function( x, y )
{
	var width = this.content.scrollWidth - this.content.parentNode.clientWidth;
	var height = this.content.scrollHeight - this.content.parentNode.clientHeight;
	x = Math.min( 0, Math.max( -width, x ) );
	y = Math.min( 0, Math.max( -height, y ) );

	var active = document.activeElement;
	
	// Fade the top and bottom shadows
	setOpacity( this.top_shade, y / -60, "block" );
	setOpacity( this.bot_shade, ( height + y ) / 60, "block" );

	// Make sure that the scroll box stays in focus for those scrolling with keyboard (FF3)
	if ( active == this.top_shade.firstChild || active == this.bot_shade.firstChild )
	{
		if ( active.parentNode.style.display == "none" )
		{
			if ( this.top_shade.style.display != "none" ) 
				this.top_shade.firstChild.focus(); 
			else if ( this.bot_shade.style.display != "none" ) 
				this.bot_shade.firstChild.focus(); 
		}
	}
	
	// Stop the autoscrolling if we hit the beginning or end
	if ( y == 0 && this.autoY > 0 )
		this.autoY = 0;
	else if ( y == -height && this.autoY < 0 )
		this.autoY = 0;
	if ( x == 0 && this.autoScrollX > 0 )
		this.autoScrollX = 0;
	else if ( x == -width && this.autoScrollX < 0 )
		this.autoScrollX = 0;

	// Scroll the content
	this.content.style.left = x + "px";
	this.content.style.top = y + "px";
}

Scroller.prototype.autoScroll = function( x, y )
{
	if ( x != null ) this.autoOnX = clamp( x, -1, 1 );
	if ( y != null ) this.autoOnY = clamp( y, -1, 1 );

	// Approach maximum speed
	this.autoX = approach( this.autoX, this.autoOnX * 10, 1 );
	this.autoY = approach( this.autoY, this.autoOnY * 10, 1 );

	// Cancel timer if no scrolling is in progress
	if ( this.autoX == 0 && this.autoY == 0 && this.autoOnX == 0 && this.autoOnY == 0 )
	{
		clearInterval( this.auto );
		this.auto = null;
	}
	// Start timer if scrolling is in progress
	else if ( !this.auto )
	{
		var me = this;
		this.auto = setInterval( function () { me.autoScroll() }, 100, me );
	}

	// Scroll the panel
	this.scrollBy( this.autoX, this.autoY );
}

Scroller.prototype.performKeys = function( down, e )
{
	var x = null, y = null;
	
	if ( e.keyCode == 37 )
		x = (down ? 1 : 0);
	else if ( e.keyCode == 39 )
		x = (down ? -1 : 0);
	
	if ( e.keyCode == 38 )
		y = (down ? 1 : 0);
	else if ( e.keyCode == 40 )
		y = (down ? -1 : 0);
	
	if ( e.keyCode == 38 && down && this.top_shade.style.display != "none" )
		this.top_shade.firstChild.focus();
	else if ( e.keyCode == 40 && down && this.bot_shade.style.display != "none"  )
		this.bot_shade.firstChild.focus();
		
	this.autoScroll( x, y );
}

Scroller.prototype.performWheel = function( e )
{
	var x = 0, y = 0;

	// Determine horizontal scroll
	if ( e.wheelDeltaX )
		x = e.wheelDeltaX;

	// Determine vertical scroll
	if ( e.wheelDeltaY )
		y = e.wheelDeltaY;
	else if ( e.wheelDelta )
		y = e.wheelDelta;
	else if ( e.detail )
		y = -e.detail;

	// Determine if scrolling up or down
	x = ( x < 0 ? -1 : ( x > 0 ? 1 : 0 ) ) * 15;
	y = ( y < 0 ? -1 : ( y > 0 ? 1 : 0 ) ) * 15;

	// Cancel and reverse auto-scroll if scrolling against it
	if ( y < 0 && this.autoY > 0 )
		this.autoY = -this.autoY;
	else if ( y > 0 && this.autoY < 0 )
		this.autoY = -this.autoY;
	this.autoScroll( 0, 0 );

	this.scrollBy( x, y );
}

function sxInit()
{
	var sxs = new Array();
	var divs = document.getElementsByTagName( "div" );
	for ( var i = 0, div; ( div = divs[i] ) != null; i++ )
	{
		if ( div.className.split(' ').indexOf('sx') >= 0 )
			sxs.push( div );
	}
	for ( var i = 0, div; ( div = sxs[i] ) != null; i++ )
		Scrollers.push( new Scroller( div ) );
}

/*
	<div class="sx text">
		<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut venenatis consequat leo. Donec id ante tellus. Nam id orci eget arcu vehicula vehicula. Phasellus commodo nibh ac augue ornare tristique. Duis iaculis pretium dui sed ullamcorper. Nullam lacinia sapien in tortor tempus id venenatis libero condimentum. Nam tincidunt luctus vestibulum. Nullam tempus pharetra mattis. Sed quis eros ac urna ultricies luctus sit amet non elit. Fusce tempus neque vel tortor egestas tincidunt. Nunc eu iaculis nunc. In ut magna a libero pellentesque pharetra. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse erat massa, mattis eleifend scelerisque eget, varius et tellus. Aenean urna mauris, bibendum nec tempus in, adipiscing a velit. Donec mollis lorem ut nisl cursus dignissim placerat purus feugiat. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Mauris aliquet nunc ac arcu convallis feugiat.</p>
		<p>Ut consequat tincidunt risus, sit amet convallis ligula mattis in. Aenean bibendum aliquam gravida. Ut gravida metus nec massa aliquet aliquet in sed lorem. Quisque rhoncus purus id magna pulvinar sit amet tincidunt est condimentum. Integer ultricies augue et nunc ultrices pulvinar. Sed quis purus vitae metus accumsan tincidunt. Suspendisse sollicitudin pellentesque massa, ac rutrum justo sodales vel. Nam dictum nisl at tellus cursus venenatis. Nunc placerat nisl et velit blandit vel consequat elit luctus. Aliquam erat volutpat. Vestibulum et magna nec arcu tristique consectetur vitae quis turpis. Suspendisse consequat, erat at tristique porttitor, diam nulla egestas diam, et mattis dolor dui sed velit. Praesent adipiscing posuere quam lobortis interdum. Nullam bibendum tempor eros sed tristique. Vestibulum malesuada enim ut ligula faucibus varius. Fusce in ipsum semper leo euismod molestie a vel lectus.</p>
	</div>
*/

if ( window.addEventListener ) {
	window.addEventListener( "load", sxInit, false );
} else if (window.attachEvent) {
	window.attachEvent( "onload", sxInit );
} else {
	if ( window.onload )
	{
		var ol = window.onload;
		window.onload = function() { sxInit(); ol(); }
	}
	else
	{
		window.onload = function() { sxInit(); }
	}
}
