//
// mgbox.js
//
// All mgBox related functions.
// There should not be any need to modify this file,
// customisation can be achieved through various
// "hook" functions.
//
// Feel free to use as you please, but please retain this
// copyright notice.
//
// 2005-02-10 MGrill Version 1.00
// 2005-02-17 MGrill added onLoad hook
//
// see http://www.dcs.lancs.ac.uk/~grill/mgbox/
//

// This is the mgBox class declaration.
// The one and only global mgBox object will be called "theMgBox",
// this object will be instantiated further down.

// number of lines in div
var line_count = 0;
var intScroll;
var is_focused = false;
var plcidfpvalue;
var gonow = false;

function mgBox() {
  if(typeof MGBOX_ASSIST_CGI_TEMPLATE == 'undefined') {
    //this.ASSIST_CGI_TEMPLATE = "cgi/assist_@.php?s=";
    this.ASSIST_CGI_TEMPLATE = "/qs_@.php?rnf=" + Math.random() + "&s=";
    //this.ASSIST_CGI_TEMPLATE = "/search_rest.asp?rnd=" + pRnd + "&campusid=" + pCampusId + "&s=";
  } else {
    this.ASSIST_CGI_TEMPLATE = MGBOX_ASSIST_CGI_TEMPLATE;
  }
  this.IDLETIME = 1000;  // after this duration we start processing the user input!
  this.timerid=null;    // will hold the timer that waits until the user does nothing for IDLETIME ms.
  this.oldcontents="";  // the previous contents of the text box
  this.textboxid="";    // our textbox - will get updated in call to onFocus() later on...
  this.textfieldhandle=null;  // handle to our textbox, see above
  this.httprequest = createXMLHttpRequest();  // the one and only active httprequest object...
  this.httprequestactive = false;
  this.highlightedline = null;
  this.html_text_array = Array(); // results from database 
  this.raw_text_array = Array();  // queries go into
  this.id_array = Array();        // these three arrays
  this.isOpenAndFilled = false;
}

