/* URL to the PHP page called for receiving suggestions for a keyword*/
var getFunctionsUrl =SITE_URL+ "suggest.php?ajax_page=true&keyword=";
/* URL for seeing the results for the selected suggestion */
var phpHelpUrl=SITE_URL+'answer.php?title=';
var opera = navigator.userAgent.toLowerCase().indexOf('opera')>=0?true:false;
/* the keyword for which an HTTP request has been initiated */
var crtMoreLink = SITE_SUGGEST_URL;
var httpRequestKeyword = "";
/* the last keyword for which suggests have been requested */
var userKeyword = "";
/* number of suggestions received as results for the keyword */
var suggestions = 0;
/* the maximum number of characters to be displayed for a suggestion */
var suggestionMaxLength = 255;
/* flag that indicates if the up or down arrow keys were pressed
   the last time a keyup event occurred  */
var isKeyUpDownPressed = false;
/* the last suggestion that has been used for autocompleting the keyword */
var autocompletedKeyword = "";
/* flag that indicates if there are results for the current requested keyword*/
var hasResults = false;
/* the identifier used to cancel the evaluation with the clearTimeout method. */
var timeoutId = -1;
/* the currently selected suggestion (by arrow keys or mouse)*/
var position = -1;
/* cache object containing the retrieved suggestions for different keywords */
var oCache = new Object();
/* the minimum and maximum position of the visible suggestions */
var minVisiblePosition = 0;
var maxVisiblePosition = 9;
// when set to true, display detailed error messages
var debugMode = true;
/* the XMLHttp object for communicating with the server */
var xmlHttpGetSuggestions = createXmlHttpRequestObject();
/* the onload event is handled by our init function */
//window.onload = init;
// creates an XMLHttpRequest instance
function createXmlHttpRequestObject()
{
  // will store the reference to the XMLHttpRequest object
  var xmlHttp;
  // this should work for all browsers except IE6 and older
  try
  {
    // try to create XMLHttpRequest object
    xmlHttp = new XMLHttpRequest();
  }
  catch(e)
  {
    // assume IE6 or older
    var XmlHttpVersions = new Array("MSXML2.XMLHTTP.6.0",
                                    "MSXML2.XMLHTTP.5.0",
                                    "MSXML2.XMLHTTP.4.0",
                                    "MSXML2.XMLHTTP.3.0",
                                    "MSXML2.XMLHTTP",
                                    "Microsoft.XMLHTTP");
    // try every prog id until one works
    for (var i=0; i<XmlHttpVersions.length && !xmlHttp; i++)
    {
      try

      {
        // try to create XMLHttpRequest object
        xmlHttp = new ActiveXObject(XmlHttpVersions[i]);
      }
      catch (e) {}
    }
  }
  // return the created object or display an error message
  if (!xmlHttp)
    alert_manual(QUES_SUGG_LANG['error_request']);
  else
    return xmlHttp;
}

/* function that initializes the page */
function init()
{
  // retrieve the input control for the keyword
  var oKeyword = document.getElementById("question");
  // prevent browser from starting the autofill function
  oKeyword.setAttribute("autocomplete", "off");
  // reset the content of the keyword and set the focus on it
  //oKeyword.value = "";
  //oKeyword.focus();
  // set the timeout for checking updates in the keyword's value
  setTimeout("checkForChanges()", 500);
}

/* function that adds to a keyword an array of values */
function addToCache(keyword, values)
{
  // create a new array entry in the cache
  oCache[keyword] = new Array();
  // add all the values to the keyword's entry in the cache
  for(i=0; i<values.length; i++)
    oCache[keyword][i] = values[i];
}
/* initiate HTTP request to retrieve suggestions for the current keyword */
function getSuggestions(keyword)
{
  /* continue if keyword isn't null and the last pressed key wasn't up or
     down */

        try
        {
          /* if the XMLHttpRequest object isn't busy with a previous
             request... */
          if (xmlHttpGetSuggestions.readyState == 4 ||
              xmlHttpGetSuggestions.readyState == 0)
          {
            httpRequestKeyword = keyword;
            userKeyword = keyword;
            xmlHttpGetSuggestions.open("GET",
                                getFunctionsUrl + encode(keyword), true);
            xmlHttpGetSuggestions.onreadystatechange =
                                                handleGettingSuggestions;
            xmlHttpGetSuggestions.send(null);
          }
          // if the XMLHttpRequest object is busy...
          else
          {
            // retain the keyword the user wanted
            userKeyword = keyword;
            // clear any previous timeouts already set
            if(timeoutId != -1)
              clearTimeout(timeoutId);
            // try again in 0.5 seconds
            timeoutId = setTimeout("getSuggestions(userKeyword);", 500);
          }
        }
        catch(e)

        {
          displayError( QUES_SUGG_LANG['server_error']);
        }

}

