// ***** function to open any links using rel="external" into a new window. Needed because the target parameter in an href is being phased out
function externalLinks() { 
 if (!document.getElementsByTagName) return; 
 var anchors = document.getElementsByTagName("a"); 
 for (var i=0; i<anchors.length; i++) { 
   var anchor = anchors[i]; 
   if (anchor.getAttribute("href") && 
       anchor.getAttribute("rel") == "external") 
     anchor.target = "_blank"; 
 } 
}
// ***** function to open a new window
function hxsPopup(file,winname,properties)
{
	var openWindow = window.open(file,winname,properties);
	openWindow.focus();
}
// ***** function to open link in parent window
function hxsParentOpener(url)
{
	window.opener.location=url;
	window.opener.focus();	
}
// ***** function to submit a form
function submitForm(formName)
{
	document.forms[formName].submit();
}
// ***** function to change the location of the page based on a value selected from a select list in a form
function pageJump()
{
	location.href = arguments[0].value
}
// ***** function to add smilie text to a textarea
function addSmilie(form,field,smilie)
{
	document.forms[form].elements[field].value=document.forms[form].elements[field].value+smilie;
	document.forms[form].elements[field].focus();
}
// ***** function to clear a form field
function clearField(form,field)
{
	document.forms[form].elements[field].value='';
	document.forms[form].elements[field].focus();
}
// ***** function to show or hide a div
function showHideDiv2(divID,action)
{
	var divs = document.getElementsByTagName('div'); 
	for(i=0;i<divs.length;i++)
	{ 
		if(divs[i].id.match(divID))
		{ 
			if (document.getElementById) 
				if ( (divs[i].style.display == 'block' || action == 'hide' || divs[i].style.display == '') && action != 'show' )
				{
					divs[i].style.display = 'none';
				} else {
					divs[i].style.display = 'block';
				}
			else if (document.layers) // Netscape 4 
				if ( (document.layers[divs[i]].display == 'block' || action == 'hide' || divs[i].style.display == '') && action != 'show' )
				{
					document.layers[divs[i]].display = 'none'; 
				} else {
					document.layers[divs[i]].display = 'block';
				}
			else // IE 4 
				if ( (document.all.hideShow.divs[i].visibility == 'visible' || action == 'hide' || divs[i].style.display == '') && action != 'show' )
				{
					document.all.hideShow.divs[i].visibility = 'hidden'; 
				} else {
					document.all.hideShow.divs[i].visibility = 'visible'; 
				}
		} 
	} 
}
// ***** function to do menu mousovers for IE as it's crap with CSS
cssMenu = function() 
{
	if (document.all&&document.getElementById) 
	{
		// find the <ul> for the menu
		navRoot = document.getElementById("cssMenu");
		if (navRoot)
		{
			var lis=navRoot.getElementsByTagName("LI");
			// loop through all its nodes
			for (i=0; i<lis.length; i++)
			{
				lis[i].onmouseover=function()
				{
					this.className+=" over";
				}
				lis[i].onmouseout=function()
				{
					this.className=this.className.replace(" over", "");
				}
			} // end of for to loop through all nodes
		}
	} // end of if to check browser
} // end of function
// ***** function to validate fields in a form
function validateFields(formName,fieldNameArray,fieldWarnings,fieldExtraArray,validateType)
{
	// initialise
	var requiredSingleFound = 'no';
	var requiredSingleWarning = 'You must populate at least one of the following fields - \n';
	
	// loop through the fields we want to check
	for (var loop = 0; loop < fieldNameArray.length; loop++)
	{
		var currField = document.forms[formName].elements[fieldNameArray[loop]];
		// required fields
		if (validateType == 'required')
		{
			if ( (currField.type == 'checkbox' && currField.checked == false) || (currField.type != 'checkbox' && currField.value == '') )
			{
				validateFieldsAlert(fieldWarnings[loop], currField);
				return false;
			}
		// one field out of a group of fields required
		} else if (validateType == 'requiredSingle' && requiredSingleFound == 'no') {
			if ( (currField.type == 'checkbox' && currField.checked == true) || (currField.type != 'checkbox' && currField.value != '') )
			{
				requiredSingleFound = 'yes';
			} else {
				requiredSingleWarning = requiredSingleWarning + fieldWarnings[loop] + '\n';
				if (loop == 0)
				{
					requiredSingleField = currField;
				}
			}
		// minimum length fields
		} else if (validateType == 'minLength') {
			var minSize = fieldExtraArray[loop];
			if (currField.value.length < minSize && currField.value != '')
			{
				validateFieldsAlert(fieldWarnings[loop], currField);
				return false;
			}
		// fields with equal values
		} else if (validateType == 'match') {
			if ((currField.value) != document.forms[formName].elements[fieldExtraArray[loop]].value)
			{
				validateFieldsAlert(fieldWarnings[loop], currField);
				return false;
			}
		// fields with differing values
		} else if (validateType == 'differ') {
			if ((currField.value) == document.forms[formName].elements[fieldExtraArray[loop]].value)
			{
				validateFieldsAlert(fieldWarnings[loop], currField);
				return false;
			}
		// email fields
		} else if (validateType == 'email'  && currField.value != '') {
			var level = 4;  // level of strictness, 0 = lowest, 3 = highest, 4 = steve's edit
			var emailPatterns = [
				/.+@.+\..+$/i,
				/^\w.+@\w.+\.[a-z]+$/i,
				/^\w[-_a-z~.]+@\w[-_a-z~.]+\.[a-z]{2}[a-z]*$/i,
				/^\w[\w\d]+(\.[\w\d]+)*@\w[\w\d]+(\.[\w\d]+)*\.[a-z]{2,7}$/i,
				/^([a-zA-Z0-9])+([\.a-zA-Z0-9_-])*@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-]+)+$/
				];
			if ( ! emailPatterns[level].test( currField.value ) )
			{
				validateFieldsAlert(fieldWarnings[loop], currField);
				return false;
			}
		// url fields
		} else if (validateType == 'url' && currField.value != '') {
			//urlPattern = /^(file|http):\/\/\S+\.(com|net|org|info|biz|ws|us|tv|cc)$/i
			urlPattern = /^(?:(?:ftp|https?):\/\/)?(?:[a-z0-9](?:[-a-z0-9]*[a-z0-9])?\.)+(?:com|edu|biz|org|gov|int|info|mil|net|name|museum|coop|aero|[a-z][a-z])\b(?:\d+)?(?:\/[^;"'<>()\[\]{}\s\x7f-\xff]*(?:[.,?]+[^;"'<>()\[\]{}\s\x7f-\xff]+)*)?/;
			if ( ! urlPattern.test( currField.value ) )
			{
				validateFieldsAlert(fieldWarnings[loop], currField);
				return false;
			}
		}
	}
	// check at the end for the required single fields
	if (validateType == 'requiredSingle' && requiredSingleFound == 'no')
	{
		validateFieldsAlert(requiredSingleWarning, requiredSingleField);
		return false;
	}
}
// ***** throw an alert message for field validation alerts
function validateFieldsAlert(message, focusField)
{
	alert (message);
	focusField.focus();
}
// ***** check a field for invalid characters
function validCharacters(evt)
{
	var keyCode = evt.which ? evt.which : evt.keyCode;
	// var prohibited = "*(|),\\\":<>[]{}`';&$#%";
	var prohibited = "(,|\\\":<>`';&%)";
	if (prohibited.indexOf(String.fromCharCode(keyCode)) >= 0)
	{
		alert ('The following characters are not permitted in this field\n\n'+prohibited+'\n\nIf the data in this field existed before this limitation was put in place then plese contact az@hexus.org');
		return false;
	}
}
// ***** check a field that can only contain numeric characters
function checkNumeric()
{
	var key = window.event.keyCode;
	if (key <= 47 || key >= 58)
	{
   		alert ('Only numeric digits are permitted in this field\n\nIf the data in this field existed before this limitation was put in place then plese contact az@hexus.org');
		return false;
	}
}
// ***** tries to check if the user has caps lock turned on. Doesn't work yet
function checkCaps()
{
	if (event.keyCode == 20)
	{
		alert ('You have CAPS LOCK on. This may cause your username or password to be wrongly entered');
	}
	return false;
}
// ***** function to resize the page columns if the window is resized
function winOnResize()
{
	adjustLayout();
}
// ***** function to find out which column on the page has the largest height and ensure all columns have the same height
function adjustLayout()
{
	// Get content heights
	var cHeight = xHeight('cCol');
	var lHeight = xHeight('lCol');
	var rHeight = xHeight('rCol');
	
	// Find the maximum height
	var maxHeight = Math.max(cHeight, Math.max(lHeight, rHeight));
	
	// Assign maximum height to all columns
	xHeight('cCol', maxHeight);
	xHeight('lCol', maxHeight);
	xHeight('rCol', maxHeight);
}
// ***** function to add a bookmark to the user's browser
function addBookmark(url,title)
{
	if (title=='') {title=url};
	if (document.all)
	{
		window.external.AddFavorite(url,title);
	} else {
		alert('Press CTRL and D to add a bookmark to:\n"'+url+'".');
	}
} 
// ***** function to execute functions in the onLoad event
function onLoadEvents()
{
	externalLinks();
	cssMenu();
	xmlSearch();
	if(document.getElementById && document.createTextNode)
	{
		ul2finder();
	}
	var ele = xGetElementById('lCol');
	if (ele && xDef(ele.style, ele.offsetHeight)) 
	{ // another compatibility check
		adjustLayout();
		xAddEventListener(window, 'resize', winOnResize, false);
	}
}
// ***** function to execute functions in the onLoad event without the X scripts
function onLoadEventsSkipX()
{
	externalLinks();
	cssMenu();
	ul2finder();
}