// gets called whenever a keydown event happens
function MgOnKeyDown(event) {
  // we process the key. if it is a "normal" character, we only react after
  // a specified timeout (see below).
  // "event" only gets set if the handler was assigned from within
  // javascript, not in the html code. this is done in onFocus().
  if(!event) {
    event = window.event;
  }
  var hBox = getElem("id","mgBox");
  
  ///////////////// DOWN //////////////////
  if(event.keyCode==40) {  // "down"
    if(!theMgBox.isOpenAndFilled) {
      theMgBox.timeoutReached(theMgBox.textboxid);
    } else {
      if(theMgBox.highlightedline!=null) {
        // change currently hightlighted line back to normal
        hBox.childNodes[0].childNodes[theMgBox.highlightedline].className="";
        // advance selection by one
        //theMgBox.highlightedline = (theMgBox.highlightedline+1) % theMgBox.html_text_array.length;
        //no loop 
        if(theMgBox.highlightedline < theMgBox.html_text_array.length - 1) {
	        theMgBox.highlightedline = theMgBox.highlightedline + 1;
        }
      } else {
        if (theMgBox.html_text_array.length>0) {
          theMgBox.highlightedline = 0;
        }
      }
      // highlight the new line
      hBox.childNodes[0].childNodes[theMgBox.highlightedline].className="mgHighlighted";

      sBox = getElem("id","mgScroll");
      line_count++;
			if (theMgBox.highlightedline == 0) {
      	sBox.scrollTop = 0;
      	line_count = 0;
      } else if (line_count > 9) {
      	sBox.scrollTop = sBox.scrollTop + 24;
//      	alert(sBox.scrollTop);
      	line_count = 9;
      }
    }
    return false;
  }
  
  ///////////////// UP //////////////////
  if(event.keyCode==38) {  // "up"
    if(!theMgBox.isOpenAndFilled) {
      theMgBox.timeoutReached(theMgBox.textboxid);
    } else {
      if(theMgBox.highlightedline!=null) {
        // change currently hightlighted line back to normal
        hBox.childNodes[0].childNodes[theMgBox.highlightedline].className="";
        // advance selection by one (upwards)
        //theMgBox.highlightedline = (theMgBox.highlightedline==0) ? theMgBox.html_text_array.length-1 : theMgBox.highlightedline-1;
        //no loop
        if(theMgBox.highlightedline > 0) {
	        theMgBox.highlightedline = theMgBox.highlightedline - 1;
        }
      } else {
        theMgBox.highlightedline = theMgBox.html_text_array.length-1;
      }
      // highlight the new line
      hBox.childNodes[0].childNodes[theMgBox.highlightedline].className="mgHighlighted";

      sBox = getElem("id","mgScroll");
      line_count--;
      if (theMgBox.highlightedline == theMgBox.html_text_array.length - 1) {            	
      	sBox.scrollTop = (theMgBox.html_text_array.length - 5) * 24;
      	line_count = 9;
      } else if (line_count < 0) {            	
      	sBox.scrollTop = sBox.scrollTop - 24;
      	line_count = 0;
      }
    }
    return false;
  }
  
  ///////////////// ENTER //////////////////
  if(event.keyCode==13) {  // "ENTER"
    //city hack
    if (theMgBox.textboxid == "cityname" && theMgBox.highlightedline == null){
	    theMgBox.highlightedline = 0;
	  }
    if(!theMgBox.isOpenAndFilled) {
      theMgBox.timeoutReached(theMgBox.textboxid);
      //return false;
    } else if(theMgBox.highlightedline != null){
      theMgBox.hideMgBox();
      
      // copy text into edit field
      var hTextbox = getElem("id",theMgBox.textboxid);
      //hTextbox.value = "";
      //hTextbox.value = theMgBox.raw_text_array[theMgBox.highlightedline];
      //theMgBox.oldcontents = theMgBox.raw_text_array[theMgBox.highlightedline];
      
      /*
      // Remember author ID in hidden input field (if it exists)
      var hHiddenIdBox = getElem("id",theMgBox.textboxid+"_id");
      if( hHiddenIdBox != null ) {
        hHiddenIdBox.value = theMgBox.id_array[theMgBox.highlightedline];
      }

      // call hook if present      
      if(typeof mgBox_onEnter_hook == 'function') {
        mgBox_onEnter_hook(theMgBox.textboxid);
      }
      //hTextbox.parentNode.submit();
      */
      //event.returnValue = false;
      location.href = theMgBox.id_array[theMgBox.highlightedline];
    }
    return false;
  }

  if(event.keyCode == 27) {  // "ESCAPE"
	  theMgBox.hideMgBox();
    var hTextbox = getElem("id",theMgBox.textboxid);
    hTextbox.value = "";
  }
}
mgBox.prototype.onKeyDown = MgOnKeyDown;

function MgOnFocus(event) {
  // we store our parent id within the MgBox object, so that later on we
  // can check whether a delayed result does actually belong to the currently
  // active box
  // we also reset some other properties
  
  // first we need to find out the id of our textfield, though:

  if( event == null ) {
    event = window.event;
  }
  var hElement = ( event.srcElement ) ? event.srcElement : event.originalTarget;
  var id=hElement.id;

  //hack for loki!!!!
  if( !id ) {
    id = "cityname";
  }
  
  theMgBox.textboxid = id;
  if( !id ) {
    alert( 'Error: every mgBox needs a unique ID attribute!' );
  }
  theMgBox.httprequestactive = false;
  theMgBox.textfieldhandle = getElem("id",id);
  if (theMgBox.textfieldhandle.value == 'Restaurant Search') {
  	theMgBox.textfieldhandle.value = '';
		theMgBox.textfieldhandle.style.color = '#000';
  }
  theMgBox.oldcontents = theMgBox.textfieldhandle.value;  // old contents = current contents
  

  // we attach the keydown handler
  theMgBox.textfieldhandle.onkeydown = theMgBox.onKeyDown;
  theMgBox.textfieldhandle.onkeyup = theMgBox.onKeyUp;
  theMgBox.textfieldhandle.onblur = theMgBox.onBlur;

  if(!theMgBox.isOpenAndFilled) {
	  theMgBox.timeoutReached(theMgBox.textboxid);
  }
}
mgBox.prototype.onFocus = MgOnFocus;

