/*
the valiables and functions used to creat suggestion list and the proper actions of keyboard and mouse events. 
*/
var queryField;
var lookupURL;
var divName;
var ifName;
var lastVal = "";
var val = ""
var xmlHttp;
var cache = new Object();
var searching = false;
var globalDiv;
var divFormatted = false;
var DIV_BG_COLOR = "#ffffff";
var DIV_HIGHLIGHT_COLOR = "#cccccc";
var typeField;
var type;

/*
+--------------------------------------------------------------------------+
| Fn name:     InitQueryCode                                               |
+--------------------------------------------------------------------------+
| Purpose:     Initiate the varialbes and cache                            |
+--------------------------------------------------------------------------+
| Inputs:      queryFieldName--query input field name								|
|					typeFieldName--search type field id									|
|					lookupURLPrefix--result page URL							         |
+--------------------------------------------------------------------------+
| Returns:     nothing                                                     |
+--------------------------------------------------------------------------+
| Notes:       															               |
+--------------------------------------------------------------------------+
*/
function InitQueryCode (queryFieldName, typeFieldName, lookupURLPrefix, hiddenDivName)
{
  queryField = document.getElementsByName(queryFieldName).item(0);
  queryField.onblur = hideDiv;
  queryField.onkeydown = keypressHandler;
  type = document.getElementById(typeFieldName).value;
  queryField.autocomplete = "off";
  
  lookupURL = lookupURLPrefix;
  if (hiddenDivName)
    divName = hiddenDivName;
  else
    divName = "querydiv";
  ifName = "queryiframe";
  //clear the old restored result
  clearCache();
  // add a blank value to the cache (so we don't try to do a lookup when the
  // field is empty) and start checking for changes to the input field
  addToCache("", new Array(), new Array());
  setTimeout("mainLoop()", 100);
}


/*
+--------------------------------------------------------------------------+
| Fn name:     addToCache		                                             |
+--------------------------------------------------------------------------+
| Purpose:     restore the search result into cache                        |
+--------------------------------------------------------------------------+
| Inputs:      queryString							                              |
|              resultArray1, resultArray2									         |
+--------------------------------------------------------------------------+
| Returns:     nothing                                                     |
+--------------------------------------------------------------------------+
*/
function addToCache (queryString, resultArray1, resultArray2)
{
  cache[queryString] = new Array(resultArray1, resultArray2);
}

/*
+--------------------------------------------------------------------------+
| Fn name:     clearCache()	                                             |
+--------------------------------------------------------------------------+
| Purpose:     clear the restored result                                   |
+--------------------------------------------------------------------------+
| Inputs:      none																         |
+--------------------------------------------------------------------------+
| Returns:     nothing                                                     |
+--------------------------------------------------------------------------+
*/
function clearCache()
{
	cache = new Array();
}

/*
+--------------------------------------------------------------------------+
| Fn name:     mainLoop			                                             |
+--------------------------------------------------------------------------+
| Purpose:     This is the function that monitors the queryField, 			|
|					and calls the lookup functions when the queryField value		| 
|					changes.             							                  |
+--------------------------------------------------------------------------+
| Inputs:      nothing															         |
+--------------------------------------------------------------------------+
| Returns:     nothing                                                     |
+--------------------------------------------------------------------------+
*/
mainLoop = function() {
  
  val = escape(queryField.value);
  if (lastVal != val && searching == false){
    var cacheResult = cache[val];
    if (cacheResult)
      showQueryDiv(val, cacheResult[0], cacheResult[1]);
    else
      doRemoteQuery(val);
    lastVal = val;
  }
  
  setTimeout("mainLoop()", 100);
  return true;
}
;


