/* URL do strony PHP, która poda podpowiedzi dla danego słowa kluczowego*/
var getFunctionsUrl = "suggest.php?keyword=";
/* URL który pokaże wyniki wyświetlane dla wybranej podpowiedzi */
var phpSearchUrl="http://mojrom.adm.com.pl/index.php?keyword=";
/* słowo kluczowe, dla którego wywołujemy żądanie HTTP*/
var httpRequestKeyword = "";
/* ostatnie słowo kluczowe, dla którego wysyłano żądanie*/
var userKeyword = "";
/* ilość podpowiedzi pojawiających się dla danego słowa kluczowego*/
var suggestions = 0;
/* maksymalna liczba znaków wyświetlanych w podpowiedzi*/
var suggestionMaxLength = 30;
/* flaga, która wskazuje, czy użytkownik skorzystał ze strzałek w górę lub w dół podczas ostatniego zdarzenia keyup*/
var isKeyUpDownPressed = false;
/* ostatnia podpowiedź użyta do autouzupełniania słowa kluczowego*/
var autocompletedKeyword = "";
/* flaga, która określa, czy są wyniki dla obecnego słowa kluczowego*/
var hasResults = false;
/* identyfikator używany do odwołania procesu oceny (metoda Timeout)*/
var timeoutId = -1;
/* obecnie wybrana (myszą lub strzałkami) podpowiedź*/
var position = -1;
/* obiekt pamięci podręcznej, zawierający podpowiedzi pobrane dla różnych słów kluczowych*/
var oCache = new Object();
/* minimalna i maksymalna pozycja widocznych podpowiedzi*/
var minVisiblePosition = 0;
var maxVisiblePosition = 9;
// wartośc true owoduje wyświetlenie szczegółowego komunikatu o błędzie
var debugMode = true;
/* obiekt XMLHttpRequest, stworzony do komunikowania się z serwerem*/
var xmlHttpGetSuggestions = createXmlHttpRequestObject();

var input_focus=false;
/* funkcja init obsługuje zdarzenie onload*/
window.onload = init;
//tworzy instancję obiektu XMLHttpRequest
function createXmlHttpRequestObject() 
{
  // przechowa odowłanie do obiektu XMLHttpRequest
  var xmlHttp;
  // powinno zadziałać dla wszystkich przeglądarem z wyjątkiem IE6 i starszych
  try
  {
    // próbuje utworzyć obiekt XMLHttpRequest
    xmlHttp = new XMLHttpRequest();
  }
  catch(e)
  {
    // zakładając, że IE6 lub starsza
    var XmlHttpVersions = new Array("MSXML2.XMLHTTP.6.0",
      "MSXML2.XMLHTTP.5.0",
      "MSXML2.XMLHTTP.4.0",
      "MSXML2.XMLHTTP.3.0",
      "MSXML2.XMLHTTP",
      "Microsoft.XMLHTTP");
    // próbuje wszystkie wartości progId, aż jedna zadziała
    for (var i=0; i<XmlHttpVersions.length && !xmlHttp; i++) 
    {
      try 
      { 
        // próbuje stworzyć obiekt XMLHttpRequest
        xmlHttp = new ActiveXObject(XmlHttpVersions[i]);
      } 
      catch (e) {}
    }
  }
  // zwraca utworzony obiekt lub wyświetla komunikat o błędzie
  if (!xmlHttp)
    alert("Błąd podczas tworzenia obiektu XMLHttpRequest.");
  else 
    return xmlHttp;
}
/* funkcja inicjująca stronę*/
function init() 
{  
  // pobiera element kontrolujący słowo kluczowe podane na wejściu
  var oKeyword = document.getElementById("keyword");    
  // zapobiega uruchomieniu domyślnego autouzupełniania przeglądarki
  oKeyword.setAttribute("autocomplete", "off");  
  // czyści zawartość słowa kluczowego i ustawia kursor w okienku tekstowym
  //oKeyword.value = "";
 // oKeyword.focus();
  // czas, po którym sprawdza się, czy nastąpiły zmiany w polu tekstowym
  setTimeout("checkForChanges()", 500);
} 
/* funkcja, która dodaje słowo kluczowe do tablicy wartości */
function addToCache(keyword, values)
{
  // twrzy nowy wpis w tablicy pamięci podręcznej
  oCache[keyword] = new Array();
  // dodaje nowe wartości słów kluczowych do pamięci
  for(i=0; i<values.length; i++)
    oCache[keyword][i] = values[i];
}
/* funkcja, która sprawdza, czy słowo kluczowe jest już w pamięci lub próbuje znaleźć najdłuższe przedrostki z pamięci do niego pasujące. Następnie dodaje je do pamięci, jako odpowiadające wpisanemu słowu kluczowemu */
function checkCache(keyword)
{

//nie cachujemy nazw zwierających polskie znaki
   if(keyword.indexOf('ś')>0) return false;
   if(keyword.indexOf('ą')>0) return false;
   if(keyword.indexOf('ę')>0) return false;
  
  // sprawdza, czy słowo kluczowe jest już w pamięci
  if(oCache[keyword])
    return true;
  // próbuje odnaleźć najdłuższy przedrostek
  for(i=keyword.length-2; i>=0; i--)
  {
    // uzupełnia bieżące słowo kluczowe
    var currentKeyword = keyword.substring(0, i+1);
    // sprawdza, czy bieżący przedrostek słowa kluczowego jest już w pamięci
    if(oCache[currentKeyword])
    {
      // jeśli jest w pamięci
      var cacheResults = oCache[currentKeyword];
      // wyniki odpowiadające bieżącemu słowu kluczowemu
      var keywordResults = new Array();
      var keywordResultsSize = 0;            
      // próbuje odnaleźć wszystkie funkcje pasujące do bieżącego przedrostka
      for(j=0;j<cacheResults.length;j++)
      {
        if(cacheResults[j].indexOf(keyword) == 0)               
          keywordResults[keywordResultsSize++] = cacheResults[j];
      }      
      // dodaje wszystkie przedrostki słowa kluczowego do pamięci
      addToCache(keyword, keywordResults);
       //alert(currentKeyword);
      return true;
    }
  }
  // nie znaleziono funkcji
  return false;
}