function MgOnBlur(event) {
  if(!is_focused){
  	theMgBox.hideMgBox();
  }

  /*  
  theMgBox.textfieldhandle.onkeydown = null;
  theMgBox.textfieldhandle.onkeyup = null;
  theMgBox.textfieldhandle.onblur = null;
  
    
  // call hook function if it exists
  if(typeof mgBox_onBlur_hook == 'function') {
    mgBox_onBlur_hook(theMgBox.textboxid);
  }

  // reset some MgBox related properties to make sure it
  // doesn't suddenly pop up!
  theMgBox.textboxid = "";
  theMgBox.oldcontents = "";
  theMgBox.httprequestactive = false;
  theMgBox.handle = null;
  */
}
mgBox.prototype.onBlur = MgOnBlur;

function MgOnKeyUp(event) {
  // we process the results of the previous keypress. 
  // "event" only gets set if the handler was assigned from within
  // javascript, not in the html code. this is done in onFocus().
  if(!event) {
    event = window.event;
  }
  var id=theMgBox.textboxid;
  var mytextbox = getElem("id",id);
  var textfieldcontents = mytextbox.value;
  
  if (textfieldcontents!=theMgBox.oldcontents) {
  
    // execute new query to fill listbox
    theMgBox.oldcontents = textfieldcontents;

    // call hook if present  
    if(typeof mgBox_onContentsChange_hook == 'function') {
      mgBox_onContentsChange_hook(id);
    }
  
    // We also try to parse the entry if a suitable
    // parsing function exists
    var parse_function = "mgBox_parse_"+id.removeTrailingDigitsIfPresent()+"_field";
    if (eval("typeof "+parse_function)=='function') {
      eval(parse_function+"('"+id+"')");
    }
    
    // we reset our timeout timer (search will only spring into action when the user does nothing
    // for IDLETIME ms so that we don't slow down the user experience.
    if (theMgBox.timerid!=null) {
      clearTimeout(theMgBox.timerid);
    }
    theMgBox.timerid = setTimeout("theMgBox.timeoutReached('"+theMgBox.textboxid+"')",theMgBox.IDLETIME);
  } 
}
mgBox.prototype.onKeyUp = MgOnKeyUp;