/* transforms all the children of an xml node into an array */
function xmlToArray(resultsXml)
{
  // initiate the resultsArray
  var resultsArray= new Array();
  // loop through all the xml nodes retrieving the content
  for(i=0;i<resultsXml.length;i++)
    resultsArray[i]=resultsXml.item(i).firstChild.data;
  // return the node's content as an array
  return resultsArray;
}
function xmlLinkToArray(resultsLinkXml)
{
  // initiate the resultsArray
  var resultsLinkArray= new Array();
  // loop through all the xml nodes retrieving the content
  for(i=0;i<resultsLinkXml.length;i++)
    resultsLinkArray[i]=resultsLinkXml.item(i).firstChild.data;

  // return the node's content as an array
  return resultsLinkArray;
}


/* handles the server's response containing the suggestions
   for the requested keyword  */
function handleGettingSuggestions()
{
  //if the process is completed, decide what to do with the returned data
  if (xmlHttpGetSuggestions.readyState == 4)
  {
    // only if HTTP status is "OK"
    if (xmlHttpGetSuggestions.status == 200)
    {
      try
      {
        // process the server's response
        updateSuggestions();
      }
      catch(e)
      {
       	// display the error message
		//displayError();
      }
    }
    else
    {
      displayError( QUES_SUGG_LANG['display_error']);
    }
  }
}

/* function that processes the server's response */
function updateSuggestions()
{
  // retrieve the server's response
  var response = xmlHttpGetSuggestions.responseText;
  // server error?
  if (response.indexOf("ERRNO") >= 0
      || response.indexOf("error:") >= 0
      || response.length == 0)
    throw(response.length == 0 ? QUES_SUGG_LANG['response_error'] : response);
   // retrieve the document element
  response = xmlHttpGetSuggestions.responseXML.documentElement;
  // initialize the new array of functions' names
  nameArray = new Array();
  nameLinkArray = new Array();
  // check to see if we have any results for the searched keyword

  if(response.childNodes.length)
  {
	/* we retrieve the new functions' names from the document element as
       an array */
    nameArray= xmlToArray(response.getElementsByTagName("name"));
	nameLinkArray= xmlLinkToArray(response.getElementsByTagName("link"));

  }

  // check to see if other keywords are already being searched for
  if(httpRequestKeyword == userKeyword)
  {
    // display the results array
    displayResults(httpRequestKeyword, nameArray, nameLinkArray);
  }
  else
  {
    // add the results to the cache
    // we don't need to display the results since they are no longer useful
    addToCache(httpRequestKeyword, nameArray);
  }
}