//***** NEW FUNCTIONS TO BE USED WITH NEW SITE *****
//*** function to update a div next to a multi-select form to let the user know what they've selected
function updateMultiSelectDisplay(divName, fieldName)
{
	var namedDiv = document.getElementById(divName);
	var selObj = document.getElementById(fieldName);
	var selectedArray = new Array();
	var selectedText = '';
	var count = 0;
	for (i=0; i<selObj.options.length; i++) 
	{
		if (selObj.options[i].selected && selObj.options[i].value != '') 
		{
			selectedArray[count] = selObj.options[i].text; // this line stores the values of the options
			selectedText = selectedText+'<br />'+selObj.options[i].text; // this line stores the text of the options
			count++;
		}
	}			
	if (selectedText != '')
	{
		namedDiv.innerHTML = '<strong>You have currently selected</strong>'+selectedText;
	}
}
//*** function to show or hide a div without the fancy scrolling effect
function showHideDiv(divID,action)
{
	var divs = document.getElementsByTagName('div'); 
	for(i=0;i<divs.length;i++)
	{ 
		if(divs[i].id.match(divID))
		{ 
			if ( (divs[i].style.display == 'block' || action == 'hide' || divs[i].style.display == '') && action != 'show' )
			{
				divs[i].style.display = 'none';
			} else {
				divs[i].style.display = 'block';
			}
		} 
	} 
}
//*** functions for XML search
var req;
var xmlSearchResultsDiv;
var globalKey;
function Initialize()
{
	try
	{
		req=new ActiveXObject("Msxml2.XMLHTTP");
	}
	catch(e)
	{
		try
		{
			req=new ActiveXObject("Microsoft.XMLHTTP");
		}
		catch(oc)
		{
			req=null;
		}
	}
	if(!req && typeof XMLHttpRequest!="undefined")
	{
		req = new XMLHttpRequest();
	}
}
function SendQuery(key, url, xmlSearchDiv, searchType)
{
	Initialize();
	var url = url+"?search="+key;
	globalKey = key;
	xmlSearchResultsDiv = xmlSearchDiv;
	if(req!=null)
	{
		req.onreadystatechange = Process;req.open("GET", url, true);
		req.send(null);
	}
}
function Process()
{
	var keyArray = globalKey.split("__");
	if ( (keyArray[0] != '' && keyArray[1] != '') || keyArray[2].length >= 3)
	{
		showHideDiv(xmlSearchResultsDiv, "show");
		document.getElementById(xmlSearchResultsDiv).innerHTML = '<div class="xmlSearching">Searching<br /><img src="http://img.hexus.net/hexus_v2/images/site/search_animation.gif" /></div>';	
	}
	if (req.readyState == 4)
	{
		if (req.status == 200)
		{
			if(req.responseText=="")
			{
				showHideDiv(xmlSearchResultsDiv, "hide");
			} else {
				showHideDiv(xmlSearchResultsDiv, "show");
				document.getElementById(xmlSearchResultsDiv).innerHTML = req.responseText;
			}
		} else {
			document.getElementById(xmlSearchResultsDiv).innerHTML = "There was a problem retrieving data:<br>"+req.statusText;
		}
	}
}
function xmlSearch(xmlSearchDiv)
{
	showHideDiv(xmlSearchDiv, "hide");
}