function MgTimeoutReached(id) {
  
  //restsearch hack
  if (plcidfp = getElem("id","plcidfp")){ 
    plcidfpvalue = getElem("id","plcidfp").value;
    if(isnearby = getElem("id","isnearby")){
    	if(isnearby.checked){
    		plcidfpvalue += getElem("id","plcidfps").value;
    	};
    }
  }  
  
  // user was idle for IDLETIME ms, do some processing!
  this.timerid = null;
  
	// has the focus changed in the meantime?
  if (id!=theMgBox.textboxid) {
    return;
  }

  // we update the listbox if the contents of the text field have changed
  var mytextbox = getElem("id",id);
  var textfieldcontents = mytextbox.value;
  if(textfieldcontents.length > 1) {
    // execute new query to fill listbox
    
    // first, show "updating..." indicator inside mgBox DIV
    var mgBoxDiv = getElem("id","mgBox");
    mgBoxDiv.innerHTML = "searching for '"+textfieldcontents+"'...";
    theMgBox.isOpenAndFilled = false;
    theMgBox.highlightedline = null;  // reset selection
    
    // make sure the box is displayed (this may be the first time!!!)
    theMgBox.showMgBox();

    // cancel any previous http requests that are still active
    if( theMgBox.httprequestactive ) {
      // cancel currently ongoing request
      //this.httprequest.abort(); // see http://www.w3schools.com/dom/dom_http.asp
      // creates empty results, so we simply create a new object instead...
      delete theMgBox.httprequest; // not sure whether we need to delete objects, we do it just in case...
      theMgBox.httprequest = createXMLHttpRequest(); // create a new one...
      theMgBox.httprequestactive = false;
    }
    if( !theMgBox.httprequestactive ) {
      theMgBox.httprequestactive = true;

      // build name of cgi, based on textbox id (less 2-digit suffix if present)
      var cgi_name = theMgBox.ASSIST_CGI_TEMPLATE.replace(/@/, theMgBox.textboxid.removeTrailingDigitsIfPresent());
      //alert(cgi_name+URLEncode(textfieldcontents) + "&plcidfp=" + plcidfpvalue);
      theMgBox.httprequest.open("GET", cgi_name+URLEncode(textfieldcontents) + "&plcidfp=" + plcidfpvalue,true);
      theMgBox.httprequest.onreadystatechange=function() {

// Ready States
//    * 0: UNINITIALIZED open() has not been called yet
//    * 1: LOADING Request not yet made (send() not called)
//    * 2: LOADED Contact established with server and HTTP status code recieved
//    * 3: INTERACTIVE In Mozilla, called multiple times while response is fetched - every 4096 bytes of response
//    * 4: COMPLETED Response complete

        if (theMgBox.httprequest.readyState==4) {
        	// has the focus changed in the meantime?
          if (theMgBox.httprequestactive == false) {
            return;
          }

          //alert(theMgBox.httprequest.readyState.toString() + " - " + theMgBox.httprequest.responseText)
          var mgBoxDiv = getElem("id","mgBox");
          // store result in internal arrays
          var result_array = theMgBox.httprequest.responseText.split("\t");
          //alert(result_array[0]);
          if(result_array[0]!="magic") {
            // error
            //mgBoxDiv.innerHTML = "no magic";
          } else if(result_array.length<3) {
            // only magic, but no results
            
            if (theMgBox.textboxid == "cityname"){
  	          mgBoxDiv.innerHTML = '<ul id="mgScroll"><li id="mgNotListedText">No Matching Results<br/>Try typing first two letters of a city, or zip code</li></ul>';
            }else{
	            //mgBoxDiv.innerHTML = '<ul id="mgScroll"><li id="mgNotListedText">No Matching Results<div class="mgAddress">For best results, try typing 3 letters first.</div></li><li id="mgNotListedLink">Restaurant not listed? <a href="/content/recommend-restaurant.asp">Let Us Know</a></li></ul>';
	            mgBoxDiv.innerHTML = '<ul id="mgScroll"><li id="mgNotListedText">No Matching Results<div class="mgAddress">For best results, try typing 3 letters first.</div></li></ul>';
            }
            
            mgBoxDiv.onmouseover = function() {
	         		is_focused = true;
	         	}
            theMgBox.showMgBox();
          } else {
						// number of lines in div
						line_count = 0;
          	
          	theMgBox.showMgBox();
            delete theMgBox.html_text_array;
            delete theMgBox.raw_text_array;
            delete theMgBox.id_array;
            theMgBox.html_text_array = new Array();
            theMgBox.raw_text_array = new Array();
            theMgBox.id_array = new Array();
            var total_html = '<ul id="mgScroll">';
            // file format is "html \n raw \n id \n [...]"

            for(var i=1; i<result_array.length-1; i+=3) { // ignore line after last \n
              theMgBox.html_text_array.push(result_array[i]);
              theMgBox.raw_text_array.push(result_array[i+1]);
              theMgBox.id_array.push(result_array[i+2]);
              total_html = total_html + '<li>' + result_array[i] + '</li>';
            }
            total_html = total_html + '</ul>'
            /*
            if (result_array.length > 32) {
            	total_html = total_html + '<div id="mgArrows"><div id="mgArrowUp"><!-- --></div><div id="mgArrowDown"><!-- --></div></div>';
            }
            */
            mgBoxDiv.innerHTML = total_html;
            mgBoxDiv.onmouseover = function() {
	         		is_focused = true;
					  	setTimeout('getElem("id","' + id + '").focus(); getElem("id","' + id + '").value = getElem("id","' + id + '").value;', 1);
           	}
            mgBoxDiv.onmouseout = function() {
	         		is_focused = false;
           	}

            /*
            if (result_array.length > 32) {
            	getElem("id","mgScroll").style.height = '800px';

            	getElem("id","mgArrowDown").onmousedown = function() {
                scrollDown();
                intScroll = setInterval("scrollDown()", 100);
            	}
            	getElem("id","mgArrowDown").onmouseup = function() {
	         	  	clearInterval(intScroll);
            	}

            	getElem("id","mgArrowUp").onmousedown = function() {
                scrollUp();
                intScroll = setInterval("scrollUp()", 100);
            	}
            	getElem("id","mgArrowUp").onmouseup = function() {
	         	  	clearInterval(intScroll);
            	}
    
            } else {
            	getElem("id","mgScroll").style.height = '';
            }
            */

            // highlight the first line
//            theMgBox.highlightedline = 0;
//            mgBoxDiv.childNodes[0].childNodes[theMgBox.highlightedline].className="mgHighlighted";

            for (var i = 0; i < mgBoxDiv.childNodes[0].childNodes.length; i++){
            	mgBoxDiv.childNodes[0].childNodes[i].onmouseover = function() {
            		if(theMgBox.highlightedline != null){
//	 		            alert(theMgBox.highlightedline);
	 		            this.parentNode.childNodes[theMgBox.highlightedline].className = "";
	 		          }
            		this.className="mgHighlighted";
            		line_count = line_count - theMgBox.highlightedline;
            		theMgBox.highlightedline = thisindex(this);
            		line_count = line_count + theMgBox.highlightedline;
            	}
            	mgBoxDiv.childNodes[0].childNodes[i].onclick = function() {
					      theMgBox.hideMgBox();
              
					      // copy text into edit field
					      var hTextbox = getElem("id",theMgBox.textboxid);
					      //hTextbox.value = "";
					      //hTextbox.value = theMgBox.raw_text_array[theMgBox.highlightedline];
					      //theMgBox.oldcontents = theMgBox.raw_text_array[theMgBox.highlightedline];
      
					      // Remember author ID in hidden input field (if it exists)
					      /*
					      var hHiddenIdBox = getElem("id",theMgBox.textboxid+"_id");
					      if( hHiddenIdBox != null ) {
				        	hHiddenIdBox.value = theMgBox.id_array[theMgBox.highlightedline];
			      		}
			      		hTextbox.parentNode.submit();
                */

			      		location.href = theMgBox.id_array[theMgBox.highlightedline];

            	}
            }
            theMgBox.isOpenAndFilled = true;
            if (gonow){
	            location.href = theMgBox.id_array[0];
            }
          }
          theMgBox.httprequestactive = false;
        }
      }
      theMgBox.httprequest.send(null);   // this will send the request
    }

    //city hack;
    if (event){
	    if (theMgBox.textboxid == "cityname" && event.keyCode == 13){
	    	gonow = true;
	    }
    }
  } else {
		// otherwise hide the box
		theMgBox.hideMgBox();
  }
}
mgBox.prototype.timeoutReached = MgTimeoutReached;