/* początkuje żądanie HTTP, w celu pobrania podpowiedzi dla wpisanego słowa kluczowego */
function getSuggestions(keyword) 
{  
  /* kontynuuje, jeśli wpisano jakieś znaki i ostatnio wciśniętym klawiszem nie była jedna z pionowych strzałek*/
  
  if(keyword != "" && keyword.length>1 && !isKeyUpDownPressed)
  {
    isInCache = checkCache(keyword);

    // jeśli jest...
    if(isInCache == true)          
    {   
      // pobiera wyniki z pamięci
      httpRequestKeyword=keyword;
      userKeyword=keyword;     
      // wyświetla wyniki 
      displayResults(keyword, oCache[keyword]); 
    }
    // jeśli go nie ma w pamięci, wysyła noże żądanie HTTP
    else    
    {    
      if(xmlHttpGetSuggestions)
      { 
        try
        {
          /* jeśli obiekt XMLHttpRequest nie jest zajęty obsługą poprzedniego żądnia... */
          if (xmlHttpGetSuggestions.readyState == 4 || 
              xmlHttpGetSuggestions.readyState == 0) 
          {    
            httpRequestKeyword = keyword;
            userKeyword = keyword;
           // alert(getFunctionsUrl + encode(keyword));
            xmlHttpGetSuggestions.open("GET", getFunctionsUrl + encode(keyword), true);
            xmlHttpGetSuggestions.onreadystatechange = handleGettingSuggestions;
            xmlHttpGetSuggestions.send(null);
          }
          // jeśli jest zajęty...
          else
          {
            // pobiera słowo, które wpisał użytkownik
            userKeyword = keyword;
            // czyści poprzednio ustawione czasy
            if(timeoutId != -1)
              clearTimeout(timeoutId); 
            // ponawia próbę po 0.5 sekundy     
            timeoutId = setTimeout("getSuggestions(userKeyword);", 500);
          }
        }
        catch(e)
        {
          displayError("Nie mogę połączyć się z serwerem:\n" + e.toString());
        }
      }
    }    
  }
}
/* przekształca wszystkie obiekty potomne węzła XML na tablicę*/
function xmlToArray(resultsXml)
{
  // początkuje zmienną resultsArray
  var resultsArray= new Array();  
  // przeszukuje w pętli wszystkie węzły XML, pobierając ich zawartość
  for(i=0;i<resultsXml.length;i++)
    resultsArray[i]=resultsXml.item(i).firstChild.data;
  // zwraca zawartość węzła w postaci tablicy
  return resultsArray;
}
/*  obsługuje odpowiedź serwera, zawierającą podpowiedzi dla żądanego słowa kluczowego */
function handleGettingSuggestions() 
{
  //po ukończeniu procesu, decyduje co zrobić z otrzymanymi danymi
  if (xmlHttpGetSuggestions.readyState == 4) 
  {
    // tylko jeśli status żądania HTTP jest "OK"
    if (xmlHttpGetSuggestions.status == 200) 
    { 
      try
      {
        // przetwarza odpowiedź serwera
        updateSuggestions();
      }
      catch(e)
      {
        // wyświetla komunikat o błędzie
        displayError(e.toString()); 
      }  
    } 
    else
    {
      displayError("Wystąpił problem podczas pobierania danych:\n" +
        xmlHttpGetSuggestions.statusText);
    }       
  }
}
/* funkcja przetwarzająca odpowiedź serwera */
function updateSuggestions()
{
  // pobiera odpowiedź serwera
  var response = xmlHttpGetSuggestions.responseText;
  // błąd serwera?
  if (response.indexOf("ERRNO") >= 0 || response.indexOf("error:") >= 0
    || response.length == 0)
    throw(response.length == 0 ? "Void server response." : response);
  // pobiera element dokumentu
  response = xmlHttpGetSuggestions.responseXML.documentElement;
  // zakłada nową tablicę z nazwami funkcji
  nameArray = new Array();
  // sprawdza, czy są wyniki dla szukanego słowa kluczowego
  if(response.childNodes.length)
  {
    /* pobieramy nowe nazwy funkcji z pliku XML w postaci tablicy */
    nameArray= xmlToArray(response.getElementsByTagName("name"));       
  }
  // sprawdza, czy są już poszukiwane inne słowa kluczowe 
  if(httpRequestKeyword == userKeyword)    
  {
    // wyświetla tablicę wyników
    displayResults(httpRequestKeyword, nameArray);
  }
  else
  {
    // dodaje wyniki do pamięci
    // nie trzeba wyświetlać wyników, ponieważ są już niepotrzebne
    addToCache(httpRequestKeyword, nameArray); 
  }
}

