Rvlt = (typeof(Rvlt)=="undefined"?{}:Rvlt); //Namespace Revelate

/*---------------------------
Rollover layers
---------------------------*/
Rvlt.Layers = function () {
	var VisibleLayer;
	var PicLayer;
	var _this = this;

	function CreatePicLayer () {
		PicLayer = document.createElement('div');
		PicLayer.id = 'PicOverlay';
		PicLayer.onmouseover = function () {_this.ShowLayer(PicLayer.id);}
		PicLayer.onmouseout = function () {_this.HideLayer();}
		PicLayer.className = 'Layer Landscape';
		PicLayer.innerHTML = '<div class="TopShadow">&nbsp;</div><div class="MiddleShadow"><img src="void" width="400" height="400" /></div><div class="BottomShadow">&nbsp;</div>';
		PicLayer.thePic = PicLayer.getElementsByTagName('img')[0];
		document.body.appendChild(PicLayer);
	}
	
	this.ShowPicLayer = function (ImgUrl, sender) {
		if (!PicLayer) {
			CreatePicLayer();
		}
		if (ImgUrl != PicLayer.thePic.src) {
			_InternalHideLayer(PicLayer)();
			PicLayer.thePic.src = ImgUrl;
		}
		_this.ShowLayer(PicLayer.id, sender);
	}

	this.ShowLayer = function (LayerID, sender){
		var theLayer = document.getElementById(LayerID);
		Rvlt.Utils.ClearTimer(theLayer, 'RollOutTimer');
		if (VisibleLayer != null && VisibleLayer != theLayer) {
			 _InternalHideLayer(VisibleLayer)();
		}
		if (theLayer.style.visibility != 'visible') {
			PositionLayer (theLayer, sender); //Note: 'this' refers to the sender here
			theLayer.style.visibility = 'visible';
		}
		VisibleLayer = theLayer;
	}
	
	this.HideLayer = function (LayerID) {
		var theLayer;
		if (LayerID == null) {
			theLayer = VisibleLayer;
		}
		else {
			theLayer = document.getElementById('LayerID');
		}
		if (theLayer != null) {
			theLayer.RollOutTimer = window.setTimeout(_InternalHideLayer(theLayer), 200);
		}
	}
	
	function _InternalHideLayer(theLayer){
		return function (){
			if (VisibleLayer == theLayer) {
				VisibleLayer = null;
			}
			theLayer.style.visibility = 'hidden';
		}
	}

	function PositionLayer (theLayer, theThumb) {				
		var OffsetX = -10;
		var OffsetY = 60;
		var theContainer = document.getElementById("PageContainer")
		var ContainerLeft = Rvlt.Utils.AbsoluteOffset(theContainer, 'Left'); 
		var ContainerWidth = theContainer.offsetWidth;
		var ContainerRight = ContainerLeft + ContainerWidth;
		var ThumbLeft = Rvlt.Utils.AbsoluteOffset(theThumb, 'Left');
		var ThumbTop = Rvlt.Utils.AbsoluteOffset(theThumb, 'Top');
		
		theLayer.style.left = GetPos (ThumbLeft, theThumb.offsetWidth, theLayer.offsetWidth,  ContainerLeft, ContainerRight, OffsetX) + "px"
		theLayer.style.top = GetPos (ThumbTop, theThumb.offsetHeight, theLayer.offsetHeight, Rvlt.Utils.getWinTop(), Rvlt.Utils.getWinBottom(), OffsetY) + "px"
	}
	
	function GetPos (SenderMin, SenderLength, TargetLength, MinPos, MaxPos, Offset) {
		var thePos = 0;
		if (SenderMin - MinPos <= (MaxPos - MinPos) / 2) {//Sender in first half of boundaries
			thePos = SenderMin + SenderLength - Offset;
			if (thePos + TargetLength > MaxPos) {//Further than max pos
				thePos = MaxPos - TargetLength; //-> Align at edge
			}
		}
		else {//Sender in second half of boundaries
			thePos = SenderMin - TargetLength + Offset;
		}
		if (thePos < MinPos){// Target larger than available space -> Align with min 
			thePos = MinPos;
		}
		
		return thePos;
	}
}

 
/*---------------------------
Shared utilities (static functions)
---------------------------*/

Rvlt.Utils = {}

/**
 * Returns a single node, or the node itself if it has the tag name. 
 * If more than one child with that name is present, returns null.
 * Useful for: Event delegation
 * @param   el      		DOM object to to start with
 * @param   tagName         Name of tag to search for. Lowercase.
 * @param   searchFor       Accepts "parent" or "child"
 */