/*
+--------------------------------------------------------------------------+
| Fn name:     getDiv			                                             |
+--------------------------------------------------------------------------+
| Purpose:     Get the <DIV> we're using to display the lookup results, 	|
|					and create the <DIV> if it doesn't already exist.           |
+--------------------------------------------------------------------------+
| Inputs:      divID																         |
+--------------------------------------------------------------------------+
| Returns:     globalDiv                                                   |
+--------------------------------------------------------------------------+
*/
function getDiv (divID)
{
  if (!globalDiv) {
    // if the div doesn't exist on the page already, create it
    if (!document.getElementById(divID)) {
      var newNode = document.createElement("div");
      newNode.setAttribute("id", divID);
      document.body.appendChild(newNode);
    }
    
    // set the globalDiv reference
    globalDiv = document.getElementById(divID);
    
    // figure out where the top corner of the div should be, based on the
    // bottom left corner of the input field
    var x = queryField.offsetLeft;
    var y = queryField.offsetTop + queryField.offsetHeight;
    var parent = queryField;
    while (parent.offsetParent) {
      parent = parent.offsetParent;
      x += parent.offsetLeft;
      y += parent.offsetTop;
    }
    
    // add some formatting to the div, if we haven't already
    if (!divFormatted) {
      globalDiv.style.backgroundColor = DIV_BG_COLOR;
      globalDiv.style.fontFamily = "Verdana, Geneva, Arial, Helvetica, sans-serif";
      globalDiv.style.padding = "4px";
      globalDiv.style.border = "1px solid black";
      globalDiv.style.fontSize = "10px";
		globalDiv.style.textAlign = "left";
  
      globalDiv.style.position = "absolute";
      globalDiv.style.left = x + "px";
      globalDiv.style.top = y + "px";
      globalDiv.style.visibility = "hidden";
      globalDiv.style.zIndex = 10000;
      
      divFormatted = true;
    }
  }
  
  return globalDiv;
}


/*
+--------------------------------------------------------------------------+
| Fn name:     showQueryDiv                                                |
+--------------------------------------------------------------------------+
| Purpose:     This is the function that should be returned by the			|
|					XMLHTTP call. It will format and display the lookup results.|
+--------------------------------------------------------------------------+
| Inputs:      queryString, resultArray1, resultArray2				         |
+--------------------------------------------------------------------------+
| Returns:     nothing                                                     |
+--------------------------------------------------------------------------+
| Notes:       onmousedown -- subForm								               |
|					onmouseover -- mouseOver												|
|					onmouseout -- unhightResult											|
+--------------------------------------------------------------------------+
*/
function showQueryDiv (queryString, resultArray1, resultArray2)
{
	var div = getDiv(divName);
	
	// remove any results that are already there
	while (div.childNodes.length > 0)
	 div.removeChild(div.childNodes[0]);
	
	// add an entry for each of the results in the resultArray
	for (var i = 0; i < resultArray1.length; i++)
	{
		// each result will be contained within its own div
		var result = document.createElement("div");
		result.style.cursor = "pointer";
		result.style.borderBottom = "1px solid #777777";
		result.style.padding = "2px 0px 2px 0px";
		_unhighlightResult(result);
		
		result.onmousedown = subForm;   
		result.onmouseover = mouseOver;
		result.onmouseout = unhighlightResult;
		
		
		// add span with data of resultArray1
		var result1 = document.createElement("span");
		result1.className = "result1";
		result1.style.textAlign = "left";
		result1.style.fontWeight = "bold";
		result1.innerHTML = resultArray1[i];
		
		// add span with data of resultArray2
		var result2 = document.createElement("span");
		result2.className = "result2";
		result2.style.textAlign = "right";
		result2.style.paddingLeft = "5px";
		result2.innerHTML = resultArray2[i];
		
		// add spans to div
		result.appendChild(result1);
		result.appendChild(result2);
		// add new sub div to the div
		div.appendChild(result);
	}
  
	// if this resultset isn't already in our cache, add it
	var isCached = cache[queryString];
	if (!isCached)
		addToCache(queryString, resultArray1, resultArray2);
	
	// display the div if we had at least one result
	showDiv(resultArray1.length > 0);
}


