// przechowuje obiekt XMLHttpRequest
var xmlHttp = createXmlHttpRequestObject();
// przechowa adres zdalnego serwera
var serverAddress = "validate.php";
// kiedy ma wartość true, wyświetla szczegółowy opis błędu
var showErrors = true;
// inicjalizuje pamięć podręczną żądania
var cache = new Array();
// tworzy obiekt XMLHttpRequest
function createXmlHttpRequestObject() 
{
  // przechowa odwołanie do obiektu XMLHttpRequest
  var xmlHttp;
  // powinno działać dla wszystkich przeglądarek z wyjątkiem IE6 i starszych
  try
  {
    // próbuje stworzyć 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");
    // sprawdza każdy prog id aż któryś zadziała
    for (var i=0; i<XmlHttpVersions.length && !xmlHttp; i++) 
    {
      try 
      { 
        // próbuje stworzyć obiekt XMLHttpRequest
        xmlHttp = new ActiveXObject(XmlHttpVersions[i]);
      } 
      catch (e) {} // ignoruje potencjalne błędy
    }
  }
  // zwraca stworzony obiekt albo wyświetla komunikat o błędzie
  if (!xmlHttp)
    displayError("Błąd podczas tworzenia obiektu XMLHttpRequest.");
  else 
    return xmlHttp;
}
// funkcja wyświetlająca komunikat o błędzie
function displayError($message)
{
  // ignoruje błąd, jeśli zmienna showErrors ma wartość false
  if (showErrors)
  {
    // wyłącza wyświetlanie błędów
    showErrors = false;
    // wyświetla wiadomość o błędzie
    alert("Wystąpił błąd: \n" + $message);
    // ponawia weryfikację po 10. sekundach
    setTimeout("validate();", 10000);
  }
}
// funkcja obsługuje weryfikację dowolnego pola
function validate(inputValue, fieldID)
{
  // kontynuuje tylko jeśli obiekt xmlHttp nie jest pusty
  if (xmlHttp)
  {
    // jeśli otrzymujemy niezerowe parametry, dodajemy je do pamięci podręcznej  formularza w kolejce zapytań.
    // Później wyślemy je do weryfikacji na serwerze
    if (fieldID)
    {
      // koduje wartości żeby zabezpieczyć je na czas transmisji HTTP
      inputValue = encodeURIComponent(inputValue);
      fieldID = encodeURIComponent(fieldID);
      // dodaje wartości do kolejki
      cache.push("inputValue=" + inputValue + "&fieldID=" + fieldID);
    }
    // próbuje połączyć się z serwerem
    try
    {
      // kontynuuje jeśli obiekt XMLHttpRequest jest wolny a pamięć podręczna nie jest pusta
      if ((xmlHttp.readyState == 4 || xmlHttp.readyState == 0) && cache.length > 0)
      {
        // pobiera nowe parametry z pamięci
        var cacheEntry = cache.shift();
        // wysyła żądanie weryfikacji na serwer
        xmlHttp.open("POST", serverAddress, true);
        xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        xmlHttp.onreadystatechange = handleRequestStateChange;
        xmlHttp.send(cacheEntry);
      }
    }
    catch (e)
    {
      // wyświetla komunikat o błędzie, jeśli nie uda się połączyć z serwerem
      displayError(e.toString());
    }
  }
}
// funkcja obsługująca odpowiedź HTTP
function handleRequestStateChange() 
{
  // kiery readyState ma wartość 4, pobieramy odpowiedź serwera
  if (xmlHttp.readyState == 4) 
  {
    // kontynuuje, jeśli status HTTP jest "OK"
    if (xmlHttp.status == 200) 
    {
      try
      {
        // czyta odpowiedź serwera
        readResponse();
      }
      catch(e)
 
      {
        // wyświetla komunikat o błędzie
        displayError(e.toString());
      }
    }
    else
    {
      // wyświetla komunikat o błędzie
      displayError(xmlHttp.statusText);
    }
  }
}
// czyta odpowiedź serwera
function readResponse()
{
  // odbiera odpowiedź serwera
  var response = xmlHttp.responseText;
  // błąd serwera?
  if (response.indexOf("ERRNO") >= 0 || response.indexOf("error:") >= 0
    || response.length == 0)
    throw(response.length == 0 ? "Server error." : response);
  // pobiera odpowiedź w formacie XML (zakładając, że jest to poprawny plik XML)
  responseXml = xmlHttp.responseXML;
  // pobiera element document
  xmlDoc = responseXml.documentElement;
  result = xmlDoc.getElementsByTagName("result")[0].firstChild.data;
  fieldID = xmlDoc.getElementsByTagName("fieldid")[0].firstChild.data;
  // znajduje element HTML, który wyświetla błąd
  message = document.getElementById(fieldID + "Failed");
  // wyświetla lub ukrywa błąd
  message.className = (result == "0") ? "error" : "hidden";
  // wywołuje ponownie funkcję validate() na wypadek, gdyby w pamięci pozostały jakieś wpisy
  setTimeout("validate();", 500);
}
// ustawia kursor w pierwszym polu
function setFocus()    
{
  document.getElementById("txtUsername").focus();
}