Rvlt.Utils.FindElementByTagName = function (el, tagName, searchFor) { //
	var ChildElements;
	if (el.tagName.toLowerCase() == tagName) {
		return el;
	}
	if (searchFor == "parent") {
		while (el != null && el.tagName.toLowerCase() != tagName) {
			el = el.parentNode.tagName != null ? el.parentNode : null;
		}
		return el;
	}
	else {
		ChildElements = el.getElementsByTagName(tagName);
		return ChildElements.length == 1 ? ChildElements[0] : null;
	}
}


/**
 * Finds next sibling of a particular tag
 * @param   el      		DOM object to to start with
 * @param   tagName         Name of tag to search for. Lowercase.
 */
Rvlt.Utils.FindNextSiblingByTagName = function (el, tagName) { //
	while (el.nextSibling != null) {
		if (el.nextSibling.tagName !=null && el.nextSibling.tagName.toLowerCase() == tagName) {
			return el.nextSibling;
		}
		else {
			el = el.nextSibling;
		}
	}
	return null;
}

/**
 * @param   e      			DOM Event
 */
Rvlt.Utils.GetEventTarget = function (e) { //Cross browser malarkey
	e = e || window.event;
	return e.target || e.srcElement;
}

/**
 * The "raison d'etre" of these functions is that an object can have
 * several classes seperated by a space in the className 
 * @param   el      		DOM element to add class to
 * @param   theClass        Class to be added (string)
 */
Rvlt.Utils.AddCssClass = function (el, theClass){
	el.className = el.className.indexOf(theClass) > -1 ? el.className : (el.className ? el.className + ' ' : '') + theClass;
}

/**
 * @param   el      		DOM element to add class to
 * @param   theClass        Class to be removed (string)
 */
Rvlt.Utils.RemoveCssClass = function (el, theClass){
	var classArray = el.className.split(' ');
	var classString = "";
	for (var i=0;i<classArray.length-1;i++) {
		if (classArray[i] != theClass) classString += classArray[i] + ' ';
	}
	el.className  = classString.substr(0, classString.length -1);
}

/**
 * @param   el      		HTML element to find offset f
 * @param   which       	 'Top' or 'Left' (case sensitive)
 * @return  int       		Returns position from edge of screen.
 */
Rvlt.Utils.AbsoluteOffset = function (el, which) { 
	return el.offsetParent ? el['offset' + which] + Rvlt.Utils.AbsoluteOffset(el.offsetParent, which) : el['offset' + which];
}

/** !! UNTESTED!!
 * @param   Coord      		'x' or 'y'
 * @param   e       	 	Event
 */
Rvlt.Utils.GetMousePos = function (Coord, e) {
	if (e.pageX || e.pageY) {
		return (Coord == 'x') ?  e.pageX : e.pageY; 
	}
	else if (e.clientX || e.clientY) {
		return (Coord == 'x') ? e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft : e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
	}
}

/**
 * @param   el      		HTML element to clear timer of
 * @param   TimerName       Name of timer	
 */
Rvlt.Utils.ClearTimer = function (el, TimerName) {
	if (el[TimerName]!= null) {
		window.clearTimeout(el[TimerName]);
		el[TimerName] = null;
	}
}

/**
 * Cross browser window information
 */
Rvlt.Utils.getWinWidth = function () {return window.innerWidth || document.documentElement.clientWidth - 15; } //the -15 is to account for scrollbars
Rvlt.Utils.getWinLeft = function () {return window.pageXOffset || document.documentElement.scrollLeft;}
Rvlt.Utils.getWinRight = function () {return Rvlt.Utils.getWinLeft() + Rvlt.Utils.getWinWidth();}
Rvlt.Utils.getWinHeight = function () {return window.innerHeight || document.documentElement.clientHeight;}
Rvlt.Utils.getWinTop = function () {return window.pageYOffset || document.documentElement.scrollTop;}
Rvlt.Utils.getWinBottom = function () {return Rvlt.Utils.getWinTop() + Rvlt.Utils.getWinHeight();} 
	
Rvlt.Utils.SetCookie = function (Name, Value) {
	var date = new Date();
	date.setTime(date.getTime()+(365*24*60*60*1000)); // now + 1 year
	document.cookie = Name + "=" + Value + "; expires=" + date.toGMTString() + "; path=/";
	return true;
}	