/*
+--------------------------------------------------------------------------+
| Fn name:     selectResult, _selectResult                                 |
+--------------------------------------------------------------------------+
| Purpose:     This is called whenever the user clicks one of the lookup 	|
|					results. It puts the value of the result in the queryField 	|
|					and hides the lookup div.												|
+--------------------------------------------------------------------------+
| Inputs:      																	         |
+--------------------------------------------------------------------------+
| Returns:     nothing                                                     |
+--------------------------------------------------------------------------+
*/
function selectResult()
{
  _selectResult(this);
}

function _selectResult(item)
{
  var spans = item.getElementsByTagName("span");
  if (spans) {
    for (var i = 0; i < spans.length; i++) {
      if (spans[i].className == "result1") {
        var str = spans[i].innerHTML;
		  // if result string contains '&amp;', replace it with '&'
		  str = str.replace(/&amp;/,"&");
        queryField.value = str;
		  lastVal = val = escape(queryField.value);
        searching = false;
        mainLoop();
        queryField.focus();
      }
    }
  }
}


/*
+--------------------------------------------------------------------------+
| Fn name:     highlightResult, _highlightResult                           |
+--------------------------------------------------------------------------+
| Purpose:     change div background color to be highlighted					|
+--------------------------------------------------------------------------+
| Inputs:      																	         |
+--------------------------------------------------------------------------+
| Returns:                                           				            |
+--------------------------------------------------------------------------+
*/
function highlightResult()
{
  _highlightResult(this);
}

function _highlightResult(item)
{
  item.style.backgroundColor = DIV_HIGHLIGHT_COLOR;
}


/*
+--------------------------------------------------------------------------+
| Fn name:     unhighlightResult, _unhighlightResult                       |
+--------------------------------------------------------------------------+
| Purpose:     change div background color to be unhighlighted					|
+--------------------------------------------------------------------------+
| Inputs:      																	         |
+--------------------------------------------------------------------------+
| Returns:                                           				            |
+--------------------------------------------------------------------------+
*/
function unhighlightResult()
{
  _unhighlightResult(this);
}

function _unhighlightResult(item)
{
  item.style.backgroundColor = DIV_BG_COLOR;
}

/*
+--------------------------------------------------------------------------+
| Fn name:     subForm, _subForm								                     |
+--------------------------------------------------------------------------+
| Purpose:     submit the search form													|
+--------------------------------------------------------------------------+
| Inputs:      																	         |
+--------------------------------------------------------------------------+
| Returns:                                           				            |
+--------------------------------------------------------------------------+
*/
function subForm()
{
	_subForm(this);
}

function _subForm(item)
{
  document.getElementById('search').submit();
}

/*
+--------------------------------------------------------------------------+
| Fn name:     mouseOver, _mouseOver					                        |
+--------------------------------------------------------------------------+
| Purpose:     highlightResult and selectResult										|
+--------------------------------------------------------------------------+
| Inputs:      																	         |
+--------------------------------------------------------------------------+
| Returns:                                           				            |
+--------------------------------------------------------------------------+
*/
function mouseOver()
{
	_mouseOver(this);	
}

function _mouseOver(item)
{
	_highlightResult(item);
	_selectResult(item);
}

/*
+--------------------------------------------------------------------------+
| Fn name:     showDiv											                     |
+--------------------------------------------------------------------------+
| Purpose:     show or hide the lookup div											|
+--------------------------------------------------------------------------+
| Inputs:      show 																	      |
+--------------------------------------------------------------------------+
| Returns:     show == true, show the div												|
|					show == false, hide the div											|
+--------------------------------------------------------------------------+
*/
function showDiv (show)
{
  var div = getDiv(divName);
  if (show)
    div.style.visibility = "visible";
  else
    div.style.visibility = "hidden";

  adjustiFrame();
}