/*
 * aScroller js
 * 
 * Copyright (C) 2005-2006
 * by Davide S. Casali
 * www.digitalhymn.com
 *
 * Last release: 2005-11-27
 *
 * Released under CC by-nc-sa 2.5
 * http://creativecommons.org/licenses/by-nc-sa/2.5/
 *
 */

/*
 * This is a simple JavaScript vertical scroller that is crossbrowser and also validates
 * as XHTML Strict.
 *
 * Usage:
 * (1) Define a <div> tag with a specified ID, containing the scrolling text. One <div> for each line.
 * (2) Define an INLINE CSS width and height (important, MUST be inline)
 * (3) Execute the divScroller function, passing id, mode (h or v),  speed (higher number means
 *     slower) and delay (in ms).
 *
 */

/****************************************************************************************************

 * Cross browser getElementByID.
 * From: www.quirksmode.org

 *

 * @param	id

 */
function getObj(name)
{
	if (document.getElementById)
	{
		this.obj = document.getElementById(name);
		this.style = document.getElementById(name).style;
	}
	else if (document.all)
	{
		this.obj = document.all[name];
		this.style = document.all[name].style;
	}
	else if (document.layers)
	{
		this.obj = document.layers[name];
		this.style = document.layers[name];
	}

}

/****************************************************************************************************

 * Enables the scrolling for the specified div (matching id).

 *

 * @param	string id of the tag
 * @param	speed
 * @param	delay

 */
