/*
	Autocomplete / Custom Dropdown / Calendar script
	Copyright © 2008-2009 Frank Pelliccio, all rights reserved.
	
	Unauthorized duplication and / or distribution is
	strictly prohibited.

	Frank Pelliccio
	0xD media / design / development
	http://0xD.com
*/

var results = new Array();
var resultIDs = new Array();
var selected = -1;
var submitted = false;
var currentsearch = '';
var resultsvisible = false;
var noblur = false;
var processing = false;
var pending = false;
var userselected = false;
var strCurrentElement = '';

var acColor = '#808080';
var acSelectColor = '#606060';

var delay = 300; //ms between keystrokes

String.prototype.startsWith = function(str) {
	return (this.match("^"+str)==str)
}

String.prototype.trim = function(x) {
	if (x=='left')
		return this.replace(/^\s*/,'');
	if (x=='right')
		return this.replace(/\s*$/,'');
	if (x=='normalize')
		return this.replace(/\s{2,}/g,' ').trim();

	return this.trim('left').trim('right');
} 

function initAC(strElement) {
	if (strElement != strCurrentElement) {
		results = new Array();
		selected = -1;
		submitted = false;
		currentsearch = '';
		resultsvisible = false;
		noblur = false;
		processing = false;
		pending = false;
		userselected = false;

		clearResults();

		strCurrentElement = strElement;
	}
}

function cancelEvent(e) {
	if (!e)
		e = window.event;

	if (e.stopPropagation)
		e.stopPropagation();
	else
		e.cancelBubble = true;
}


function selectItem(index) {
	noblur = false;

	if (userselected) {
		currentsearch = results[index].replace(/&nbsp;/gi,'').trim();
		var intID = document.getElementById('int' + strCurrentElement + 'ID')
		if (intID) {
			intID.value = resultIDs[index];

			var acroot = document.getElementById('ac' + strCurrentElement + 'root');
			if (acroot.className == 'xdDropDownSubmit') {
				document.getElementById('str' + strCurrentElement).form.submit();
			}
		}
	}

	submitForm();
}

function findPos(obj) {
	var curleft = curtop = 0;
	if (obj.offsetParent) {
		curleft = obj.offsetLeft
		curtop = obj.offsetTop
		while (obj = obj.offsetParent) {
			curleft += obj.offsetLeft
			curtop += obj.offsetTop
		}
	}
	return [curleft,curtop];
}

function iscalendar(strElement) {
	var acroot = document.getElementById(acrootName());
	if (acroot) {
		return (acroot.className == 'xdCalendar');
	}
}

function acrootName() {
	return 'ac' + strCurrentElement + 'root';
}

function processData(strElement, strCompareString) {
	if (!pending) {
		initAC(strElement);

		var acroot = document.getElementById(acrootName());
		var isCalendar = iscalendar(acrootName());

		if (isCalendar || results.length > 0) {
			var newHTML = '';
			var searchtext = document.getElementById('str' + strCurrentElement);
			var isDropDown = acroot.className.startsWith('xdDropDown');

			if (isDropDown)
				strCompareString = '';
			
			var matchLength = strCompareString.length;
			var matchStart = 0;
			var tempMatch = '';
			strCompareString = strCompareString.toLowerCase();

			var ac = document.getElementById('ac' + strCurrentElement);

			resultsvisible = true;

			if (isCalendar) {
				var datCalendar = parseDate(document.getElementById('str' + strCurrentElement).value.split(' ')[0]);
				if (!datCalendar) {
					datCalendar = new Date();
				}
			}
			else {
				for (i=0;i<results.length;i++) {
					tempMatch = results[i].toLowerCase();
					matchStart = tempMatch.indexOf(strCompareString);
					tempMatch = results[i].substring(0, matchStart) + '<b>' + results[i].substring(matchStart, matchStart + matchLength) + '</b>' + results[i].substring(matchStart + matchLength, results[i].length);
					newHTML += '<div id="' + strCurrentElement + 'acresult' + i + '" onmousedown="userselected=true;selectItem(' + i + ');" class="dropdownItem" onmouseout="noblur=false;" onmouseexit="noblur=false;" onmouseover="highlight(' + i + ');">';
					newHTML += tempMatch + '</div>\r\n';
				}
			}

			if (resultsvisible) {
				var pos = findPos(searchtext);
				acroot.style.left = pos[0];
				acroot.style.top = pos[1] + searchtext.offsetHeight;

				if (isDropDown || isCalendar)
					acroot.style.width = searchtext.offsetWidth + 20;
				else
					acroot.style.width = searchtext.offsetWidth;

				if (!isCalendar) {
					acroot.style.overflow = 'auto';
					acroot.style.height = 100;
				}
				else {
					acroot.style.overflow = 'hidden';
					acroot.style.height = 160;
					newHTML = renderCalendar(datCalendar);
				}

				acroot.onmousedown = function(e){noblur=true;cancelEvent(e);};
				acroot.onclick = 'noblur=true;'

				acroot.style.display = 'block';
				ac.innerHTML = newHTML;
				ac.zIndex = 0;
			}
			else {
				clearResults();
			}
		}
		else {
			clearResults();
		}
	}

	processing = false;
}