function MgShowMgBox() {
  box = getElem("id","mgBox","");
  par = this.textfieldhandle;
  pos = findPos(par);
  x = pos[0];
  y = pos[1];
  box.style.top = y + par.offsetHeight + 'px';
  box.style.left = x + 'px';
  box.style.visibility = "visible";
}
mgBox.prototype.showMgBox = MgShowMgBox;

function MgHideMgBox() {
  getElem("id","mgBox","").style.visibility = "hidden";
  theMgBox.isOpenAndFilled = false;
}
mgBox.prototype.hideMgBox = MgHideMgBox;

// iterate through all text fields, install handlers for
// all text fields with attribute "mgBox"
function MgInitMgBoxes() {

// This function was inspired by Mircho Mirev's cAutocomplete.autoInit()
//  mo /mo@momche.net/
//	Copyright (c) 2004 Mircho Mirev
//
  var nI = 0;
  var sLangAtt;
  var hTextField=null;

  var nInputsLength = document.getElementsByTagName( 'INPUT' ).length
  for( nI = 0; nI < nInputsLength; nI++ ) {
    if( document.getElementsByTagName( 'INPUT' )[ nI ].type.toLowerCase() == 'text' ) {
      sLangAtt = document.getElementsByTagName( 'INPUT' )[ nI ].getAttribute( 'mgBox' )
      if( sLangAtt != null && sLangAtt.length > 0 ) {
        //alert("i think i found one");
        hTextField=document.getElementsByTagName( 'INPUT' )[ nI ];
        //don't submit the form
        hTextField.parentNode.onsubmit = function() {return false;}

        //alert(hTextField.onfocus);
        hTextField.onfocus=theMgBox.onFocus;
        hTextField.onblur=theMgBox.onBlur;
        //alert(hTextField.onfocus);

        if (isnearby = getElem("id","isnearby")){ //restsearch hack
        	isnearby.onclick = function() {
        		MgTimeoutReached("restname");
         		is_focused = false;
				  	setTimeout('getElem("id","restname").focus(); getElem("id","restname").value = getElem("id","restname").value;', 1);
       		}

        }
      }
    }
  }

  // call hook if present      
  if(typeof mgBox_onLoad_hook == 'function') {
    mgBox_onLoad_hook();
  }
}
mgBox.prototype.initMgBoxes = MgInitMgBoxes;