/* populates the list with the current suggestions */
function displayResults(keyword, results_array, results_link_array)
{
  // start building the HTML table containing the results
  var div = "<table>";
  div += "<tr id='relatedSuggestLink'><td class='clsSuggestHeading'>"+ QUES_SUGG_LANG['related_question'] +"</td></tr>" ;
  // if the searched for keyword is not in the cache then add it to the cache
  if(!oCache[keyword] && keyword)
    addToCache(keyword, results_array);
  // if the array of results is empty display a message
  if(results_array.length == 0)
  {
    div += "<tr><td class='clsSuggestNoRecords'>"+ QUES_SUGG_LANG['no_records'] +"<strong>" + keyword +
           "</strong></td></tr>";
    // set the flag indicating that no results have been found
    // and reset the counter for results
    hasResults = false;
    suggestions = 0;
  }
  // display the results
  else
  {
    // resets the index of the currently selected suggestion
    position = -1;
    // resets the flag indicating whether the up or down key has been pressed
    isKeyUpDownPressed = false;
    /* sets the flag indicating that there are results for the searched
       for keyword */
    hasResults = true;
    // get the number of results from the cache
    suggestions = oCache[keyword].length;
    // loop through all the results and generate the HTML list of results

    for (var i=0; i<oCache[keyword].length; i++)
    {
      // retrieve the current function
      crtFunction = oCache[keyword][i];
      // set the string link for the for the current function
      // to the name of the function
      crtFunctionLink = crtFunction;
	   // replace the _ with - in the string link

	  while(crtFunctionLink.indexOf(" ") !=-1)
	  	{
        	crtFunctionLink = crtFunctionLink.replace(" ","-");
		}
      // start building the HTML row that contains the link to the
      // PHP help page of the current function
      div += "<tr id='tr" + i +
             "' onclick='location.href=document.getElementById(\"a" + i +
             "\").href;' onmouseover='handleOnMouseOver(this);' " +
             "onmouseout='handleOnMouseOut(this);'>" +
             "<td align='left'><a id='a" + i +
             "' href='" + results_link_array[i] ;

          // bold the entire function name
          div += "'><b>" +
                 crtFunction.substring(0,suggestionMaxLength) +
                 "</b></td></tr>"

    }
    div += "<tr id='moreLink'>" +
             "<td align='right'><a href='" + crtMoreLink+keyword+
                 "'>"+ QUES_SUGG_LANG['more'] +" </a></b></td></tr>" ;


  }

  // end building the HTML table
  div += "</table>";
  // retrieve the suggest and scroll object
  var oSuggest = document.getElementById("suggest");
  var oScroll = document.getElementById("scroll");
  // scroll to the top of the list
  oScroll.scrollTop = 0;
  // update the suggestions list and make it visible
  oSuggest.innerHTML = div;
  oScroll.style.visibility = "visible";
  // if we had results we apply the type ahead for the current keyword
  if(results_array.length > 0)
    autocompleteKeyword();
}

/* function that periodically checks to see if the typed keyword has changed */
function checkForChanges()
{
  // retrieve the keyword object

  var keyword = document.getElementById("question").value;
  // check to see if the keyword is empty
  if(keyword == "")
  {
    // hide the suggestions
    hideSuggestions();
    // reset the keywords
    userKeyword="";
    httpRequestKeyword="";
  }
  // set the timer for a new check
  setTimeout("checkForChanges()", 500);
  // check to see if there are any changes
if((userKeyword != keyword) &&
      (!isKeyUpDownPressed))
    // update the suggestions
    getSuggestions(keyword);
}

/* function that handles the keys that are pressed */
function handleKeyUp(e)
{
  // get the event
  e = (!e) ? window.event : e;
  // get the event's target
  target = (!e.target) ? e.srcElement : e.target;
  if (target.nodeType == 3)
    target = target.parentNode;
  // get the character code of the pressed button
  code = (e.charCode) ? e.charCode :
       ((e.keyCode) ? e.keyCode :
       ((e.which) ? e.which : 0));

  // check to see if the event was keyup
  if (e.type == "keyup")
  {

    isKeyUpDownPressed =false;
    // check to see we if are interested in the current character
    if ((code < 13 && code != 8) ||
        (code >=14 && code < 32) ||
        (code >= 33 && code <= 46 && code != 38 && code != 40) ||
        (code >= 112 && code <= 123))
    {
      // simply ignore non-interesting characters
    }
    else
    /* if Enter is pressed we jump to the PHP help page of the current
       function */
    if(code == 13)
    {
      // check to see if any function is currently selected
      if(position>=0)
      {
        location.href = document.getElementById("a" + position).href;
      }
    }
    else
    // if the down arrow is pressed we go to the next suggestion
      if(code == 40)
      {
        newTR=document.getElementById("tr"+(++position));
        oldTR=document.getElementById("tr"+(--position));
        // deselect the old selected suggestion
        if(position>=0 && position<suggestions-1)
          oldTR.className = "";

        // select the new suggestion and update the keyword
        if(position < suggestions - 1)
        {
          newTR.className = "highlightrow";
          //updateKeywordValue(newTR);
          position++;
        }
        e.cancelBubble = true;
        e.returnValue = false;
        isKeyUpDownPressed = true;
        // scroll down if the current window is no longer valid
        if(position > maxVisiblePosition)
        {
          oScroll = document.getElementById("scroll");
          oScroll.scrollTop += 18;
          maxVisiblePosition += 1;
          minVisiblePosition += 1;
        }
      }
      else
      // if the up arrow is pressed we go to the previous suggestion
      if(code == 38)
      {
        newTR=document.getElementById("tr"+(--position));
        oldTR=document.getElementById("tr"+(++position));
        // deselect the old selected position
        if(position>=0 && position <= suggestions - 1)
        {
          oldTR.className = "";
        }
        // select the new suggestion and update the keyword
        if(position > 0)
        {
          newTR.className = "highlightrow";
          //updateKeywordValue(newTR);
          position--;
          // scroll up if the current window is no longer valid
          if(position<minVisiblePosition)
          {
            oScroll = document.getElementById("scroll");
            oScroll.scrollTop -= 18;
            maxVisiblePosition -= 1;
            minVisiblePosition -= 1;
          }
        }
        else
          if(position == 0)
            position--;
        e.cancelBubble = true;
        e.returnValue = false;
        isKeyUpDownPressed = true;
      }
  }
}