function setDateValue(strValue, blnHide) {
	userselected = true;
	noblur = false;

	var objElement = document.getElementById('str' + strCurrentElement);
	var strTime = objElement.value;

	if (strTime.split(' ').length > 1) {
		strValue += ' ' + strTime.split(' ')[1];
	}

	objElement.value = strValue;

	if (blnHide) {
		hideResults();
		initAC('');
	}
}

function daysInMonth(intMonth, intYear) {
	var intDIM = 0;
	
	if (intYear < 1900) {
		intYear += 1900;
	}

	datNext = new Date(intMonth + '/1/' + intYear);
	datNext.setMonth(datNext.getMonth() + 1);
	datNext.setDate(-1);
	intDIM = datNext.getDate() + 1;

	return intDIM;
}

function daysInPrevMonth(datIn) {
	var datTemp = new Date(datIn);
	datTemp.setDate(1);
	datTemp.setDate(-1);
	return datTemp.getDate() + 1;
}

function renderCalendar(datCurrent) {
	currentsearch = datCurrent;

	noblur = true;

	var i;
	var arrMonths = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
	var arrDays = ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT'];
	var strHTML = '';
	
	var intMonth = datCurrent.getMonth();
	var intDay = datCurrent.getDate();
	var intYear = datCurrent.getYear();

	if (intYear < 1900) {
		intYear += 1900;
	}

	var datFDOM = new Date(datCurrent);
	datFDOM.setDate(1);
	var intDay1 = datFDOM.getDay() - 1;

	var intDIM = daysInMonth(intMonth + 1, intYear);

	strHTML = '<table width="100%" height="100%" border=0 style="font-size:8pt;">';
	strHTML += '<tr height="20"><td align="center" colspan=7>';

	strHTML += '<table width="100%" cellpadding=0 cellspacing=0 background="/images/gradient.gif">';
	strHTML += '<tr height="18" valign="middle">';
	strHTML += '<td align="right"><img src="/images/prev_button.gif" style="cursor:pointer;border:0;" onmousedown="noblur=true;" onmouseup="noblur=false;" onclick="selectPreviousMonth();"></td>';
	strHTML += '<td align="center" width="150" style="font-size:8pt;">' + arrMonths[intMonth] + ' ' + intYear + '</td>';
	strHTML += '<td align="left"><img src="/images/next_button.gif" style="cursor:pointer;border:0;" onmousedown="noblur=true;" onmouseup="noblur=false;" onclick="noblur=true;selectNextMonth();"></td>';
	strHTML += '</tr></table>';

	strHTML += '</td></tr>';
	strHTML += '<tr height="20px" bgcolor="' + acColor +'">';
	for (i = 0; i < arrDays.length; i++) {
		strHTML += '<td align=center width="14%"><font style="font-size:8pt;color:#ffffff;">' + arrDays[i] + '</font></td>';
	}
	strHTML += '</tr>';
	for (i = 0; i <= (intDIM + intDay1); i++) {
		if (i % 7 == 0) {
			if (i > 1) {
				strHTML += '</tr>';
			}
			strHTML += '<tr>';
		}
		if (i > intDay1) {
			strHTML += '<td align=center onmouseout="this.style.backgroundColor=\'' + ((i - intDay1 == intDay) ? acColor : '#ffffff') + '\';this.style.color=\'' + ((i - intDay1 == intDay) ? "#ffffff" : '#000000') + '\';" onmouseover="this.style.backgroundColor=\'' + acSelectColor + '\';this.style.color=\'#ffffff\';" style="cursor:pointer;' + ((i - intDay1 == intDay) ? 'background-color:' + acColor + ';color:#ffffff;' : '') + '" onclick="setDateValue(\'' + (intMonth + 1) + '/' + (i - intDay1) + '/' + intYear + '\', true)">';
			strHTML += (i - intDay1);
		}
		else {
			strHTML += '<td>';
		}		
		strHTML += '</td>';
	}
	strHTML += '</tr>';
	strHTML += '</table>';

	return strHTML;
}

function selectPreviousMonth() {
	userselected = true;
	var intDate = currentsearch.getDate();
	var intDIPM = daysInMonth(currentsearch.getMonth(), currentsearch.getYear());
	var intDICM = daysInMonth(currentsearch.getMonth() + 1, currentsearch.getYear());
	select(-1 * (intDate > intDIPM ? intDate : intDIPM));
}