/* zapełnia listę podpowiedziami*/
function displayResults(keyword, results_array) 
{  
  // rozpoczyna tworzenie tabeli HTML, w której umieścimy wyniki

  var show_r=true;
  
  if(results_array.length < 2) { hideSuggestions(); }

  var div = "<table>"; 
  // jeśli poszukiwane słowo kluczowe nie znajduje się w pamięci, dodaje je do niej
  if(!oCache[keyword] && keyword)
    addToCache(keyword, results_array);
  // jeśli tablica wyników jest pusta, wyświetla komunikat
  if(results_array.length == 0)
  {
    div += "<tr><td>Nie znaleziono dopasowania dla <strong>" + keyword + 
           "</strong></td></tr>";
    // ustawia flagę braku wyników i zeruje licznik
    hasResults = false;
    show_r=false;
    suggestions = 0;
  }
  // wyświetla wyniki
  else
  {
    // przestawia indeks wyróżnionej podpowiedzi
    position = -1;
    // przestawia flagę określającą, czy wciśnięto którąś ze strzałek
    isKeyUpDownPressed = false;
    /* ustawia flagę informującą o dopasowania funkcji do podanego słowa kluczowego */
    hasResults = true;
    // pobiera z pamięci liczbę wyników
    suggestions = oCache[keyword].length;
    // przegląda w pętli wyniki i tworzy ich listę w HTML
    for (var i=0; i<oCache[keyword].length; i++) 
    {  
      // pobiera bieżącą nazwę funkcji
      crtFunction = oCache[keyword][i];
      // ustawia łańcuch odnośnika do dopasowanej funkcji na jej nazwę
      crtFunctionLink = crtFunction;
      // zastępuje znak _ w łańcuchu odnośnika znakiem - 
     // while(crtFunctionLink.indexOf("_") !=-1)
     //   crtFunctionLink = crtFunctionLink.replace("_","-");
     
      // zaczyna tworzyć rząd tabeli HTML, który zawiera odnośnik do oficjalnej strony z pomocą dotyczącą szukanej funkcji
      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='" + phpSearchUrl + escape(encodeURIComponent(crtFunctionLink));
      // sprawdza czy długość nazwy wybranej funkcji przekracza dopuszczalną liczbę znaków, które mogą być wyświetlone
      if(crtFunction.length <= suggestionMaxLength)
      {

        // pogrubia dopasowany fragment tekstu
        //div += "'><b>" + crtFunction.substring(0, httpRequestKeyword.length) + "</b>"
        //div += crtFunction.substring(httpRequestKeyword.length, crtFunction.length) +
       //   "</a></td></tr>";
        var tekst= crtFunction;
        tekst = tekst.replace(httpRequestKeyword, '<strong>'+httpRequestKeyword+'</strong>');
        div += "'>" + tekst;
        div +=      "</a></td></tr>";

      }
      else
      {
        // sprawdza czy długość nazwy wybranego słowa kluczowego przekracza dopuszczalną liczbę znaków, które mogą być 
        //wyświetlone
        if(httpRequestKeyword.length < suggestionMaxLength)
        {
          /* pogrubia dopasowany fragment tekstu */
          //div += "'><b>" + crtFunction.substring(0, httpRequestKeyword.length) + "</b>"
          //div += crtFunction.substring(httpRequestKeyword.length, suggestionMaxLength) +
          //  "</a></td></tr>";
          var tekst= crtFunction;
          tekst = tekst.replace(httpRequestKeyword, '<strong>'+httpRequestKeyword+'</strong>');
          div += "'>" + tekst;
          div +=      "</a></td></tr>";
        }
        else
        {
          // pogrubia całą nazwę funkcji
          //div += "'><b>" + crtFunction.substring(0,suggestionMaxLength) +
          //  "</b></td></tr>"
          var tekst= crtFunction;
          tekst = tekst.replace(httpRequestKeyword, '<strong>'+httpRequestKeyword+'</strong>');
          div += "'>" + tekst;
          div +=      "</a></td></tr>";
        }
      }
    }
  }
  // koniec tabeli HTML
  div += "</table>";
  // pobiera obiekty oSuggest i oScroll
  var oSuggest = document.getElementById("suggest");  
  var oScroll = document.getElementById("scroll");
  // przewija na górę listy
  oScroll.scrollTop = 0;
  // aktualizuje i wyświetla listę podpowiedzi
  oSuggest.innerHTML = div;

  if(show_r ==true)
  {
//alert(show_r);
  oScroll.style.visibility = "visible";
  oScroll.style.display = "block";
  }
  // jeśli były jakieś wyniki uzupełniamy słowo kluczowe do wartości pierwszej funkcji
 // if(results_array.length > 0)
 //   autocompleteKeyword();
    var oKeyword = document.getElementById("keyword");
    autocompletedKeyword=oKeyword.value;
}

