/*
 * RobsChoice.com Javascript functions - generic and reusable (not app specific)
 */
 
 /******************************************************************
 * global constants
 *
 ******************************************************************/
var WAIT_ICON_HEIGHT = 32; // height of the wait icon in px


 /******************************************************************
 * cross-browser & utility methods
 *
 ******************************************************************/

function setCookie(c_name, value)
/*
 * Sets the specified cookie to the specified value. Cookie expires in 365 days.
 */
{
	var expiredays = 365;
	var exdate = new Date();
	exdate.setDate(exdate.getDate() + expiredays);
	document.cookie = c_name + "=" + escape(value) + ";expires=" + exdate.toGMTString();
}

function getCookie(c_name)
/*
 * Returns the value for the specified cookie, or an empty string if none exists.
 */
{
	if (document.cookie.length>0) {
		c_start = document.cookie.indexOf(c_name + "=");
		if (c_start != -1) {
			c_start = c_start + c_name.length+1;
			c_end = document.cookie.indexOf(";",c_start);
			if (c_end == -1) c_end = document.cookie.length;
			return unescape(document.cookie.substring(c_start,c_end));
		}
	}
	return "";
}

function relativeBaseUrl()
/*
 * Returns the document's relative base URL (i.e. everything after the domain but before any # or ?)
 */
{
	var url = document.URL.substring( document.URL.indexOf("/", document.URL.indexOf("://")+3 ) ); // drop the http://mydomain.com part
	if (url.indexOf("#") > 0) url = url.substring(0,url.indexOf("#")); // drop everything after #
	else if (url.indexOf("?") > 0) url = url.substring(0,url.indexOf("?")); // drop everything after ?
	return url;
}

function getXMLHttpRequest()
/*
 * AJAX code to get the XMLHttpRequest object.
 */
{
	try { return new XMLHttpRequest() } catch (e) {} // Firefox, Opera 8.0+, Safari, IE7+
	try { return new ActiveXObject("Msxml2.XMLHTTP") } catch (e) {} // IE6+
	try { return new ActiveXObject("Microsoft.XMLHTTP") } catch (e) {} // IE5.5+
	alert("Your browser is too old to use this site. Please upgrade it. (Doesn't support AJAX)");
	throw new Error("Your browser does not support AJAX!");
}