/*
+--------------------------------------------------------------------------+
| Fn name:     hideDiv											                     |
+--------------------------------------------------------------------------+
| Purpose:     hide the lookup div when initializing								|
+--------------------------------------------------------------------------+
| Inputs:       																		      |
+--------------------------------------------------------------------------+
| Returns:     																				|
+--------------------------------------------------------------------------+
*/
function hideDiv ()
{
  showDiv(false);
}

/*
+--------------------------------------------------------------------------+
| Fn name:     adjustiFrame									                     |
+--------------------------------------------------------------------------+
| Purpose:     Use an "iFrame shim" to deal with problems where the lookup |
| 					div shows up behind selection list elements, if they're  	|
|					below the queryField.													|
+--------------------------------------------------------------------------+
| Inputs:       																	      	|
+--------------------------------------------------------------------------+
| Notes:     The problem and solution are described at:							|
|        http://dotnetjunkies.com/WebLog/jking/archive/2003/07/21/488.aspx |
|        http://dotnetjunkies.com/WebLog/jking/archive/2003/10/30/2975.aspx|
+--------------------------------------------------------------------------+
*/
function adjustiFrame()
{
  if (!document.getElementById(ifName)) {
    var newNode = document.createElement("iFrame");
    newNode.setAttribute("id", ifName);
    newNode.setAttribute("src", "javascript:false;");
    newNode.setAttribute("scrolling", "no");
    newNode.setAttribute("frameborder", "0");
    document.body.appendChild(newNode);
  }
  
  iFrameDiv = document.getElementById(ifName);
  var div = getDiv(divName);
  
  try {
    iFrameDiv.style.position = "absolute";
    iFrameDiv.style.width = div.offsetWidth;
    iFrameDiv.style.height = div.offsetHeight;
    iFrameDiv.style.top = div.style.top;
    iFrameDiv.style.left = div.style.left;
    iFrameDiv.style.zIndex = div.style.zIndex - 1;
    iFrameDiv.style.visibility = div.style.visibility;
  } catch(e) {
  }
}

/*
+-----------------------------------------------------------------+
| Fn name:    GetXmlHttpObject                                    |
+-----------------------------------------------------------------+
| Purpose:    check browser type, alert when the browser          |
|             doesn't support the method                          |
+-----------------------------------------------------------------+
| Inputs:     handler                                             |
+-----------------------------------------------------------------+
| Result:    if browser supports, return objXmlHttp               |
|            Or return nothing                                    |
+-----------------------------------------------------------------+
*/
function getXMLHTTP(){
  var A = null;
  
  try{
    A = new ActiveXObject("Msxml2.XMLHTTP");
  }catch(e){
    try{
      A = new ActiveXObject("Microsoft.XMLHTTP");
    } catch(oc){
      A = null;
    }
  }
  
  if(!A && typeof XMLHttpRequest != "undefined") {
    A = new XMLHttpRequest();
  }
  
  return A;
}

/*
+--------------------------------------------------------------------------+
| Fn name:     doRemoteQuery									                     |
+--------------------------------------------------------------------------+
| Purpose:     send the search query and get result by xmlHttp.responseText|
+--------------------------------------------------------------------------+
| Inputs:      queryString															      |
+--------------------------------------------------------------------------+
| Returns:     showQueryDiv('queryString', resultArray1, resultArray2)		|
+--------------------------------------------------------------------------+
*/
function doRemoteQuery (queryString)
{
  
	query_con = queryString + '&type=' + type;
	searching = true;
	if(xmlHttp && xmlHttp.readyState != 0) {
		xmlHttp.abort()
	}
	
	xmlHttp=getXMLHTTP();
	if(xmlHttp){
		xmlHttp.open("GET", lookupURL + query_con, true);
		
		// xmlHttp.onreadystatechange event cause eval(xmlHttp.responseText)
		xmlHttp.onreadystatechange = function() {
			if (xmlHttp.readyState == 4 && xmlHttp.responseText && searching) {
			eval(xmlHttp.responseText);
			searching = false;
			}
		}
		;
	
		xmlHttp.send(null);
	}
}