/* funkcja, która okresowo sprawdza, czy wprowadzono zmiany w oknie tekstowym */
function checkForChanges()
{
  // pobiera obiekt słowa kluczowego
  var keyword = document.getElementById("keyword").value;

  if(keyword == "" || input_focus==false)
  {
    // ukrywa podpowiedzi
    hideSuggestions();
    // czyści słowo kluczowe
    userKeyword="";
    httpRequestKeyword="";
  }
  // ustawia licznik czasu dla nowego sprawdzenia
  setTimeout("checkForChanges()", 500);
  // sprawdza, czy wprowadzono zmiany 
  if((userKeyword != keyword) && (autocompletedKeyword != keyword) &&
    (!isKeyUpDownPressed))
    // aktualizuje podpowiedź
    getSuggestions(keyword);
}

/* funkcja obsługująca wciśnięcie klawisza*/
function handleKeyUp(e) 
{
  // pobiera zdarzenie
  e = (!e) ? window.event : e;
  // pobiera adresata zdarzenia
  target = (!e.target) ? e.srcElement : e.target;
  if (target.nodeType == 3) 
    target = target.parentNode;
  // pobiera kod znaku naciśniętego klawisza
  code = (e.charCode) ? e.charCode :
       ((e.keyCode) ? e.keyCode :
       ((e.which) ? e.which : 0));
  // sprawdza, czy zdarzenie było typu  keyup
  if (e.type == "keyup") 
  {    
    isKeyUpDownPressed =false; 
    // sprawdza, czy pojawił się któryś z ważnych dla aplikacji znaków
    if ((code < 13 && code != 8) || (code >=14 && code < 32) ||
      (code >= 33 && code <= 46 && code != 38 && code != 40) ||
      (code >= 112 && code <= 123)) 
    {
      // ignoruje pozostałe znaki
    }
    else
    /* po wciśnięciu klawisza Enter, przechodzi do strony pomocy PHP dla danej funkcji */
    if(code == 13)
    {
      // sprawdza, czy jakaś funkcja jest właśnie wybrana
      if(position>=0)
      {
        location.href = document.getElementById("a" + position).href;
      }        
    }        
    else
    // po naciśnięciu strzałki w dół przechodzi do kolejnej podpowiedzi
      if(code == 40)
      {                   
        newTR=document.getElementById("tr"+(++position));
        oldTR=document.getElementById("tr"+(--position));
        // usuwa stary wybór
        if(position>=0 && position<suggestions-1)
          oldTR.className = "";
 
        // wybiera nową podpowiedź i aktualizuje słowo kluczowe
        if(position < suggestions - 1)
        {
          newTR.className = "highlightrow";
          updateKeywordValue(newTR);
          position++;         
        }     
        e.cancelBubble = true;
        e.returnValue = false;
        isKeyUpDownPressed = true;        
        // przewija podpowiedzi w dół, jeśli widoczne okno nie jest już aktualne
        if(position > maxVisiblePosition)
        {   
          oScroll = document.getElementById("scroll");
          oScroll.scrollTop += 18;
          maxVisiblePosition += 1;
          minVisiblePosition += 1;
        }
      }
      else
      // naciśnięcie strzałki w góę przenosi nas do poprzedniej podpowiedzi
      if(code == 38)
      {       
        newTR=document.getElementById("tr"+(--position));
        oldTR=document.getElementById("tr"+(++position));
        // usuwa stare zaznaczenie
        if(position>=0 && position <= suggestions - 1)
        {       
          oldTR.className = "";
        }
        // zaznacza nową podpowiedź i aktualizuje słowo kluczowe
        if(position > 0)
        {
          newTR.className = "highlightrow";
          updateKeywordValue(newTR);
          position--;
          // przewija okno w górę, jeśli dane w nim są już nieaktualne
          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;  
      }     
  }
}
/* funkcja uzupełniająca słowo kluczowe do warości wybranej podpowiedzi */
function updateKeywordValue(oTr)
{
  // pobiera obiekt słowa kluczowego
  var oKeyword = document.getElementById("keyword");
  // pobiera odnośnik do wybranej funkcji
  var crtLink = document.getElementById("a" +
    oTr.id.substring(2,oTr.id.length)).toString();
  // zastępuje znaki - znakami _ i pomija rozszerzenie .php
  //crtLink = crtLink.replace("-", "_");
  crtLink = crtLink.substring(0, crtLink.length);
  // aktualizuje słowo kluczowe
 oKeyword.value=decodeURIComponent(unescape(crtLink.substring(phpSearchUrl.length, crtLink.length)));
}

/* funkcja usuwająca styl podpowiedzi */
function deselectAll()
{ 
  for(i=0; i<suggestions; i++)
  {
    var oCrtTr = document.getElementById("tr" + i);
    oCrtTr.className = "";    
  }
}
/* funkcja obsługująca pojawienie się kursora myszy w obszarze podpowiedzi */
function handleOnMouseOver(oTr)
{
  deselectAll();  
  oTr.className = "highlightrow";  
  position = oTr.id.substring(2, oTr.id.length);
}
/* funkcja obsługująca wyjście kursora myszy z obszaru podpowiedzi */
function handleOnMouseOut(oTr)
{
  oTr.className = "";   
  position = -1;
}

/* funkcja sterująca łańcuchem */
function encode(uri) 
{
  if (encodeURIComponent) 
  {
    return escape(encodeURIComponent(uri));
  }

  if (escape) 
  {
    return escape(uri);
  }
}
/* funkcja ukrywająca warstwę z popdpowiedziami */
function hideSuggestions()
{
  var oScroll = document.getElementById("scroll");
  oScroll.style.visibility = "hidden";
  oScroll.style.display = "none";

}
/* funkcja, która wybiera obszar w obiekcie tekstowym, przekazywanym jako jej parametr */
function selectRange(oText, start, length)
{  
  // sprawdz rodzaj przeglądarki - IE czy 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();
}
/* funkcja uzupełniająca wpisane słowo kluczowe */
function autocompleteKeyword()
{
  //pobiera obikt słowa kluczowego
  var oKeyword = document.getElementById("keyword");
  // zeruje pozycję zaznaczonej podpowiedzi
  position=0;
  // usuwa zaznacznie ze wszystkich odpowiedzi
  deselectAll();
  // podświetla wybraną podpowiedź
  document.getElementById("tr0").className="highlightrow";  
  // uzupełnia słowo kluczowe do podpowiedzi
   updateKeywordValue(document.getElementById("tr0"));
  // stosuje odpowiedni styl 
  selectRange(oKeyword,httpRequestKeyword.length,oKeyword.value.length);  
  // ustawia uzupełnione słowo jako wartość słowa kluczowego
  autocompletedKeyword=oKeyword.value;
}
/* funkcja wyświetlająca komunikat o błędzie */
function displayError(message)
{
  // wyświetla komunikat błędu - bardziej szczegółowy jeśli debugMode ma wartość true
  alert("Błąd podczas dostępu do serwera! " + (debugMode ? "\n" + message : ""));
}

