
function slideController( el )
{
	// internal vars
	var self = this;
	self.link = el;
	self.target = false;
	self.target_height = 0;
	self.expandLink = false;
	self.animationFrame = 0;
	self.stepSize = 0;
	self.minHeight = 0;
	self.alterLink = true;

	// vars controlling how the animation plays
	self.OpenIcon = '<img src="/images/down.png" alt="expand" style="border:none;" />';
	self.CloseIcon = '<img src="/images/up.png" alt="collapse" style="border:none;" />';
	self.fps = 25; // frames per second to shoot for
	self.animationTime = 0.5; // time (in seconds) the slide animation should last

	self.noArrows = false;

	// initialize-- creates the up/down arrow and sets the onclick handler
	self.init = function()
	{
		var startHidden = false;
		
		// parse the args argument.  
		var args = self.link.getAttribute('args');
		if( args.toLowerCase().indexOf('starthidden') != -1 )
			{ startHidden = true; }

		if( args.toLowerCase().indexOf('ellipsis') != -1 )
		{ 
			self.OpenIcon = " (...more)";
			self.CloseIcon = " (hide)";
		}

		if( args.toLowerCase().indexOf('noalterlink') != -1 )
		{
			self.alterLink = false;
		}

		if( args.toLowerCase().indexOf('minheight') != -1 )
		{
			var mh = args.match( /minheight=(\d*)/i );
			if( mh[1] !== null )
				{ self.minHeight = mh[1]; }
		}

		if( args.toLowerCase().indexOf('noarrow') != -1 )
		{
			self.noArrows = true;
		}
		
		var t = args.match( /target=([^:]*)/i );
		if( t===null || t[1]===null ) { return; }
		self.target = $(t[1]);

		// get the expanded size of the element
		//   on some pages the size is incorrently calculated.  for whatever reason, if there's a border it works.
		if( !self.target.style.border )
		{ 
			self.target.style.border = "1px solid transparent";
			self.target_height = self.target.getSize().height -2; 
			self.target.style.border = "";
		}
		else
		{
			self.target_height = self.target.getSize().height;
		}
		
		// set the size and overflow
		self.target.style.height = (startHidden) ? self.minHeight+"px" : self.target_height+"px";
		self.target.style.overflow = "hidden";

		// alter the link, if needed
		if( self.alterLink )
		{
			self.link.onclick = (startHidden) ? self.slideOpen : self.slideClosed;
		}

		// create the up/down link
		self.expandLink = create('a').set('href','javascript:void(0);').set('innerHTML', (startHidden) ? self.OpenIcon : self.CloseIcon);
		self.expandLink.style.textDecoration = "none";
//		self.expandLink.style.cssFloat = self.expandLink.style.styleFloat = "right";
		self.expandLink.onclick = (startHidden) ? self.slideOpen : self.slideClosed;

		// insert the link
//		self.link.parentNode.insertBefore(self.expandLink, self.link);

		if( self.noArrows !== true )
		{
			$(self.link.parentNode).insertAfter(self.expandLink, self.link);
		}


	}

	// onclick that closes the element
	self.slideClosed = function()
	{
		self.animateToHeight( self.minHeight );

		self.expandLink.innerHTML = self.OpenIcon; 
		self.expandLink.onclick = self.slideOpen;
		if( self.alterLink )
			{ self.link.onclick = self.slideOpen; }
		

		return false;
	};

	// onclick handler that opens the element
	self.slideOpen = function()
	{
		self.animateToHeight( self.target_height );

		self.expandLink.innerHTML = self.CloseIcon;
		self.expandLink.onclick = self.slideClosed;
		if( self.alterLink )
			{ self.link.onclick = self.slideClosed; }
		
		return false;
	};
	
	// set up the animation frames
	self.animateToHeight = function( height )
	{
		var numFrames = self.animationTime * self.fps; // total number of frames to animate

		var currentSize = (self.target.getSize().height) ? self.target.getSize().height : 0;
		var sizeDifference = height - currentSize;
		self.stepSize = sizeDifference / numFrames;

		self.animationFrame = 0;

		// animate one extra frame-- it will go to far, but be caught by the bounds checking
		//  this way any rounding errors are accounted for and the size doesn't drift
                for (var i=0; i<=numFrames+1; i++)
		{
			setTimeout( self.stepFrame, (1000/self.fps)*i );
		}
	};

	// animate one frame
	self.stepFrame = function()
	{
		// calc new height
		var newHeight = parseInt(self.target.style.height,10) + self.stepSize;

		// catch out-of-bounds numbers
		if( newHeight > self.target_height )
			{ newHeight = self.target_height; }
		else if( newHeight < self.minHeight )
			{ newHeight = self.minHeight; }

		// apply it
		self.target.style.height = newHeight+"px";
		self.animationFrame++;
	};

	// init the class
	self.init();
}

var UWLaw_SlideControllers = new Array();
addWindowOnload( function() {
		
	var links = document.getElementsByTagName('a');	

	var foundElements = new Array();
	for( var i=0; i<links.length; i++ )
	{
		if( links[i].getAttribute("rel") && links[i].getAttribute("rel").toLowerCase() == 'lawslidetoggle' )
		{
			if( !links[i].getAttribute('args') )
				{ continue; }

			foundElements.push( links[i] );
		}
	}

	for( var i=0; i<foundElements.length; i++ )
	{
		UWLaw_SlideControllers.push( new slideController( foundElements[i] ) );
	}
} );