/* function that updates the keyword value with the value
   of the currently selected suggestion */
function updateKeywordValue(oTr)
{
  // retrieve the keyword object
  var oKeyword = document.getElementById("question");
  // retrieve the link for the current function
  var crtLink = document.getElementById("a" +
                            oTr.id.substring(2,oTr.id.length)).toString();
  // replace - with _ and leave out the .php extension

  crtLink = crtLink.replace("-", "_");
  crtLink = crtLink.substring(0, crtLink.length - 4);
  // update the keyword's value
  oKeyword.value = unescape(crtLink.substring(phpHelpUrl.length, crtLink.length));
}

/* function that removes the style from all suggestions*/
function deselectAll()
{
  for(i=0; i<suggestions; i++)
  {
    var oCrtTr = document.getElementById("tr" + i);
    oCrtTr.className = "";
  }
}

/* function that handles the mouse entering over a suggestion's area
   event */
function handleOnMouseOver(oTr)
{
  deselectAll();
  oTr.className = "highlightrow";
  position = oTr.id.substring(2, oTr.id.length);
}

/* function that handles the mouse exiting a suggestion's area event */
function handleOnMouseOut(oTr)
{
  oTr.className = "";
  position = -1;
}

/* function that escapes a string */
function encode(uri)
{
  if (encodeURIComponent)
  {
    return encodeURIComponent(uri);
  }

  if (escape)
  {
    return escape(uri);
  }
}

var clearSuggestion = '';
function hideSuggestionsAfterSometime(){
	var clearSuggestion = setTimeout('hideSuggestions()', 500);
}

/* function that hides the layer containing the suggestions */
function hideSuggestions()
{
  var oScroll = document.getElementById("scroll");
  if (oScroll) oScroll.style.visibility = "hidden";
  if (clearSuggestion) clearTimeout(clearSuggestion);
}

/* function that hides the layer containing the suggestions */
function showSuggestions()
{
  var oScroll = document.getElementById("scroll");
  if (oScroll) oScroll.style.visibility = "visible";
}

/* function that selects a range in the text object passed as parameter */
function selectRange(oText, start, length)
{
  // check to see if in IE or FF
  if (oText.createTextRange)
  {
    //IE
    var oRange = oText.createTextRange();
    oRange.moveStart("character", start);
    oRange.moveEnd("character", length - oText.value.length);
    oRange.select();

  }
  else
    // FF
    if (oText.setSelectionRange)
    {
      oText.setSelectionRange(start, length);
    }
  oText.focus();
}

/* function that autocompletes the typed keyword*/
function autocompleteKeyword()
{
  //retrieve the keyword object
  var oKeyword = document.getElementById("question");
  // reset the position of the selected suggestion
  position=0;
  // deselect all suggestions
  deselectAll();
  // highlight the selected suggestion
  document.getElementById("tr0").className="highlightrow";
  // update the keyword's value with the suggestion
  //updateKeywordValue(document.getElementById("tr0"));
  // apply the type-ahead style
  selectRange(oKeyword,httpRequestKeyword.length,oKeyword.value.length);
  // set the autocompleted word to the keyword's value
  autocompletedKeyword=oKeyword.value;
}

/* function that displays an error message */
function displayError(message)
{
  // display error message, with more technical details if debugMode is true
  	var alert_message =  message;
	alert_manual(alert_message);

}

