function _init()
{
	iTimeoutDelay = 100;
	oSuggestTimer = false;
	parseSuggestions();
	return;
}
function addText(oAttach, sText)
{
	var oText = document.createTextNode(sText);
	oAttach.appendChild(oText);
	return;
}
function safeRegExp(sText)
{
	return sText.replace(/([\^$(){}|?\\\/*+\[\].])/g, '\\$1');
}
function containsClass(oElement, sClass)
{
	var _regex = new RegExp("(^| )" + safeRegExp(sClass) + "( |$)");
	return ( _regex.test(oElement.className) ) ? true : false;
}
function addClass(oElement, sClass)
{
	var _regex = new RegExp("(^| )" + safeRegExp(sClass) + "( |$)");
	if ( oElement.className.length > 0 ) {
		if ( !(_regex.test(oElement.className)) ) {
			oElement.className += ' ' + sClass;
		}
	} else {
		oElement.className = sClass;
	}
	return;
}
function removeClass(oElement, sClass)
{
	var _regex = new RegExp("(^| )" + safeRegExp(sClass) + "( |$)", "g");
	oElement.className = oElement.className.replace(_regex, "");
	return;
}
function insertAfter(oNew, oTarget)
{
	var oParent = oTarget.parentNode;
	if ( oParent.lastChild == oTarget ) {
		oParent.appendChild(oNew);
	} else {
		oParent.insertBefore(oNew, oTarget.nextSibling);
	}
	return;
}
function clearNode(oNode)
{
	while (oNode.childNodes[0]) {
		oNode.removeChild(oNode.childNodes[0]);
	}
	return;
}
function keyStroke(evt)
{
	var charCode = (evt.charCode || evt.keyCode || evt.which || 0);
	switch ( charCode ) {
		
		case 3:
		case 13:
			return 13;	//	enter
		
		case 9:
		case 25:
			return 9;	//	tab
		
		case 33:
		case 63276:
			return 33;	//	page up
		
		case 34:
		case 63277:
			return 34;	//	page down
		
		case 35:
		case 63275:
			return 35;	//	end
		
		case 36:
		case 63273:
			return 36;	//	home
		
		case 28:
		case 37:
		case 63234:
			return 37;	//	left arrow
		
		case 30:
		case 38:
		case 63232:
			return 38;	//	up arrow
		
		case 29:
		case 39:
		case 63235:
			return 39;	//	right arrow
		
		case 31:
		case 40:
		case 63233:
			return 40;	//	down arrow
		
		case 45:
		case 63302:
			return 45;	//	insert
		
		case 46:
		case 63272:
			return 46;	//	delete
		
		case 144:
		case 63289:
			return 144;	//	num lock
		
		default:
			break;
		
	}
	
	return charCode;
}
function normalCharCode(charCode)
{
	switch ( charCode )
	{
		case 8:
		case 9:
		case 16:
		case 33:
		case 34:
		case 35:
		case 36:
		case 37:
		case 38:
		case 39:
		case 40:
		case 45:
		case 46:
		case 144:
			return false;
		
		default:
			break;
	}
	return true;
}
function cancelEvent(evt)
{
	if ( evt.preventDefault || evt.stopPropagation ) {
		if ( evt.preventDefault ) {
			evt.preventDefault();
		}
		if ( evt.stopPropagation ) {
			evt.stopPropagation();
		}
	} else {
		evt.keyCode = 0;
		evt.returnValue = false;
	}
	return;
}
function placeCursorAtEnd(mObjectOrId, sDelay)
{
	if ( typeof mObjectOrId == 'object' ) {
		var oText = mObjectOrId;
	} else {
		var oText = document.getElementById(mObjectOrId);
	}
	if ( sDelay != true ) {
		window.setTimeout("placeCursorAtEnd('" + oText.id + "', true);", 1);
	} else {
		if ( oText.setSelectionRange ) {
			oText.setSelectionRange(oText.value.length, oText.value.length);
		} else if ( oText.createTextRange ) {
			var range = oText.createTextRange();
			range.collapse(true);
			range.moveEnd('character', oText.value.length);
			range.moveStart('character', oText.value.length);
			range.select();
		}
	}
	return;
}
function suggestKeyDown(evt)
{
	evt = ( evt || window.event );
	evt.key = keyStroke(evt);
	evt.targetNode = ( evt.srcElement || evt.target );
	var sID = evt.targetNode.id;
	
	//	clear pending requests
	window.clearTimeout(oSuggestTimer);
	
	switch ( evt.key ) {
		
		case 9:		//	tab
			
			if ( document.getElementById('s_' + sID) ) {
				if ( !(evt.shiftKey) ) {
					selectSuggestion(sID);
				}
				clearSuggestions(sID);
			}
			break;
		
		case 38:	//	up
		case 40:	//	down
			
			var oCells = document.getElementById('s_' + sID).getElementsByTagName('td');
			for (var i = 0, sIndex = false; i < oCells.length; i++) {
				if ( oCells[i].className == 'selected' ) {
					sIndex = i;
					break;
				}
			}
			if ( sIndex === false ) {
				sIndex = ( evt.key == 38 ) ? 0 : -1;
			}
			sIndex = ((( evt.key == 38 ) ? --sIndex : ++sIndex) + oCells.length) % oCells.length;
			for (var i = 0; i < oCells.length; i++) {
				oCells[i].className = ( i == sIndex ) ? 'selected' : "";
			}
			break;
		
	}
	return;
}
function suggestKeyPress(evt)
{
	evt = ( evt || window.event );
	evt.key = keyStroke(evt);
	evt.targetNode = ( evt.srcElement || evt.target );
	var sID = evt.targetNode.id;
	
	//	enter
	if ( evt.key == 13 ) {
		
		if ( document.getElementById('s_' + sID) ) {
			selectSuggestion(sID);
			cancelEvent(evt);
			clearSuggestions(sID);
		}
		
	}
	
	return;
}
function suggestKeyUp(evt)
{
	evt = ( evt || window.event );
	evt.key = keyStroke(evt);
	evt.targetNode = ( evt.srcElement || evt.target );
	var sID = evt.targetNode.id;
	
	//	clear pending requests
	window.clearTimeout(oSuggestTimer);
	
	switch ( evt.key ) {
		
		case 13:	//	enter
			placeCursorAtEnd(sID);
			break;
		
		case 38:	//	up
		case 40:	//	down
			placeCursorAtEnd(sID);
			break;
		
		case 8:		//	backspace
		case 46:	//	delete
			if ( evt.targetNode.value.length == 0 ) {
				clearSuggestions(sID);
			} else {
				delayRequest(sID);
			}
			break;
		
		default:
			if ( normalCharCode(evt.key) ) {
				delayRequest(sID);
			}
			break;
		
	}
	return;
}
function suggestBlur(evt)
{
	evt = ( evt || window.event );
	evt.targetNode = ( evt.srcElement || evt.target );
	var sID = evt.targetNode.id;
	
	window.clearTimeout(oSuggestTimer);
	oSuggestTimer = window.setTimeout("clearSuggestions('" + sID + "');", iTimeoutDelay);
}
function delayRequest(sID)
{
	oSuggestTimer = window.setTimeout("suggestRequest('" + sID + "');", iTimeoutDelay);
	return;
}
function suggestRequest(mObjectOrID)
{
	if ( typeof mObjectOrID == 'object' ) {
		var oText = mObjectOrID;
	} else {
		var oText = document.getElementById(mObjectOrID);
	}
	if ( oText ) {
		sParams = 'name=' + encodeURIComponent(oText.id);
		sParams += '&search=' + encodeURIComponent(oText.value);
		var sForm = oText.form.getAttribute('id');
		if ( sForm ) {
			sParams += '&form=' + encodeURIComponent(sForm);
		}
		var sURL = '/index.php?neverrewind&module=whla.websiteforms&cmd=getcities';
		ajax(sURL, 'get', 'receiveSuggestions', sParams);
	}
	return;
}
function getPosition(oNode, iHorz, iVert)
{
	var sHorz = 0;
	var sVert = 0;
	if ( typeof iHorz == 'number' ) {
		sHorz = iHorz;
	}
	if ( typeof iVert == 'number' ) {
		sVert = iVert;
	}
	if ( oNode.offsetParent ) {
		while ( oNode.offsetParent ) {
			sHorz += oNode.offsetLeft;
			sVert += oNode.offsetTop;
			oNode = oNode.offsetParent;
		}
		sHorz += oNode.offsetLeft;
		sVert += oNode.offsetTop;
	} else if ( oNode.x && oNode.y ) {
		sHorz += oNode.x;
		sVert += oNode.y;
	}
	return [sHorz.toString() + 'px', sVert.toString() + 'px'];
}
function createSuggestionBox(sData, sID)
{
	clearSuggestions();
	var oContainer = document.createElement('table');
	var oSuggestions = document.createElement('tbody');
	oContainer.appendChild(oSuggestions);
	oContainer.className = 'suggestions';
	oContainer.id = 's_' + sID;
	for (var i = 0; i < sData[1].length; i++) {
		addSuggestion(oSuggestions, sData[0], sData[1][i], (( i ) ? false : true), sID);
	}
	appendSuggestionBox(oContainer, sID);
	hideSelects(true);
}
function addSuggestion(oSuggestions, sOriginal, sDatum, sSelected, sID)
{
	var oRow = document.createElement('tr');
	var oCell = document.createElement('td');
	
	var sSplit = splitText(sOriginal, sDatum, false);
	if ( sSplit[0].length ) {
		addText(oCell, sSplit[0]);
	}
	if ( sSplit[1].length ) {
		var oBold = document.createElement('span');
		oBold.className = 'bold';
		oCell.appendChild(oBold);
		addText(oBold, sSplit[1]);
	}
	if ( sSplit[2].length ) {
		addText(oCell, sSplit[2]);
	}
	oRow.appendChild(oCell);
	oSuggestions.appendChild(oRow);
	oCell.onmousedown = function() { selectSuggestion(sID, true); };
	oCell.onmouseover = function() { deselectRows(sID); this.className = 'selected'; };
	oCell.onmouseout = function() { this.className = ""; };
	if ( sSelected ) {
		oCell.className = 'selected';
	}
	return;
}

function splitText(sOriginal, sDatum, sLoose)
{
	var sRegex = (( sLoose == true ) ? '^(.*?)' : '(^|.+?\\s)') + '(' + safeRegExp(sOriginal) + ')(.*?)$';
	var sPattern = new RegExp(sRegex, 'i');
	if ( sPattern.test(sDatum) ) {
		var sSplit = sPattern.exec(sDatum);
		return [sSplit[1], sSplit[2], sSplit[3]];
	}
	return [sDatum, "", ""];
}
function deselectRows(sID)
{
	var oCells = document.getElementById('s_' + sID).getElementsByTagName('td');
	for (var i = 0; i < oCells.length; i++) {
		oCells[i].className = "";
	}
	return;
}
function appendSuggestionBox(oContainer, mObjectOrId)
{
	if ( typeof mObjectOrId == 'object' ) {
		var oInput = mObjectOrId;
	} else {
		var oInput = document.getElementById(mObjectOrId);
	}
	var sPosition = getPosition(oInput, 0, oInput.offsetHeight);
	oContainer.style.left = sPosition[0];
	oContainer.style.top = sPosition[1];
	oContainer.setAttribute('width', oInput.offsetWidth);
	oContainer.style.position = 'absolute';
	oContainer.setAttribute('cellPadding', 0);
	oContainer.setAttribute('cellSpacing', 0);
	var sTagName = oInput.parentNode.tagName.toLowerCase();
	var oNode = ( /^(body|form|td|th)$/i.test(sTagName) ) ? oInput : oInput.parentNode;
	document.body.appendChild(oContainer);
	return;
}
function selectSuggestion(mObjectOrId, bClose)
{
	if ( typeof mObjectOrId == 'object' ) {
		var oText = mObjectOrId;
	} else {
		var oText = document.getElementById(mObjectOrId);
	}
	var oCells = document.getElementById('s_' + oText.id).getElementsByTagName('td');
	for (var i = 0; i < oCells.length; i++) {
		if ( oCells[i].className == 'selected' ) {
			oText.value = getSuggestionText(oCells[i]);
			break;
		}
	}
	if ( bClose == true ) {
		clearSuggestions(oText.id);
	}
	return;
}
function getSuggestionText(oCell)
{
	var sText = "";
	var oTexts = oCell.childNodes;
	for (var i = 0; i < oTexts.length; i++) {
		var oText = oTexts[i];
		while ( oText.nodeType != 3 ) {
			oText = oText.firstChild;
		}
		sText += oText.nodeValue;
	}
	return sText;
}
function clearSuggestions(sID)
{
	if ( sID == null ) {
		
		var oContainers = getElementsByClass('suggestions');
		var i = oContainers.length;
		while ( (i--) > 0 ) {
			var oParent = oContainers[i].parentNode;
			oParent.removeChild(oContainers[i]);
		}
		
	} else {
		
		var oContainer = document.getElementById('s_' + sID);
		if ( oContainer ) {
			var oParent = oContainer.parentNode;
			oParent.removeChild(oContainer);
		}
		
	}
	
	hideSelects(false);
	return;
}
function receiveSuggestions(sResponse)
{
	try {
		eval('var jResponse = ' + sResponse);
	} catch (e) {
		return;
	}
	if ( jResponse['error'] != 0 ) {
		return;
	}
	var oText = document.getElementById(jResponse['name']);
	if ( jResponse['form'] ) {
		oForm = document.forms[jResponse['form']];
	} else {
		oForm = null;
	}
	if ( oText ) {
		if ( oForm && oForm != oText.form ) {
			return false;
		}
		if ( jResponse['data'].length ) {
			createSuggestionBox([jResponse['search'], jResponse['data']], jResponse['name']);
		} else {
			clearSuggestions(jResponse['name']);
		}
	}
	return;
}
function parseSuggestions()
{
	var oSuggests = getElementsByClass('suggest', document, 'input');
	for (var i = 0; i < oSuggests.length; i++) {
		xAddEventListener(oSuggests[i], 'keydown', suggestKeyDown);
		xAddEventListener(oSuggests[i], 'keypress', suggestKeyPress);
		xAddEventListener(oSuggests[i], 'keyup', suggestKeyUp);
		xAddEventListener(oSuggests[i], 'blur', suggestBlur);
		oSuggests[i].setAttribute('autocomplete', 'off');
		if ( oSuggests[i].value.length > 0 ) {
			oSuggests[i].setAttribute('ctg:hint', oSuggests[i].value);
		}
	}
	
	return;
}
function hideSelects(bHide)
{
	if ( /msie [56]/i.test(navigator.userAgent) ) {
		
		var oSelects = document.getElementsByTagName('select');
		for (var i = 0; i < oSelects.length; i++) {
			
			if ( bHide ) {
				
				//	create table
				var oHideTable = document.createElement('table');
				var oHideTbody = document.createElement('tbody');
				var oHideTrow  = document.createElement('tr');
				var oHideTcell = document.createElement('td');
				//	set sizing
				oHideTable.style.margin = oSelects[i].style.margin;
				oHideTable.style.padding = oSelects[i].style.padding;
				oHideTable.style.height = oSelects[i].offsetHeight + 'px';
				oHideTable.style.width  = oSelects[i].offsetWidth + 'px';
				oHideTable.style.borderCollapse = 'collapse';
				oHideTable.style.verticalAlign = 'middle';
				oHideTable.style.display = 'inline';
				//	add table
				oHideTrow.appendChild(oHideTcell);
				oHideTbody.appendChild(oHideTrow);
				oHideTable.appendChild(oHideTbody);
				//	hide and add
				oSelects[i].style.display = 'none';
				insertAfter(oHideTable, oSelects[i]);
				oHideTable.className = 'delete_me';
				
			} else if ( getElementsByClass('suggestions', document, 'table').length == 0 ) {
				
				//	remove table
				if ( oSelects[i].nextSibling ) {
					if ( oSelects[i].nextSibling.className == 'delete_me' ) {
						oSelects[i].parentNode.removeChild(oSelects[i].nextSibling);
					}
				}
				
				//	show select box
				oSelects[i].style.display = 'inline';
				
			}
			
		}
		
	}
	
	return;
}
function isAncestor(oNode, oParent)
{
	var oParentCheck = oNode.parentNode;
	while ( !(/^(body|html)$/i.test(oParentCheck.tagName)) ) {
		if ( oParent == oParentCheck ) {
			return (true);
		}
		oParentCheck = oParentCheck.parentNode;
	}
	return ( oParent == document.body ) ? true : false;
}
/*----------------------------------------*/
function xAddEventListener(oElement, sType, fListener)
{
	if ( oElement.addEventListener ) {
		oElement.addEventListener(sType, fListener, false);
	} else if ( oElement.attachEvent ) {
		oElement.attachEvent('on' + sType, fListener);
	} else if ( typeof oElement['on' + sType] == 'function' ) {
		var fOld = oElement['on' + sType];
		oElement['on' + sType] = function()
		{
			fOld();
			fListener();
		}
	} else {
		oElement['on' + sType] = fListener;
	}
	return;
}
function getElementsByClass(sClass, oNode, sTag)
{
	var oFinal = new Array();
	if ( oNode == null ) {
		oNode = document;
	}
	if ( sTag == null ) {
		sTag = '*';
	}
	var oPotential = oNode.getElementsByTagName(sTag);
	var sPattern = new RegExp('(^|\\s)' + sClass + '(\\s|$)');
	for (var i = 0, j = 0; i < oPotential.length; i++) {
		if ( sPattern.test(oPotential[i].className) ) {
			oFinal[j] = oPotential[i];
			j++;
		}
	}
	return oFinal;
}
ready(function() {
	_init();
});
