//want to add autoroll stuff here since it's not working inside a scroll bar, but window.load is a problem. 




/**
 * STRATA
 * 
 * JS Library
 * 
 * @package STRATA SSE Framework - Front End
 * @author Ben Swenson
 * @copyright 2009 
 */



/**
 * Setup our namespace
 */
if (!sse) var sse= {};





/**
 * Error Handler
 * 
 */
sse.errorDisplay = function (message, page, line, chr){
	winMoveCenter('modalwindow');
	winToFront('dimscreen');
	winToFront('modalwindow');
	
	// this animation works the smoothest if the time 
	// for both show and hide is set to double the following opacity #
	// opacity at .5 and time at 1 seems to be the best
	var modalBgShow = { opacity: { to: .5 } }; 
	var dimOn = new SIDJA.util.Anim('dimscreen', modalBgShow, .2); //, SIDJA.util.Easing.easeOut);
	
    dimOn.animate(); 
    
	var modalWinShow = { opacity: { to: .8 } }; 
	var modalOn = new SIDJA.util.Anim('modalwindow', modalWinShow, .2); //, SIDJA.util.Easing.easeOut);
	
    modalOn.animate();     
    
    getEl('modalContent').innerHTML = 
    			'Woops! <br>' + 
    			'<span class="error_header">' + message + '</span>' + 
    			'<span class="error_text"> <br>In file: ' + page + 
    			' <br>On line: ' + line; // + ' Character: ' + chr + '</span>';
    
    return true; //don't show the default error handler
	
}









/**
 * Debugging 
 * 
 * FIXME Global Function
 * 
 */

// global debugging setting, can not be overridden if off
DEBUGGING = 1;



function debug(debugTxt, debuggingOn){
	if (debuggingOn == 1 && DEBUGGING == 0){
		return debugTxt;
	}	
	else if (debuggingOn == 0 && DEBUGGING == 0){
		// don't even bother
	}
	else if (debuggingOn == 0 && DEBUGGING == 1){
		return debugTxt;
	}
	else if (debuggingOn == 1 && DEBUGGING == 1){
		alert(debugTxt);
	}
	
	return true;
}





/**
 * Get position of mouse
 */
mouseCheck = function(e){

	var mouseX = 1;
	var mouseY = 1;
	
	if (!e) e = window.event;
	if (e.pageX || e.pageY) {
		
		mouseX = e.pageX;
		mouseY = e.pageY;
		
	}
	else if (e.clientX || e.clientY) {
		
		mouseX = e.clientX + document.body.scrollLeft
			+ document.documentElement.scrollLeft;
		mouseY = e.clientY + document.body.scrollTop
			+ document.documentElement.scrollTop;
			
	}
	
	return [mouseX, mouseY];
	
};		



/**
 * Get position of element
 * 
 * Neds the name of a variable wich has already
 * been assigned by document.getElementById
 */
getPos = function(el){ // this will not work if the window is scrolled, see : http://www.codingforums.com/archive/index.php/t-75188.html

	var tmpEl = el;
	//console.log(tmpEl);
	
	var curleft = 0;
	var curtop = 0;
	
	if (tmpEl.offsetParent) {
		
		do {
			curleft += tmpEl.offsetLeft;
			curtop += tmpEl.offsetTop;
			//console.log(curleft + ' ' + curtop);
			
		} while (tmpEl = tmpEl.offsetParent); // unsets el here (don't know why)...so we specify a temp version
		
	return [curleft, curtop];
	
	}
	
	return false;

};






/**
 * getEl - replace document.getElementById(el)
 * 
 * FIXME Global Function
 * 
 */

function getEl(el){
	return document.getElementById(el);
}



/**
 * Get Elements by Tag
 * 
 * Convenience Function
 */
function getTag(el, tag){
	if (el == null){
		el = document;
	}
	return el.getElementsByTagName(tag);
}




/**
 * Get Elements By Class
 * 
 * @author Ben Swenson
 * @copyright 2009
 * 
 * el and tag are optional
 */
function getClass(searchClass, el, tag){
	if (el == null){
		el = document;
	}
	if (tag == null){
		tag = '*';
	}
	var ret = new Array();
	var matches = getTag(el, tag); // probably faster to NOT call a function here, but rather to use the original el.getElementsByTag(tag);
	var matchLen = matches.length;
	var matchCount = 0;
	for (i = 0; i < matchLen; ++i){
		if (matches[i].className == searchClass){
			ret[matchCount] = matches[i];
			
			++matchCount;
		}
	}
	
	return ret;
	
}





