function MVXAjax() 
{
  this.InicializaAjax = InicializaAjax;
  this.AcionaAjax = AcionaAjax;
  this.GetCampoXML = GetCampoXML;
  this.CampoFormXML = CampoFormXML;

  // Esta função tem a finalidade de instanciar um objeto de conexão HTTP no contexto JavaScript da página,
  // e guardá-lo na variável global ObjetoHTTP, dando condições ao script de fazer requisições HTTP e
  // tratá-las como for necessário.
  function InicializaAjax()
  {
    this.Resultado = null;
    // Faremos várias tentativas de criar um objeto de comunicação HTTP.
    // Primeiro para browsers como Mozilla, FireFox, Safari, etc.
    if(typeof XMLHttpRequest != 'undefined')
      this.Resultado = new XMLHttpRequest();
    else if (window.ActiveXObject)
    { // Se não der certo, verificamos se o browser suporta objetos ActiveX. Se sim, estamos no IE,
      // e vamos tentar instanciar um objeto HTTP tentando todas as variantes de ActiveX HTTP que a Microsoft já criou.
      // É criado um array com os nomes dos objetos.
      this.VersoesHTTP = ["MSXML2.XMLHttp.5.0", "MSXML2.XMLHttp.4.0",
                         "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp", "Microsoft.XMLHttp"];
      this.NumVersoesHTTP = this.VersoesHTTP.length;
      // Agora faremos um loop pelo array para tentar instanciar cada um deles.
      for (var i=0; i<this.NumVersoesHTTP; i++)
      {
        // Tentamos instanciar.
        // Se der certo, break faz a execução sair do loop. Se der errado, tentamos com o próximo.
        try{ this.Resultado = new ActiveXObject(this.VersoesHTTP[i]); break; } catch (e) {}
      }
    }
    return this.Resultado;
  }

  // Função que executa chamadas Ajax.
  function AcionaAjax(URL, FuncaoCallBack, Objeto)
  {
    //alert(URL);
    this.ObjetoHTTP = this.InicializaAjax();
    if(this.ObjetoHTTP)
    {
      // Carrega o objeto com o endereço da requisição de dados que desejamos fazer.
      // O primeiro parâmetro e o tipo de requisição HTTP.
      // Depois vem a URL a ser chamada. E por fim, true para chamadas assíncronas, e false para síncronas.
      this.ObjetoHTTP.open("GET", URL, true);
      // Setamos agora onreadystatechange, que informa ao objeto qual função de callback ele deve chamar quando a 
      // requisição estiver concluída. A função de callback deve ser implementada de modo a tomar as ações corretas 
      // de acordo com o valor da propriedade readyState do objeto HTTP, que informa o status do objeto, quando usamos
      // o modo assíncrono:
      // 0: O Objeto foi criado mas o método open() não foi chamado ainda.
      // 1: O método open() foi chamado mas a requisição não foi enviada ainda.
      // 2: A requisição foi enviada, aguardando retorno.
      // 3: Uma parte da resposta do servidor foi recebida, mas ainda faltam dados.
      // 4: Toda a informação de retorno já chegou e a conexão foi fechada com sucesso.
      // Apenas os status 0, 1 e 4 são confiáveis entre os diferentes browsers. No status 4, teremos as propriedades
      // status, responseText e statusText populadas no objeto. Devemos checar se status = 200 (sucesso), e então
      // ler os dados de retorno (possivelmente o XML retornado) em responseText. Se houver erro, seu descritivo
      // estará em statusText.
      //alert('fora: '+this);
      this.ObjetoHTTP.onreadystatechange =
      function()
      {
        // Chacamos se o novo status é 4.
        if(this.readyState == 4)
        {
          // Se sim, a requisição foi finalizada. Checaremos então se o status HTTP é 200.
          //alert(ObjetoHTTP.responseText);
          if(this.status == 200)
            // Se sim, significa que a requisição foi completada com sucesso, então podemos suspender o timeout setado
            // anteriormente, e chamar a função de callback. Utilizamos apply para que o escopo da função seja o do Objeto
            // passado. Desta forma, poderemos usar "this" dentro do callback, referenciando diretamente o objeto desejado.
            //cleartimeout(Timeout);
            //FuncaoCallBack(this.responseXML);
            FuncaoCallBack.apply(Objeto, [this.responseXML])
          else if(this.status == 404) 
            alert('A URL informada não foi encontrada:\n"'+URL+'"');
          else if(this.status == 403)
            alert('Acesso negado.');
          else
            alert('Ocorreu um erro na chamada HTTP: '+this.status+' - '+this.statusText);
        }
      }
      // Agora vamos setar um limite de tempo para a execução da chamada. Se o limite estourar, FuncaoTimeout será
      // chamada e a requisição será abortada.
      //Timeout = setTimeout(FuncaoTimeout, LimiteTimeout);
      // Por fim, submete a requisição.
      this.ObjetoHTTP.send('');
    }
  }

  // Função que retorna o valor de um elemento XML dentro do elemento informado.
  // Ela facilita a leitura de dados de uma estrutura XML, fazendo também a checagens de valores nulos/inexistentes.
  function GetCampoXML(Elemento, Valor)
  {
    // Inicializa variável de retorno.
    this.Resultado;
    // Checamos se o elemento procurado existe mesmo.
    if(Elemento.getElementsByTagName(Valor)[0].hasChildNodes())
      // Se existir, ele é lido.
      this.Resultado = Elemento.getElementsByTagName(Valor)[0].childNodes[0].nodeValue;
    else
      // Se não existir, retornamos vazio.
      this.Resultado = '';
    // O valor encontrado é retornado.
    return this.Resultado;
  }

  // Função que preenche um campo do formulário com um valor existente dentro de um elemento XML
  // Ela facilita a colocacão de dados de uma estrutura XML dentro de campos de formulário, fazendo também
  // a checagem de valores nulos/inexistentes.
  function CampoFormXML(Campo, Elemento, Valor)
  {
    CampoForm(Campo, GetCampoXML(Elemento, Valor));
  }
}