function divScroller(id, direction, speed, delay)
{
	if (document.getElementById)

	{

		// DOM3 = IE5+, NS6+, FF0.7+
		// *** Scroller

		var scroller = new getObj(id);
		
		// *** Debug force vars
		//scroller.style.height = "30px";
		//scroller.style.backgroundColor = "#FFEEEE";
		
		// *** Computed Styles
		//alert(scroller.obj.currentStyle.height);
		/*if (!scroller.style.height)
			if (scroller.obj.currentStyle)
				scroller.style.height = scroller.obj.currentStyle.height;
			else
				scroller.style.height = document.defaultView.getComputedStyle(scroller.obj, null).getPropertyValue("height");*/
		
		// *** Needed vars
		scroller.style.position = "relative";
		scroller.style.overflow = "hidden";
		
		// *** Generate scrolling inner <div>
		scroller.obj.innerHTML = "<div id=\"" + id + "_inner\">" + scroller.obj.innerHTML + "</div>";
		
		// *** Inner
		var inner = new getObj(id + "_inner");
		inner.style.position = "absolute";
		inner.style.left = parseInt(scroller.style.width) + "px";
		inner.style.top = parseInt(scroller.style.height) + "px";
		
		// *** Apply sub-styles
		//divScrollItemsStyler(id, direction);
		
		// *** Worker
		if (direction == "h" || direction == "horizontal")
		{
			// ****** HORIZONTAL
			// MouseOver: pauses the ticker
			scroller.obj.onmouseover = function() { divScroll_onMouseOver(id); };
			scroller.obj.onmouseout = function() { divScroll_onMouseOut(id); };
			
			// Create a temp element to evaluate the size (awful, but no better way to do this)
			fxpatch = navigator.userAgent.indexOf("Firefox") > -1 ? " left: -9000px;" : ""; // Firefox different CSS (on every other browser since IE5+ isn't needed)
			spanContent = "<span id=\"" + id + "_widthEval\" style=\"visibility: hidden; position: absolute; top: -100px; left: -1px; z-index: -10; white-space: nowrap;" + fxpatch + "\"><nobr>" + inner.obj.innerHTML + "</nobr></span>";
			if (document.createElement)
			{
				var span = document.createElement('span');
				span.innerHTML = spanContent;
				scroller.obj.appendChild(span);
			}
			else
			{
				document.write(spanContent);
			}
			var widthEval = new getObj(id + "_widthEval");
			
			// Setup the scrolling inner drawer
			inner.style.top = "0px";
			inner.style.whiteSpace = "nowrap";
			inner.style.width = widthEval.obj.offsetWidth + "px";
			limit = parseInt(inner.style.width);
			
			// Execute
			setTimeout("divScrollHelperH(\"" + id + "\", " + limit + ", " + speed + ", " + delay + ")", parseInt(speed));
		}
		else if (direction == "v" || direction == "vertical")
		{
			// ****** VERTICAL
			// Setup the scrolling inner drawer
			inner.style.left = "0px";
			inner.style.width = parseInt(scroller.style.width) + "px";
			limit = inner.obj.getElementsByTagName('div').length * parseInt(scroller.style.height);
			
			// Execute
			setTimeout("divScrollHelperV(\"" + id + "\", " + limit + ", " + speed + ", " + delay + ")", parseInt(speed));
		}

	}
}