/**
 * Similar to the PHP function of the same name
 * 
 * STRATA Framework Front
 * 
 * @author Ben Swenson
 * @copyright June 2009
 * 
 * @return string
 * @param {string} toDecode
 */
htmlspecialchars_decode = function(toDecode) {
	
	// for more HTML entities, see 
	// http://www.zytrax.com/tech/web/entities.html
	toDecode = toDecode.replace(/&lt;/gim, '<');
	toDecode = toDecode.replace(/&gt;/gim, '>');
	
	// unicode?
	toDecode = toDecode.replace(/&#60;/gim, '<');
	//toDecode = toDecode.replace(/&#39;/gim, '<');
	
	toDecode = toDecode.replace(/&laquo;/gim, '�');
	toDecode = toDecode.replace(/&raquo;/gim, '�');
	toDecode = toDecode.replace(/&copy;/gim, '�');
	toDecode = toDecode.replace(/&reg;/gim, '�');
	toDecode = toDecode.replace(/&quot;/gim, '"');
	toDecode = toDecode.replace(/&amp;/gim, '&');
	
	toDecode = toDecode.replace(/&mdash;/gim, '--');
	toDecode = toDecode.replace(/&#8212;/gim, '--');
	
	return toDecode;
};





/**
 * Returns the content of the FIRST
 * matching tag only, and for XML tags
 * will remove the CDATA tag
 * 
 * STRATA Framework Front
 * 
 * @author Ben Swenson
 * @copyright June 2009
 * 
 * @return String
 * @param tag
 * @param searchIn
 */
getTagContent = function(tag, searchIn){
	var ret;

	// This did not handle multiline tags, and 
	// we can't pass flags since we can't seem to
	// use a regex literal with our 'tag' variable.
	// so we'll get rid of newlines first
	searchIn = searchIn.replace(/[\n\r]*/gm, '');
	
	// clean up any cdata tags
	searchIn = searchIn.replace("<!\[CDATA\[", '', 'gim');
	searchIn = searchIn.replace("<!\[CDATA\[>", '', 'gim'); // Fix broken cdata tags, as found on valleywag
	//searchIn = searchIn.replace("\]\]>", '', 'gim'); //working except on valleywag on chrome
	//searchIn = searchIn.replace("\]*>", '', 'gim');
	var regexCdataClose = /\]{2}>/gim;
	searchIn = searchIn.replace(regexCdataClose, '');


	/*
	//This doesn't work, because it finds the WHOLE string, not isolating the tag we want
	ret = searchIn.replace("<" + tag + ">", ''); //"\b[^>]*>", ''); // replace the start tag
	ret = ret.replace("<\/" + tag + ">", ''); // replace the close tag
	*/
	
	//console.log(searchIn);
	//console.log('called on: ' + tag); // + ' searching in: ' + searchIn);
	
	/*
	*/
	//ret = searchIn.match("<" + tag + ">.*?<\/" + tag + ">"); 	// match the tag exactly (won't match if it has attributes)
	ret = searchIn.match("<" + tag + ".*?<\/" + tag + ">")  || ''; //searchIn; 	// match tag with any attributes, if no matches, return the original string so as not to throw errors
	
	var numMatches = ret.length;
	
	//var regexClean = /<.*?>/gim; // this should be only getting rid of the tag called 'tag' - it's getting ANY tag
	
	if (numMatches >= 1){
		//ret = ret[0].replace(regexClean, '');
		//ret = ret[0];
		ret = ret[0].replace("<" + tag + ">", '', 'gim'); // this should get ONLY the tag we want
	}
	else {
		//ret = ret.replace(regexClean, ''); //not working TODO
	}
	
	//var regexCleanClose = /<\/.*?>/gim; // this is getting rid the close tag for 'tag'
	//ret = ret.replace(regexCleanClose, '');
	ret = ret.replace("<\/" + tag + ">", '', 'gim');
	
	
	return ret;
}




/**
 * Split a string by a tag
 * 
 * STRATA Framework Front
 * 
 * @author Ben Swenson
 * @copyright June 2009
 * 
 * @return Array
 * @param {Object} tag
 * @param {Object} searchIn
 */
splitOnTag = function(tag, searchIn){
	
	//return searchIn.split("<" + tag + ">"); 	// split on the tag exactly (won't match if it has attributes)
	return searchIn.split("<" + tag);  	// split on tag with any attributes (as long as it starts with tag) so it will work with slashdot like feeds <item rdf:
	
}




/**
 * Wrap String in a tag
 * 
 * STRATA Framework Front
 * 
 * @author Ben Swenson
 * @copyright June 2009
 * 
 * @return string
 * 
 * @param toWrap
 * @param wrapper
 */
wrapIn = function(wrapper, toWrap){
	if (wrapper == 'img'){
		return '<' + wrapper + ' src="' + toWrap + '" />';
	}
	else{
		return '<' + wrapper + '>' + toWrap + '</' + wrapper + '>';
	}
}




/**
 * Wrap String in a tag with a class
 * 
 * STRATA Framework Front
 * 
 * @author Ben Swenson
 * @copyright June 2009
 * 
 * @return string
 * 
 * @param toWrap
 * @param wrapper
 */
wrapInWithClass = function(wrapper, toWrap, objClass){
	if (wrapper == 'img'){
		return '<' + wrapper + ' src="' + toWrap + '" />';
	}
	else{
		return '<' + wrapper + ' class="' + objClass + '">' + toWrap + '</' + wrapper + '>';
	}
}





/**
 * Assemble a link
 * 
 * STRATA Framework Front
 * 
 * @author Ben Swenson
 * @copyright June 2009
 * 
 * @return string
 * 
 * @param linkContent
 * @param linkLocation
 */
makeLink = function(linkContent, linkLocation){
	return '<a href="' + linkLocation + '">' + linkContent + '</a>';
}




/**
 * Line Break
 * 
 * STRATA Framework Front
 * 
 * @author Ben Swenson
 * @copyright June 2009
 * 
 * @return string
 * 
 */
br = function(){
	return '<br />';
}




/**
 * Converts newlines to HTML <br />'s
 * Similar to PHP function of same
 * name
 * 
 * STRATA Framework Front
 * 
 * @author Ben Swenson
 * @copyright June 2009
 * 
 * @return string
 * 
 */
nl2br = function(inputText){
	return inputText.replace(/\r\n|\r|\n/gm, '<br />');
}



/**
 * Converts triple (look like double) newlines to double HTML <br />'s
 * 
 * STRATA Framework Front
 * 
 * @author Ben Swenson
 * @copyright June 2009
 * 
 * @return string
 * 
 */
nlTriple2DoubleBr = function(inputText){
	return inputText.replace(/(\r\n|\r|\n){3}/gm, '<br /><br />');
}



/**
 * Strips \n's
 * 
 * STRATA Framework Front
 * 
 * @author Ben Swenson
 * @copyright June 2009
 * 
 * @return string
 * 
 */
nlStrip = function(inputText){
	return inputText.replace(/\r\n|\r|\n/gm, '');
}



/**
 * replace \n's with space
 * 
 * STRATA Framework Front
 * 
 * @author Ben Swenson
 * @copyright June 2009
 * 
 * @return string
 * 
 */
nl2space = function(inputText){
	return inputText.replace(/\r\n|\r|\n/gm, ' ');
}





/**
 * Base Mouse Coordinates Class
 * 
 * @param {Object} e // <-- is this still true?
 * @author Ben Swenson & QM
 */

//if(!sse.mouseMovement) sse.mouseMovement={};

mouseMovement = function() { // just the name of the class?
	
	this.getPageMouseCoords = function (e){ // so it won't be instantiated before time?
		
		this.e = e;
		
		if (!this.e) this.e = window.event;
		if (this.e.pageX || this.e.pageY) {
			
			this.posX = this.e.pageX;
			this.posY = this.e.pageY;
			
		}
		else if (this.e.clientX || this.e.clientY) {
			
			this.posX = this.e.clientX + document.body.scrollLeft
				+ document.documentElement.scrollLeft;
			this.posY = this.e.clientY + document.body.scrollTop
				+ document.documentElement.scrollTop;
				
		}
	}

	
	// posx and posy contain the mouse position relative to the document
	// Do something with this information
	return true;
	
}











/**
 * Light Drag Class
 * 
 * No libs...Pure DOM speed
 * 
 * No constraints on movement, that will 
 * have to be an extension of this class
 * probably something like (constrained drag)
 * 
 * Improvements to be made: 
 * -Add a timer so frames can be dropped. 
 * -Add throwing (velocity), etc.
 * 
 * FIXME 
 * Functions at the end need to be broken out
 * into modular pieces. And the whole class structure
 * is garbage at this point.
 * 
 * Extends Base Mouse Coordinates
 * @author Ben Swenson
 * @copyright April 27 2009
 * @package Strata Framework - Front
 * @param el	element to be dragged
 * @param e	event
 * @param handleEl	element of handle
 */

//if(!sse.winDiv) sse.winDiv={};

lightDrag.prototype = new mouseMovement(); // inheritance takes place here so we can get mouse movement inside the div if we want



function lightDrag(el, handleEl, e){

	this.el = el; // these might be unnecessary here....they don't seem to propagate down to the other functions
	this.e = e;
	this.handleEl = handleEl;
	
}




lightDrag.prototype.getPos = function (){

	this.tmpEl = this.el; // see note in while loop
	
	this.curleft = 0;
	this.curtop = 0;
	//this.el = '';// how do we set this? //FIXME
	
	if (this.tmpEl.offsetParent) {
		
		do {
			this.curleft += this.tmpEl.offsetLeft;
			this.curtop += this.tmpEl.offsetTop;
		} while (this.tmpEl = this.tmpEl.offsetParent); // unsets el here...so we specify a temp version
		
	return [this.curleft, this.curtop];
	
	}
	
	return false;

}



	// stuff that's now in dragMe between the ///---- was here
	


/**
 * setNewXY
 * 
 * @param {Object} el
 * @param {Object} newX
 * @param {Object} newY
 */
lightDrag.prototype.setNewXY = function (newX, newY){
	
	
	this.newX = newX;
	this.newY = newY;
	
	//alert(newX);
	
	this.el.style.left = this.newX + "px";
	this.el.style.top = this.newY + "px";
	
}




/**
 * lightDrag init
 * 
 * @param {Object} el
 */
lightDrag.prototype.dragInit = function (){

//	this.e = e;

	//alert(this.e);
	
	///----
	// Run the function from the base class
	this.getPageMouseCoords(this.e); //we're only trying to run it to get the posX and Y
	
	// get the initial div position
	this.initPosDiv = this.getPos(this.el);
	this.initLeftPosDiv = parseInt(this.initPosDiv[0]);
	this.initTopPosDiv = parseInt(this.initPosDiv[1]);
	
	// get the div offset
	this.xOff = this.posX - this.initLeftPosDiv;
	this.yOff = this.posY - this.initTopPosDiv;


	if (this.handleEl){
		
		// get the initial handle position
		this.initPosHandle = this.getPos(this.handleEl);
		this.initLeftHandle = parseInt(this.initPosHandle[0]);
		this.initTopHandle = parseInt(this.initPosHandle[1]);
			
		// get the handle offset
		this.xOff = this.posX - this.initLeftHandle;
		this.yOff = this.posY - this.initTopHandle;
	
	}
	///----	

	//debug(this.initPosDiv + '\n' + this.posX + '\n' + this.xOff, 0); // getting init, event position and offset correctly? - using this debug screws up drag


}




/**
 * dragMe
 * 
 * Here is where the dragging actually takes place.
 * 
 * It requires that the winDiv have an inline style. 
 * But for performance and flexibility reasons, and 
 * since the winDiv's should be generated on the fly 
 * by a factory, this makes sense anyway.
 */
lightDrag.prototype.dragMe = function (){
	
	///----
	// Run the function from the base class
	this.getPageMouseCoords(this.e); //we're only trying to run it to get the posX and Y
	
	var tmpNewX = this.posX - this.xOff;
	var tmpNewY = this.posY - this.yOff;
	
	// i like to move it, move it
	this.setNewXY(tmpNewX, tmpNewY);
	
	// show page coords
	//getEl("posX").innerHTML = this.posX;
	//getEl("posY").innerHTML = this.posY;
	
	// show div coords
	//getEl("divPosX").innerHTML = this.posX - this.initLeftPosDiv;
	//getEl("divPosY").innerHTML = this.posY - this.initTopPosDiv;
	

}




lightDrag.prototype.startDrag = function () {
	// 'closures' are the only way i know to use 
	// setInterval within an object without losing reference to 'this'
	//this.dragging = setInterval("this.dragMe()", 500); //33 is approximately 30fps <-- doesn't work
	// 
	
	/*
	 * Timer isn't working properly 
	 
	var thisObj = this;
	function callBack(){
		thisObj.dragMe();
	}
	this.draggingTimer = setInterval(callBack, 15); // 30fps is too slow, it's not updating enough to even move really
	
	*/

}




lightDrag.prototype.endDrag = function () {
	
	/*
	 * Timer isn't working properly 
	this.draggingTimer = clearInterval(this.dragging);

	debug('I am past the timer');
	 */
}






/**
 * 
 * Instantiate the draggable object
 * 
 * FIXME this needs to be objectified?, but I 
 * am having scope problems with the object it creates
 */

sse.lightDrag = function(el, e, handleEl){

	// setup
	var tmpDiv = new lightDrag();
	tmpDiv.el = el;
	if (handleEl) {tmpDiv.handleEl = handleEl;};
	tmpDiv.e = e;
	tmpDiv.dragInit();



	
	/**
	 * Send Selection events to a black hole while dragging
	 */
	eventsBlackHole = function(){
		
		function captureEvents(){
			return false;
		}
		document.onselectstart = captureEvents;
		document.onselect = captureEvents;
		document.onmousedown = captureEvents;	
		//document.ondblclick = captureEvents;
			
	}
	// initiate now
	eventsBlackHole();



	
	/**
	 * Bring Selection events back after dragging
	 */
	eventsRecoverBlackHole = function(){
		
		function captureEvents(){
			return true;
		}
		document.onselectstart = captureEvents;
		document.onselect = captureEvents;
		document.onmousedown = captureEvents;	
		//document.ondblclick = captureEvents;
			
	}


	

	document.onmousemove = function(event){
		tmpDiv.e = event;
		tmpDiv.startDrag();
		tmpDiv.dragMe();
	}

	
	
	
	document.onmouseup = function(){
		document.onmousemove = null;
		// Basic garbage collection...
		// destroy the object instance
		delete tmpDiv; 
		tmpDiv.endDrag();
		eventsRecoverBlackHole();
	}

	
}




/**
 * Get Style
 * 
 * Geometry will be from parent 
 * 
 * @author: Ben Swenson
 * @copyright: April 28th, 2009
 * @param: id
 * @param: property
 */
sse.getStyle = function(el, styleProp) {
	
	//return getEl(el).style[styleProp]; // this should actually work in most cases now
	
	var x = getEl(el);
	if (x.currentStyle)
		var y = x.currentStyle[styleProp];
	else if (window.getComputedStyle)
		var y = document.defaultView.getComputedStyle(x,null).getPropertyValue(styleProp);
	return y;
	

}




/**
 * Set Style
 * 
 * 
 * @author: Ben Swenson
 * @copyright: April 28th, 2009
 * @param: id
 * @param: property
 */
sse.setStyle = function(el, styleProp, styleValue) {
	
	getEl(el).style[styleProp] = styleValue;
	

}



/**
 * Toggle Style
 * 
 * 
 * @author: Ben Swenson
 * @copyright: April 28th, 2009
 * @param: el	ID of element
 * @param: styleProp	which property to change
 * @param: origValue	original property value
 * @param: newValue		new property value
 */


sse.toggleStyle = function(el, styleProp, origValue, newValue) {
	
	
	if (!sse.toggled) {
		sse.toggled = {};
		sse.toggled[el] = {
				toggled : 1,
				origHeight : origValue,
				newHeight : newValue 	
		};

		sse.setStyle(el, styleProp, newValue);
		
	}
	
	else if (sse.toggled[el].toggled == 1){
		sse.toggled[el].toggled = 0;
		var toggleTo = sse.toggled[el].origHeight;
		//console.log(toggleTo)
		sse.setStyle(el, styleProp, toggleTo);
		
	}
	
	else {
		sse.toggled[el].toggled = 1;
		var toggleTo = sse.toggled[el].newHeight;
		sse.setStyle(el, styleProp, toggleTo);
	}

}




/**
 * SSE Frame Animator
 * 
 * Features:
 * - Non frame dropping
 * - Floating point calculations 
 * - For numeric/geometric properties only.
 * - One animation at a time only //FIXME
 * - Duration is not guaranteed (but it will try to get close), 
 *   but the number of frames is.
 * - If you start a second animation, it will interrupt the first
 * - Velocity is variant on distance and time
 * TODO 
 * - Objectify
 * - Bug fix
 * - add more properties
 * - detect browsers/send specific code
 * - add delayed start
 * - add queue
 * - add easing
 * - allow us to specify how many frames we want at what fps, you calc the duration!! FIXME
 * NOTE: 24 frames / second = interval of 41.666666667ms
 * 
 * After trying every other animation library out there,
 * they just weren't fast enough in a lot of cases...so 
 * here it is. Looks easier than it was.
 * 
 * FIXME Calculations on IE are ending up 
 * wrong...rounding error in their browser?
 * 
 * @author: Ben Swenson
 * @copyright: April 28th, 2009
 * @package: Strata Framework - Front Animation
 * @version: .1
 * 
 * @param el	object to animate
 * @param property	property to animate
 * @param propTo	animation end parameter
 * @param duration	duration of animation in seconds
 * @param fps	frames per second of animation
 */
sse.frameAnimate = function(el, property, propTo, duration, fps){
	
	/**
	 * numFrames needs to be a whole number
	 * 
	 * The 30fps .25s fastUp bug was because
	 * this was coming out at 7.5 frames, 
	 * so it ran 1 too many times.
	 */
	var numFrames = Math.floor(duration * fps); 
	var frameInterval = 1000/fps;
	var intFrameInterval = frameInterval; 
	var startedAt = parseFloat(sse.getStyle(el, property));
	var propSuffix = '';
	isComplete = false;
	
	if (property == 'height' || 'width' || 'left' || 'right' || 'top' || 'bottom'){ 
		propSuffix = 'px';
	}
	else {
		propSuffix = '';
	}
	
	
	var propDiff = '';
	var propStep = '';
	var getBigger = '';
	
	if (startedAt < propTo){
		 propDiff = propTo - startedAt;
		 propStep = propDiff/numFrames;
		 getBigger = 1;
		 
		 //console.log(propStep)
	}
	else {
		 propDiff = startedAt - propTo;
		 propStep = propDiff/numFrames;
		 
		 //console.log(propStep)
	}
	
	//console.log(numFrames, frameInterval, intFrameInterval, startedAt, propDiff, propStep);
	
	
	var currentlyAt = '';
	var tmrAnimate = '';
	var frameCount = 0;
	
	
	aniRun = function(){
		
		if (frameCount < numFrames){
			frameCount++;
			
			//do anim
			currentlyAt = parseFloat(sse.getStyle(el, property));

			var setProp = '';
			
			if (getBigger){
				setProp = currentlyAt + propStep;// (propStep * (i+1));
			}

			else{
				setProp = currentlyAt - propStep;// (propStep * (i+1));
			}
	

		//console.log(currentlyAt, setHeight, intFrameInterval, propStep, frameCount, numFrames);
		
		
		// I like to move it, move it
		sse.setStyle(el, property, setProp+propSuffix);
		
		}
		else {
			clearInterval(tmrAnimate);
			
			isComplete = true;
		}
		
	}
	
	tmrAnimate = setInterval("aniRun()", intFrameInterval);
	
	return isComplete;
	
}










/**
 * SSE Time Animator
 * 
 * Frame dropping, floating point animation engine - 
 * for numeric/geometric properties only. One at a time,
 * duration is guaranteed, number of frames are not.
 * 
 * After trying every other animation library out there,
 * they just weren't fast enough in a lot of cases...so 
 * here it is. Looks easier than it was.
 * 
 * @author: Ben Swenson
 * @copyright: April 28th, 2009
 * @package: Strata Framework - Front Animation
 * @version: .1
 * 
 * @param el	object to animate
 * @param property	property to animate
 * @param propTo	animation end parameter
 * @param duration	duration of animation in seconds
 * @param fps	frames per second of animation
 */
sse.timeAnimate = function(el, property, propTo, duration, fps){
	
	/**
	 * numFrames needs to be a whole number
	 * 
	 * The 30fps .25s fastUp bug was because
	 * this was coming out at 7.5 frames, 
	 * so it ran 1 too many times.
	 */
	var numFrames = Math.floor(duration * fps); 
	var frameInterval = 1000/fps;
	var intFrameInterval = frameInterval; 
	var startedAt = parseFloat(sse.getStyle(el, property));
	var propSuffix = '';
	var aniCheckIn = 20; // the interval time in ms that we will see if we should update the frame
	isComplete = false;
	
	if (property == 'height' || 'width' || 'left' || 'right' || 'top' || 'bottom'){ 
		propSuffix = 'px';
	}
	else {
		propSuffix = '';
	}
	
	
	var propDiff = '';
	var propStep = '';
	var getBigger = '';
	
	if (startedAt < propTo){
		 propDiff = propTo - startedAt;
		 propStep = propDiff/numFrames;
		 getBigger = 1;
		 
		 //console.log(propStep)
	}
	else {
		 propDiff = startedAt - propTo;
		 propStep = propDiff/numFrames;
		 
		 //console.log(propStep)
	}
	
	//console.log(numFrames, frameInterval, intFrameInterval, startedAt, propDiff, propStep);
	
	
	var currentlyAt = '';
	var tmrAnimate = '';
	var frameCount = 0;
	
	// start the real world time test
	var initTime = new Date();
	startTime = initTime.getTime();
	
	
	aniRun = function(){


		// let's check the time to see where we should be at
//		var nowTime = new Date();
//		
//		if ( (nowTime.getTime() - startTime) > (frameCount * frameInterval) {
//			//we're ahead
//			
//		}		
		

		if (frameCount < numFrames){
			frameCount++;
			
			//do anim
			currentlyAt = parseFloat(sse.getStyle(el, property));

			var setProp = '';
			
			if (getBigger){
				setProp = currentlyAt + propStep;// (propStep * (i+1));
			}

			else{
				setProp = currentlyAt - propStep;// (propStep * (i+1));
			}
	

		//console.log(currentlyAt, setHeight, intFrameInterval, propStep, frameCount, numFrames);
		
		
		// I like to move it, move it
		sse.setStyle(el, property, setProp+propSuffix);
		
		}
		else {
			clearInterval(tmrAnimate);
			
			isComplete = true;
		}
		
	}
	
	tmrAnimate = setInterval("aniRun()", aniCheckIn); //, intFrameInterval); // , 20); // , thisInterval);
	
}














/**
 * Resizer
 * 
 * Expects the handle to have an absolute
 * bottom and right value
 * 
 * FIXME unworking with lightDrag
 * 
 * @param el handle to resize by
 */
sse.resize = function(el, handleEl, e){
	
	
	var elWidth = sse.getStyle(el, 'width');
	var elHeight = sse.getStyle(el, 'height');
	
	var handleT = sse.getStyle(handleEl, 'top');
	var handleL = sse.getStyle(handleEl, 'left');
	
	//console.log(elWidth + ' ' + elHeight);
	//console.log(handleT + ' ' + handleL);
	
	/**
	 * Set the left and top here, if it didn't have
	 * one before, because lightDrag expects a left and top
	 */
	//sse.setStyle(handleEl, 'top', handleT+'px');
	//sse.setStyle(handleEl, 'left', handleL+'px');
	
	var tmpResize = new sse.lightDrag(handleEl, e);
	
	tmpResize.endDrag = function(){
		var newHandleT = sse.getStyle(handleEl, 'top');
		var newHandleL = sse.getStyle(handleEl, 'left');
		
		var diffX = handleT - newHandleT;
		var diffY = handleL - newHandleL;
		
		sse.setStyle(el, 'width', diffX+'px');
		sse.setStyle(el, 'height', diffY+'px');
	}
	
	return true;
}






/**
 * User Info
 * 
 */
sse.userInfo = function(param){

	this.moz = navigator.appCodeName; //always mozilla
	this.browser = navigator.appName;
	this.ua = navigator.userAgent; // full string
	this.os = navigator.platform; // not always reliable, use/parse below?
	this.cookies = navigator.cookieEnabled;
	this.appVer = navigator.appVersion; // this usually shows the os/platform as well
	this.appVerB = parseFloat(this.appVer);
	this.cpu = navigator.cpuClass; //IE only
	this.uaMinorV = navigator.appMinorVersion;
	this.uaString = 'Parameter: <strong>' + this[param] + '</strong>'; //FIXME
	
	if (!param){
		
		uaString = 'Browser name: <strong>' + this.ua + '</strong>';
		return this.uaString;

	}
	
	return this.uaString;
	
}