/*
+--------------------------------------------------------------------------+
| Fn name:     keypressHandler								                     |
+--------------------------------------------------------------------------+
| Purpose:     handle the keypress event												|
+--------------------------------------------------------------------------+
| Inputs:      evt -- key pressed												      |
+--------------------------------------------------------------------------+
| Returns:     keyup	-- highlightResult, selectResult								|
|					keydown -- highlightResult, selectResult							|
|					keyenter -- no action(submit form)									|
+--------------------------------------------------------------------------+
*/
function keypressHandler (evt)
{
  // don't do anything if the div is hidden
  var div = getDiv(divName);
  if (div.style.visibility == "hidden")
    return true;
  
  // make sure we have a valid event variable
  if(!evt && window.event) {
    evt = window.event;
  }
  var key = evt.keyCode;
  
  
  // if this key isn't one of the ones we care about, just return
  var KEYUP = 38;
  var KEYDOWN = 40;
  var KEYENTER = 13;
  var KEYTAB = 9;
  
  if ((key != KEYUP) && (key != KEYDOWN) && (key != KEYENTER) && (key != KEYTAB))
    return true;
  
  // get the span that's currently selected, and perform an appropriate action
  var selNum = getSelectedSpanNum(div);
  var selSpan = setSelectedSpan(div, selNum);
  

	if (key == KEYUP)
	selSpan = setSelectedSpan(div, selNum - 1);
	if (key == KEYDOWN)
	selSpan = setSelectedSpan(div, selNum + 1);
	if (selSpan)
	{
		_highlightResult(selSpan);
		_selectResult(selSpan);
		 evt.cancelBubble=true;
		 //return false;
	}
  	if ((key == KEYENTER) || (key == KEYTAB)) {
		//alert(key);
		if (selSpan)
		{
			/*_highlightResult(selSpan);
			_selectResult(selSpan);
			 evt.cancelBubble=true;*/
			 //document.getElementById('search').submit();
			 //return false;
		}
	}
  showDiv(true);
  return true;
}

/*
+--------------------------------------------------------------------------+
| Fn name:     getSelectedSpanNum							                     |
+--------------------------------------------------------------------------+
| Purpose:     Get the number of the result that's currently 					|
|					selected/highlighted   													|
+--------------------------------------------------------------------------+
| Inputs:      div																	      |
+--------------------------------------------------------------------------+
| Returns:     if span exist, return span number									|
|					else, return -1															|
+--------------------------------------------------------------------------+
| Notes:			the first result is 0, the second is 1, etc.						|
+--------------------------------------------------------------------------+
*/
function getSelectedSpanNum (div)
{
  var count = -1;
  var spans = div.getElementsByTagName("div");
  if (spans) {
    for (var i = 0; i < spans.length; i++) {
      count++;
      if (spans[i].style.backgroundColor != div.style.backgroundColor)
        return count;
    }
  }
  
  return -1;
}

/*
+--------------------------------------------------------------------------+
| Fn name:     setSelectedSpan								                     |
+--------------------------------------------------------------------------+
| Purpose:     select and highlight the result at the given position			|
+--------------------------------------------------------------------------+
| Inputs:      div, spanNum														      |
+--------------------------------------------------------------------------+
| Returns:     span																			|
+--------------------------------------------------------------------------+
*/
function setSelectedSpan (div, spanNum)
{
	var count = -1;
	var thisSpan;
	var spans = div.getElementsByTagName("div");
	if (spans) {
		for (var i = 0; i < spans.length; i++) {
			if (++count == spanNum) {
				_highlightResult(spans[i]);
				thisSpan = spans[i];
			} 
			else {
				_unhighlightResult(spans[i]);
			}
		}
	}
	return thisSpan;
}