function parseJSON(text)
/*
 * The RFC that defines JSON suggests using the following code to validate JSON before using eval() 
 * to create the object from the text.
 * Returns the results of eval() after validation.
 */
{
	return (!(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(text.replace(/"(\\.|[^"\\])*"/g, ''))) && eval('(' + text + ')'));
}

function getLastKeyPress()
/*
 * Returns the last key pressed by the user as a character, or an empty string if it can't be determined.
 * Normalizes the differences between browsers.
 */
{
	var lastKeyPress = "";
	try {
		lastKeyPress = String.fromCharCode(window.event.keyCode); // IE
	} catch (error) {
		try {
			lastKeyPress = String.fromCharCode(window.event.which); // Netscape/Firefox/Opera
		} catch (error) {
			//throw "Neither event.keyCode nor event.which supported by browser."; // must be none of the above
			// alert("Unable to determine last key press! Details:"+error);
			return "";
		}
	}
	return lastKeyPress;
}

function getClientWidth() 
/*
 * Returns client width - browser independent.
 */
{
	return _filterResults (
		window.innerWidth ? window.innerWidth : 0,
		document.documentElement ? document.documentElement.clientWidth : 0,
		document.body ? document.body.clientWidth : 0
	);
}

function getClientHeight()
/*
 * Returns client height - browser independent.
 */
{
	if (self.innerHeight) {
		return self.innerHeight; // all except IE
	} else if (document.documentElement && document.documentElement.clientHeight) {
		return document.documentElement.clientHeight; // IE6 Strict Mode
	} else if (document.body) {
		return document.body.clientHeight; // other IE
	} else {
		return 0;
	}
}

function getScrollLeft()
/*
 * Returns client horizontal scroll position - browser independent.
 */
{
	return _filterResults (
		window.pageXOffset ? window.pageXOffset : 0,
		document.documentElement ? document.documentElement.scrollLeft : 0,
		document.body ? document.body.scrollLeft : 0
	);
}

function getScrollTop()
/*
 * Returns client vertical scroll position - browser independent.
 */
{
	return _filterResults (
		window.pageYOffset ? window.pageYOffset : 0,
		document.documentElement ? document.documentElement.scrollTop : 0,
		document.body ? document.body.scrollTop : 0
	);
}

function _filterResults(n_win, n_docel, n_body)
{
	var n_result = n_win ? n_win : 0;
	if (n_docel && (!n_result || (n_result > n_docel)))
		n_result = n_docel;
	return n_body && (!n_result || (n_result > n_body)) ? n_body : n_result;
}

function getAbsoluteTop(anElement)
/*
 * Returns the absolute top coordinate for the specified element.
 */
{		
	var returnValue = anElement.offsetTop;
	for (anElement = anElement.offsetParent; anElement != null; anElement = anElement.offsetParent) {
		if (anElement.tagName != 'HTML') returnValue += anElement.offsetTop;
	}
	return returnValue;
}

function getAbsoluteLeft(anElement)
/*
 * Returns the absolute left coordinate for the specified element.
 */
{
	var returnValue = anElement.offsetLeft;
	for (anElement = anElement.offsetParent; anElement != null; anElement = anElement.offsetParent) {
		if (anElement.tagName != 'HTML') returnValue += anElement.offsetLeft;
	}
	return returnValue;
}

function addEvent(anObject, eventName, handlerFunction)
/*
 * Adds the specified event to the specified object - browser independent.
 */
{
	if(anObject.attachEvent) {
		//anObject['e'+eventName+handlerFunction] = handlerFunction;
		//anObject[eventName+handlerFunction] = function() { anObject['e'+eventName+handlerFunction]( window.event ); }
		//anObject.attachEvent('on'+eventName, anObject[eventName+handlerFunction] );
		
		anObject.attachEvent('on'+eventName, handlerFunction);
	} else {
		anObject.addEventListener(eventName, handlerFunction, false); // W3C standards based browsers
	}
}

/******************************************************************
 * Methods for handling modal dialogs: 
 *      openModalDialog(dialogWidth, dialogHeight, url)
 *      closeModalDialog()
 *      _modalDialogHandleWindowScrollOrResize()
 ******************************************************************/

function openModalDialog(dialogWidth, dialogHeight, dialogTitle, focalElementId, url)
{
	// center popup
	var xPos = (getClientWidth() / 2) - (dialogWidth / 2) + getScrollLeft(); // center
	var yPos = (getClientHeight() / 2) - (dialogHeight / 2) + getScrollTop(); // center

	// create transparent div
	var divDimmer = document.createElement("DIV");
	divDimmer.className="modalDialog_dimmer_layer";
	divDimmer.id = "modalDialogDimmer";
	divDimmer.style.top = getScrollTop() + "px";
	divDimmer.style.left = getScrollLeft() + "px";
	divDimmer.style.width = getClientWidth() + "px";
	divDimmer.style.height = getClientHeight() + "px";
	document.body.appendChild(divDimmer);

	// create content div
	var divContent = document.createElement("DIV");
	divContent.className = "modalDialog_content_layer";
	divContent.id = "modalDialog";
	divContent.style.top = yPos + "px";
	divContent.style.left = xPos + "px";
	divContent.style.width = dialogWidth + "px";
	divContent.style.height = dialogHeight + "px";
	var waitIconTopMargin = (dialogHeight / 2) - (WAIT_ICON_HEIGHT / 2);
	divContent.innerHTML = '<img class="wait" style="margin-top:'+waitIconTopMargin+'px" src="/images/ui/wait.gif" alt="Please Wait" />';
	document.body.appendChild(divContent);
	
	// handle scroll & resize
	addEvent(window, 'scroll', _modalDialogHandleWindowScrollOrResize);
	addEvent(window, 'resize', _modalDialogHandleWindowScrollOrResize);

	// ajax url data
	var xmlHttp = getXMLHttpRequest();
	xmlHttp.onreadystatechange = function() {
		if (xmlHttp.readyState==4) {
			// ready to process result
			if (xmlHttp.status == 200) {
				// success
				document.getElementById("modalDialog").innerHTML = xmlHttp.responseText;
				document.getElementById("modalDialogTitle").innerHTML = dialogTitle;
				registerDraggableElement(document.getElementById("modalDialog"), document.getElementById("modalDialogHeader"), false);
				if (focalElementId) document.getElementById(focalElementId).focus();
			} else {
				// failure
				alert('An error occurred. Please try again later. (Error ' + xmlHttp.status + ': ' + xmlHttp.statusText + ')');
				closeModalDialog();
				window.open().document.write(xmlHttp.responseText);
			}
		}
	}
	xmlHttp.open("GET",url,true);
	xmlHttp.send(null);

	return;
}

function closeModalDialog()
{
	document.body.removeChild( document.getElementById("modalDialog") );
	document.body.removeChild( document.getElementById("modalDialogDimmer") );
}

function _modalDialogHandleWindowScrollOrResize()
{
	var divDimmer = document.getElementById("modalDialogDimmer");
	if (divDimmer) {
		divDimmer.style.top = getScrollTop()+"px";
		divDimmer.style.left = getScrollLeft()+"px";
		divDimmer.style.width = getClientWidth()+"px";
		divDimmer.style.height = getClientHeight()+"px";
	}
}

function submitModalForm(formElement, baseURL, successMessage, async)
/*
 * POST the modal dialog's form via AJAX.
 * If async is true, submit is done async otherwise not.
 * formElement data is POSTed to baseURL
 * If successMessage is null, no success dialog will be displayed to the user.
 * An Alert is displayed on failure in all cases.
 */
{
	var params = "";
	for (var i = 0; i < formElement.length; i++) {
		var field = formElement.elements[i];
		if (i > 0) params += "&";
		params += escape(field.name)+"="+escape(field.value);
	}
	var url = baseURL+"?"+params;
	
	// ajax to send data
	var xmlHttp = getXMLHttpRequest();
	xmlHttp.onreadystatechange = function() {
		if (xmlHttp.readyState == 4) {
			// ready to process result
			if (async) _stopAsyncWait();
			if (xmlHttp.status == 200) {
				// success
				closeModalDialog();
				if (successMessage && successMessage.length > 0) openMessageDialog(successMessage);
			} else {
				// failure
				alert('An error occurred. Please try again later. (Error ' + xmlHttp.status + ': ' + xmlHttp.statusText + ')');
				window.open().document.write(xmlHttp.responseText);
			}
		}
	}
	xmlHttp.open("POST",url,async);
	xmlHttp.send(null);
	
	if (async) _startAsyncWait();
	
	return false; // critical to return false to prevent normal submit behaviour on some browsers
}

function _startAsyncWait()
{
	var divDimmer = document.getElementById("modalDialogDimmer");
	var waitIconTopMargin = (getClientHeight() / 2) - (WAIT_ICON_HEIGHT / 2);
	divDimmer.innerHTML = '<img class="wait" style="margin-top:'+waitIconTopMargin+'px" src="/images/ui/wait.gif" alt="Please Wait" />';
	divDimmer.style.zIndex = 200;
}

function _stopAsyncWait()
{
	var divDimmer = document.getElementById("modalDialogDimmer");
	divDimmer.innerHTML = '';
	divDimmer.style.zIndex = 90;
}


/*********************************************************************************************
 * Methods for handling draggable objects: 
 *      registerDraggableElement(elementToDrag, hotSpotElement, isElementPoppedToTopOnDrag)
 *      _isHotSpotMatch(hotSpot, srcElement)
 *      _dragMouseDown(e)
 *      _dragMouseMove(e)
 *      _dragMouseUp(e)
 *********************************************************************************************/
var mouseDownX;
var mouseDownY;
var origAbsLeft;
var origAbsTop;
var draggableElements = [];
var hotSpotElements = [];
var isPopToTop = [];
var activeIndex;

function registerDraggableElement(elementToDrag, hotSpotElement, isElementPoppedToTopOnDrag)
{
	draggableElements.push(elementToDrag);
	hotSpotElements.push(hotSpotElement);
	isPopToTop.push(isElementPoppedToTopOnDrag);
	hotSpotElement.onmousedown = _dragMouseDown;
}

function _isHotSpotMatch(hotSpot, srcElement)
{
	if (hotSpot == srcElement) {
		return true;
	} else {
		if (srcElement.parentNode) return _isHotSpotMatch(hotSpot, srcElement.parentNode);
	}
	return false;
}

function _dragMouseDown(e)
{
	// get event and its srcElement in browser independant way
	if (!e) e = window.event;
	var sourceElement;
	if (e.target) sourceElement = e.target;
	else if (e.srcElement) sourceElement = e.srcElement;
	if (sourceElement.nodeType == 3) sourceElement = sourceElement.parentNode; // defeat Safari bug
	
	// set activeIndex 
	for (activeIndex = 0; activeIndex < hotSpotElements.length; activeIndex++) {
		if ( _isHotSpotMatch(hotSpotElements[activeIndex], sourceElement) ) break;
	}
	
	// save orig mouse down location
	var dragElement = draggableElements[activeIndex];
	mouseDownX = e.clientX;
	mouseDownY = e.clientY;
	
	// set new mouseMove & mouseUp handlers + cursor for hotspot
	document.body.onmousemove = _dragMouseMove;
	document.body.onmouseup = _dragMouseUp;
	hotSpotElements[activeIndex].style.cursor = "move";

	// modify zIndex only if asked - WE CAN REMOVE THIS - CAN DESIGN PAGE IN WAY NOT NEEDED
	if (isPopToTop[activeIndex] == true) dragElement.style.zIndex = dragElement.style.zIndex + 1;
	
	origAbsLeft = getAbsoluteLeft(dragElement);
	origAbsTop = getAbsoluteTop(dragElement);
	
	dragElement.style.left = origAbsLeft + 'px';
	dragElement.style.top = origAbsTop + 'px';
	dragElement.style.position = "absolute";
}

function _dragMouseMove(e)
{
	if (!e) e = window.event;
	draggableElements[activeIndex].style.left = (e.clientX - mouseDownX + origAbsLeft) + 'px';
	draggableElements[activeIndex].style.top = (e.clientY - mouseDownY + origAbsTop) + 'px';
}

function _dragMouseUp(e)
{
	if (!e) e = window.event;
	document.body.onmousemove = null;
	document.body.onmouseup = null;
	hotSpotElements[activeIndex].style.cursor = "auto";
}


/*********************************************************************************************
 * other misc functions 
 *
 *********************************************************************************************/
 
 