function selectNextMonth() {
	userselected = true;
	var intDate = currentsearch.getDate();
	var intDICM = daysInMonth(currentsearch.getMonth() + 1, currentsearch.getYear());
	var intDINM = daysInMonth(currentsearch.getMonth() + 2, currentsearch.getYear());
	select(intDate > intDINM ? intDINM : intDICM);
}

function validateData(e) {
	var keynum;
	var handled = false;
	var isCalendar = (iscalendar(acrootName()));

	if(window.event)
		keynum = e.keyCode;
	else if(e.which)
		keynum = e.which;

	// Escape
	if (keynum == 27) {
		noblur = false;
		userselected = false;
		hideResults(strCurrentElement);
		handled = true;
	}
	// Backspace
	else if (keynum == 8) {
		userselected = false;
		reloadData(e);
	}
	// PageUp
	else if (keynum == 33 && isCalendar) {
	    if (resultsvisible) {
    	    selectPreviousMonth();
	    	handled = true;
	    }
	}
	// PageDown
	else if (keynum == 34 && isCalendar) {
	    if (resultsvisible) {
    	    selectNextMonth();
	    	handled = true;
	    }
	}
	// Right Arrow
	else if (keynum == 39 && isCalendar) {
	    if (resultsvisible) {
    		userselected = true;
	    	select(1);
   		    handled = true;
        }
	}
	// Left Arrow
	else if (keynum == 37 && isCalendar) {
	    if (resultsvisible) {
		    userselected = true;
		    select(-1);
		    handled = true;
        }
	}
	// Up Arrow
	else if (keynum == 38) {
	    if (resultsvisible) {
		    userselected = true;
		    select(isCalendar ? -7 : -1);
		    handled = true;
        }
	}
	// Down arrow
	else if (keynum == 40) {
	    if (resultsvisible) {
		    userselected = true;
		    select(isCalendar ? 7 : 1);
		}
		forceSearch(strCurrentElement);
        handled = true;
	}
	// Enter
	else if ((keynum == 13) && ((selected >= 0) || (isCalendar && resultsvisible))) {
		cancelEvent(e);
		if (isCalendar) {
			setDateValue(shortDate(currentsearch), true);
			noblur = false;
		}
		else {
			selectItem(selected);
		}
		handled = true;
	}
	else {
		noblur = false;
		userselected = false;
	}

	if (handled) {
		if(window.event)
			window.event.keyCode = 0;

		return false;
	}
}

function reloadData(e) {
	var keynum;
	
	if (e) {
		if(window.event)
			keynum = e.keyCode;
		else if(e.which)
			keynum = e.which;
	}

	if ((keynum == null) || (keynum == 27)){
		if(window.event)
			window.event.keyCode = 0;

		return true;
	}
	else if ((keynum == 13) && ((selected >= 0) || iscalendar(acrootName()))) {
		if(window.event)
			window.event.keyCode = 0;

		cancelEvent(e);
		return true;
	}
	else {
		pending = true;
		selected = -1;
		processRequest();
	}
}

function debugClear() {
	var debugwin = document.getElementById('acdebugwin');
	
	if (debugwin) {
		debugwin.innerHTML = '';
	}
}

function debug(strMessage) {
	strMessage += '\r\n';
	
	var debugwin = document.getElementById('acdebugwin');
	
	if (!debugwin) {
		var body = document.getElementsByTagName('body')[0];
		debugwin = document.createElement('textarea');
		debugwin.id = 'acdebugwin';
		debugwin.style.width = 400;
		debugwin.style.height = 250;
		var button = document.createElement('input');

		button.type = 'button'
		button.value = 'Clear';
		button.onclick = function () { debugClear(); };

		body.appendChild(debugwin);
		body.appendChild(button);
	}
	
	debugwin.innerHTML += strMessage;
}

function highlight(index) {
	noblur = true;

	if (selected >= 0) {
		unselect(selected);
	}

	selected = index;

	if ((selected >= 0) && (selected < results.length)) {
		var divX = document.getElementById(strCurrentElement + 'acresult' + selected);

		if (divX) {
			divX.style.backgroundColor = acSelectColor;
			divX.style.color = '#ffffff';

			ensureVisible(divX);
		}
	}
}

function ensureVisible(divItem) {
	var acroot = document.getElementById(acrootName());
	var acTop = acroot.offsetTop;
	var acHeight = acroot.offsetHeight;
	var acRelTop = acroot.scrollTop;
	var acRelBottom = acroot.scrollTop + acHeight;

	var divTop = divItem.offsetTop;
	var divHeight = divItem.offsetHeight;
	var divBottom = divTop + divHeight;

	if (divTop < acRelTop)
		acroot.scrollTop = divTop;
	else if (divBottom > acRelBottom)
		acroot.scrollTop = divTop - (acHeight - divHeight) + 2;
}