/****************************************************************************************************

 * Helper for the HORIZONTAL scrolling for the specified div (matching id).
 * This is the real "ticker" function, executed to move the div.

 *

 * @param	string id of the tag
 * @param	pre-calculated height limit (to speed up execution)
 * @param	speed
 * @param	delay

 */
function divScrollHelperH(id, limit, speed, delay)
{
	if (document.getElementById)

	{

		// DOM3 = IE5+, NS6+, FF0.7+
		var scroller = new getObj(id);
		var inner = new getObj(id + "_inner");
		
		// *** Tick duration
		nextTick = speed;
		
		// *** Avoiding some errors
		if (!inner.style.left) inner.style.left = "0px";
		
		// *** Moving the inner div. At the end, restart.
		if (parseInt(inner.style.left) < -limit)
		{
			inner.style.left = parseInt(scroller.style.width) + "px";
		}
		else if (!scroller.obj.pause || scroller.obj.pause == false)
		{
			inner.style.left = (parseInt(inner.style.left) - 1) + "px";
			
			// Deceiving Opera8 stupidity
			//inner.style.width = parseInt(scroller.style.width) - (parseInt(inner.style.left) - 4) + "px";
		}
		
		// *** Bigger delay on item found
		// Skips borders to make transition without delays on loop
		/*if (!(parseInt(inner.style.left) == parseInt(scroller.style.width)) &&
			!(parseInt(inner.style.left) == -limit) &&
			(parseInt(inner.style.left) % parseInt(scroller.style.width)) == 0)
		{
			nextTick = delay;
		}*/
		
		// *** Tick!
		setTimeout("divScrollHelperH(\"" + id + "\", " + limit + ", " + speed + ", " + delay + ")", parseInt(nextTick));
	}
}