/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
////
////  the "main()" function
////
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
theMgBox = new mgBox();
theMgBox.initMgBoxes();

// Attach onLoad handler...
/*
if( window.attachEvent ) {
  window.attachEvent( 'onload', theMgBox.initMgBoxes );
} else if( window.addEventListener ) {
  window.addEventListener( 'load', theMgBox.initMgBoxes, false )
}
*/

function thisindex(elm) { 
	var nodes = elm.parentNode.childNodes, node; 
	var i = count = 0; 
	while( (node=nodes.item(i++)) && node!=elm ) 
		if( node.nodeType==1 ) count++; 
	return count; 
}

function scrollDown() {
  mgBoxDiv = getElem("id","mgBox");
  mgBoxDiv.childNodes[0].childNodes[theMgBox.highlightedline].className="";
  if(theMgBox.highlightedline < theMgBox.html_text_array.length - 1) {
    theMgBox.highlightedline = theMgBox.highlightedline + 1;
  } else {
  	clearInterval(intScroll);
  }
  // highlight the new line
  mgBoxDiv.childNodes[0].childNodes[theMgBox.highlightedline].className="mgHighlighted";
  sBox = getElem("id","mgScroll");
  line_count++;
	if (theMgBox.highlightedline == 0) {
  	sBox.scrollTop = 0;
  	line_count = 0;
  } else if (line_count > 9) {            	
  	sBox.scrollTop = sBox.scrollTop + 24;
  	line_count = 9;
  }
}

function scrollUp() {
  mgBoxDiv = getElem("id","mgBox");
  mgBoxDiv.childNodes[0].childNodes[theMgBox.highlightedline].className="";
  if(theMgBox.highlightedline > 0) {
	  theMgBox.highlightedline = theMgBox.highlightedline - 1;
  } else {
  	clearInterval(intScroll);
  }
  // highlight the new line
  mgBoxDiv.childNodes[0].childNodes[theMgBox.highlightedline].className="mgHighlighted";
  sBox = getElem("id","mgScroll");
  line_count--;
  if (theMgBox.highlightedline == theMgBox.html_text_array.length - 1) {            	
  	sBox.scrollTop = (theMgBox.html_text_array.length - 8) * 24;
  	line_count = 9;
  } else if (line_count < 0) {            	
  	sBox.scrollTop = sBox.scrollTop - 24;
  	line_count = 0;
  }
}

function findPos(obj) {
	var curleft = curtop = 0;
	if (obj.offsetParent) {
		do {
			curleft += obj.offsetLeft;
			curtop += obj.offsetTop;
		} while (obj = obj.offsetParent);
	}
	return [curleft,curtop];
}