function shortDate(datIn) {
	var intYear = datIn.getYear();
	
	if (intYear <= 1900) {
		intYear += 1900;
	}

	return (datIn.getMonth() + 1) + '/' + datIn.getDate() + '/' + intYear;
}

function select(direction) {
	if (iscalendar(acrootName())) {
	    var datTemp = new Date(currentsearch);

	    datTemp.setDate(datTemp.getDate() + direction);
	    document.getElementById('ac' + strCurrentElement).innerHTML = renderCalendar(datTemp);
	    setDateValue(shortDate(currentsearch), false);
	}
	else {
		var next = selected + direction;

		if (next < 0)
			next = 0;
		else if (next >= results.length)
			next = results.length - 1;
		
		if (selected >= 0)
			unselect(selected);

		highlight(next);
	}
}

function unselect(index) {
	if ((index >= 0) && (index < results.length)) {
		var divX = document.getElementById(strCurrentElement + 'acresult' + index);
		divX.style.backgroundColor = '#ffffff';
		divX.style.color = acColor;
	}
}
			
function processRequest() {
	if ((!pending) && (!processing) && (strCurrentElement)) {
		current = document.getElementById('str' + strCurrentElement).value.trim().toLowerCase();

		if ((!submitted) && (currentsearch != current)) {

			if (current) {
				processing = true;

				if (current.length > 0) {
					fetchResults(strCurrentElement, escape(current));
				}
				else {
					processing = false;
					pending = false;
					userselected = false;
					clearResults();
				}
			}
			else {
				userselected = false;
				clearResults();
			}
		}
	}
	else {
		setTimeout("processRequest()", delay);
		pending = false;
	}	
}

function fetchResults(strElement, search) {
	strCurrentElement = strElement;

	var url = 'http://' + window.location.hostname + '/autocomplete.asp?' + strCurrentElement + '=' + search;
	var head = document.getElementsByTagName('head')[0];
	var scriptTag = document.getElementById('ac' + strCurrentElement + 'Script');

	if (scriptTag)
		head.removeChild(scriptTag);
								
	script = document.createElement('script');
	script.src = url;
	script.type = 'text/javascript';
	script.id = 'ac' + strCurrentElement + 'Script';
	head.appendChild(script);
}
			
function hideResults(strElement) {
	if ((!noblur) && (strElement)) {
		selected = -1;
		resultsvisible = false;
		var acroot = document.getElementById('ac' + strElement + 'root');
		acroot.style.display = 'none'
		if (acroot.className.startsWith('xdDropDown') || acroot.className == 'xdCalendar') {
			dropDownImage('off');
		}
	}
	
	noblur=false;
}
			
function submitForm() {
	if (!submitted) {
		if (strCurrentElement) {
			submitted = true;
			if (userselected) {
				document.getElementById('str' + strCurrentElement).value = currentsearch;
			}

			hideResults();
		}

		initAC('');

		submitted = false;
		return true;
	}

	return false;
}

function clearResults() {
	hideResults(strCurrentElement);
	currentsearch = '';
	results = new Array();
	resultIDs = new Array();
}

function forceSearch(strElement) {
	if (!resultsvisible) {
		initAC(strElement);

        if (iscalendar(acrootName())) {
            showCalendar(strCurrentElement);
        }
        else {
		    if (results.length > 0) {
			    processData(strCurrentElement, document.getElementById('str' + strCurrentElement).value);
		    }
		    else {
			    var searchtext = document.getElementById('str' + strCurrentElement);
			    if (searchtext) {
				    currentsearch = '';
				    processRequest();
			    }
		    }
        }
	}
}

function dropDownImage(strState) {
	if (strCurrentElement)
		document.getElementById('btn' + strCurrentElement + 'Off').src = window.location.protocol + '//' + window.location.hostname + ':' + window.location.port + '/images/dropdown_button_grey_' + strState + '_20_24.gif';
}

function showCalendar(strElement) {
	userselected = false;
	selected = -1;

	initAC(strElement);

	if (resultsvisible) {
		clearResults();
	}
	else {
		dropDownImage('on');
		processData(strCurrentElement, '');
	}
}

function dropDown(strElement, arrData, arrIDs) {
	userselected = false;
	selected = -1;

	initAC(strElement);

	if (resultsvisible) {
		clearResults();
	}
	else {
		results = arrData;
		resultIDs = arrIDs;
		dropDownImage('on');
		processData(strCurrentElement, '');
	}
}