/****************************************************************************************************

 * Helper for the VERTICAL scrolling for the specified div (matching id).
 * This is the real "ticker" function, executed to move the div.

 *

 * @param	string id of the tag
 * @param	pre-calculated height limit (to speed up execution)
 * @param	speed
 * @param	delay

 */
function divScrollHelperV(id, limit, speed, delay)
{
	// DOM3 = IE5+, NS6+, FF0.7+
	var scroller = new getObj(id);
	var inner = new getObj(id + "_inner");
	
	// *** Tick duration
	nextTick = speed;
	
	// *** Avoiding some errors
	if (!inner.style.top) inner.style.top = "0px";
	
	// *** Moving the inner div. At the end, restart.
	if (parseInt(inner.style.top) < -limit)
	{
		inner.style.top = parseInt(scroller.style.height) + "px";
	}
	else
	{
		inner.style.top = (parseInt(inner.style.top) - 1) + "px";
	}
	
	// *** Bigger delay on item found
	// Skips borders to make transition without delays on loop
	if (!(parseInt(inner.style.top) == parseInt(scroller.style.height)) &&
		!(parseInt(inner.style.top) == -limit) &&
		(parseInt(inner.style.top) % parseInt(scroller.style.height)) == 0)
	{
		nextTick = delay;
	}
	
	// *** Tick!
	setTimeout("divScrollHelperV(\"" + id + "\", " + limit + ", " + speed + ", " + delay + ")", parseInt(nextTick));
}

/****************************************************************************************************

 * OnMouseOver helper for the HORIZONTAL scrolling for the specified div (matching id).

 *

 * @param	string id of the tag

 */
function divScroll_onMouseOver(id)
{
	var scroller = new getObj(id);
	scroller.obj.pause = true;
}

function divScroll_onMouseOut(id)
{
	var scroller = new getObj(id);
	scroller.obj.pause = false;
}

/****************************************************************************************************

 * Apply essential working styles to each <div> inside the scroller.

 *

 * @param	string id of the inner div

 */
function divScrollItemsStyler(id, direction)
{
	// DOM3 = IE5+, NS6+, FF0.7+
	var scroller = new getObj(id);
	var inner = new getObj(id + "_inner");
	
	elements = inner.obj.getElementsByTagName('div');
	
	for (var i = 0; i < elements.length; i++)
	{
		var item = elements.item(i);
		
		item.style.width = scroller.style.width;
	}
}

/****************************************************************************************************

 * Return to opener window, setting its parent product ID and name

 */

 function closeSetParent(id,name)
 {
	 var parentID = opener.document.getElementById('hxsPrdParent');
	 parentID.value = id;
	 var parentName = opener.document.getElementById('hxsPrdParentName');
	 parentName.value = name;

	 window.opener.focus();
	 window.close();
 }

 /****************************************************************************************************

 * Return to opener window, adding a product to the list

 */
 function closeAddProduct(id,name)
 {
	 var listID = opener.document.getElementById('hxsProducts');
	 var newElement = opener.document.createElement('option');
	 newElement.text = name;
	 newElement.value = id;
	 try {
		 listID.add(newElement, null); // !IE
     }
     catch(ex) {
		 listID.add(newElement); // IE
     }
	 
	 window.opener.focus();
	 window.close()
 }

  /****************************************************************************************************

 * Remove an item from a list

 */

 function removeFromList(listID)
 {
	 var listElement = document.getElementById(listID);
	 var i;
	 /* Gotta go backwards because removing items shuffles indices */
	 for (i = listElement.length - 1; i >= 0; i-- )
	 {
		 if (listElement.options[i].selected)
		 {
			 listElement.remove(i);
		 }
	 }
 }

  /****************************************************************************************************

 * Selects all items in a list

 */
 function listSelectAll(listID)
 {
	 var listElement = document.getElementById(listID);
	 var i;
	 for (i = 0; i < listElement.length; i++)
	 {
		 listElement.options[i].selected = true;
	 }
 }