da2k / curso-javascript-ninja

Curso Javascript Ninja
http://blog.da2k.com.br/curso-javascript-ninja/
2.35k stars 2.94k forks source link

[Aula 29] API não funciona #10232

Closed anarsantos closed 10 months ago

anarsantos commented 10 months ago

Oi, Fernando!

Copiei o link que você indicou no vídeo 172: "Guarde esse link para usar na hora da solução do desafio 28: https://apicep.com/api-de-consulta/"

Mas, contudo, entretanto, todavia não está funcionando:

image

image

Fiz como você indicou no vídeo, acho eu rs, tenho que trocar apenas o link da API? Onde consigo um que funcione?

@fdaciuk

fdaciuk commented 10 months ago

Oi @anarsantos! Esse link é apenas para a documentação da API =) Se você clicar nele, vai ver que lá mostra a URL que você vai usar para consultar um CEP, e o formato do objeto retornado :D

anarsantos commented 10 months ago

Eu coloquei a url que está nesse site, mas também continua com erro. Não mostra como no vídeo.

image

image

fdaciuk commented 10 months ago

É que o CEP é dinâmico.. ali na URL tem o [cep] que deve ser substituído pelo CEP que você quer buscar =)

fdaciuk commented 10 months ago

Fiz um teste rápido aqui, e parece que a API não está respondendo como deveria, ainda passando o CEP corretamente. Vou fazer mais alguns testes e volto em breve com uma solução, ok? :D

fdaciuk commented 10 months ago

É, parece que essa API realmente está com problemas 😞 Normal, existem outras opções =)

Vou atualizar o local onde eu indiquei essa API para usar o Via CEP. Pode usar essa por enquanto que está funcionando corretamente: https://viacep.com.br/

anarsantos commented 10 months ago

Coloquei como o senhor falou e não funcionou :( Não aparece como na última imagem que coloquei abaixo que você mostra no vídeo. Com esse link deveria aparecer como no seu vídeo né, que mesmo sem CEP ao clicar em "Consultar CEP" aparece: "Carregando..."?

image

image

image

fdaciuk commented 10 months ago

Essa URL também é só para a documentação =) Lá na página ele mostra a URL que você deve usar para fazer a requisição =)

fdaciuk commented 10 months ago

Obs.: Eu não estou dando a resposta final de propósito, ok? É importante acostumar a tentar procurar um pouco com base nas informações que você tem :D

anarsantos commented 10 months ago

Então, mas eu não sei se estou certa, porque ainda estou no vídeo 175 parte 2. Não tenho todo código e quando testo não fica igual ao seu. A parte do "Carregando... Popular fomulário...." não aparece. Eu coloquei a url do site e agora está assim, não sei se está certo até aqui?

O senhor poderia me dizer por que não aparece a mensagem como no seu?

image

anarsantos commented 10 months ago

Finalizei o vídeo 175, mas o erro continua aparecendo. Diz que é no ajax.send(), mas não entendi. Está igual ao seu.

image

(function () {
  'use strict';
  /*
    No HTML:
    - Crie um formulário com um input de texto que receberá um CEP e um botão
    de submit;
    - Crie uma estrutura HTML para receber informações de endereço:
    "Logradouro, Bairro, Estado, Cidade e CEP." Essas informações serão
    preenchidas com os dados da requisição feita no JS.
    - Crie uma área que receberá mensagens com o status da requisição:
    "Carregando, sucesso ou erro."

    No JS:
    - O CEP pode ser entrado pelo usuário com qualquer tipo de caractere, mas
    deve ser limpo e enviado somente os números para a requisição abaixo;
    - Ao submeter esse formulário, deve ser feito um request Ajax para a URL:
    "https://viacep.com.br/ws/[CEP]/json/", onde [CEP] será o CEP passado
    no input criado no HTML;
    - Essa requisição trará dados de um CEP em JSON. Preencha campos na tela
    com os dados recebidos.
    - Enquanto os dados são buscados, na área de mensagens de status, deve mostrar
    a mensagem: "Buscando informações para o CEP [CEP]..."
    - Se não houver dados para o CEP entrado, mostrar a mensagem:
    "Não encontramos o endereço para o CEP [CEP]."
    - Se houver endereço para o CEP digitado, mostre a mensagem:
    "Endereço referente ao CEP [CEP]:"
    - Utilize a lib DOM criada anteriormente para facilitar a manipulação e
    adicionar as informações em tela.
    */
    function DOM(elements) {
      this.element = document.querySelectorAll(elements);
    }

    DOM.prototype.on = function on(eventType, callback) {
      Array.prototype.forEach.call(this.element, function (element) {
        element.addEventListener(eventType, callback, false);
      });
    };

    DOM.prototype.off = function off(eventType, callback) {
      Array.prototype.forEach.call(this.element, function (element) {
        element.removeEventListener(eventType, callback, false);
      });
    };

    DOM.prototype.get = function get() {
      return this.element;
    };

    //forEach, map, filter, reduce, reduceRight, every e some.
    DOM.prototype.forEach = function forEach() {
      return Array.prototype.forEach.apply(this.element, arguments);
    };

    DOM.prototype.map = function map() {
      return Array.prototype.map.apply(this.element, arguments);
    };

    DOM.prototype.filter = function filter() {
      return Array.prototype.filter.apply(this.element, arguments);
    };

    DOM.prototype.reduce = function reduce() {
      return Array.prototype.reduce.apply(this.element, arguments);
    };

    DOM.prototype.reduceRight = function reduceRight() {
      return Array.prototype.reduceRight.apply(this.element, arguments);
    };

    DOM.prototype.every = function every() {
      return Array.prototype.every.apply(this.element, arguments);
    };

    DOM.prototype.some = function some() {
      return Array.prototype.some.apply(this.element, arguments);
    };

    //isArray, isObject, isFunction, isNumber, isString, isBoolean, isNull.
    DOM.prototype.isArray = function isArray(param) {
      return Object.prototype.toString.call(param) === '[object Array]';
    };

    DOM.prototype.isObject = function isObject(param) {
      return Object.prototype.toString.call(param) === '[object Object]';
    };

    DOM.prototype.isFunction = function isFunction(param) {
      return Object.prototype.toString.call(param) === '[object Function]';
    };

    DOM.prototype.isNumber = function isNumber(param) {
      return Object.prototype.toString.call(param) === '[object Number]';
    };

    DOM.prototype.isString = function isString(param) {
      return Object.prototype.toString.call(param) === '[object String]';
    };

    DOM.prototype.isBoolean = function isBoolean(param) {
      return Object.prototype.toString.call(param) === '[object Boolean]';
    };

    DOM.prototype.isNull = function isNull(param) {
      return Object.prototype.toString.call(param) === '[object Null]' || Object.prototype.toString.call(param) === '[object undefined]';
    };

    var $formCEP = new DOM('[data-js="form-cep"]');
    var $inputCEP = new DOM ('[data-js="input-cep"]');
    $formCEP.on('submit', handleSubmitFormCEP); //função callback
    var ajax = new XMLHttpRequest();

    function handleSubmitFormCEP(event) {
      event.preventDefault();
      console.log($inputCEP.get()[0].value);
      var url = 'viacep.com.br/ws/json/'.replace('[CEP]', $inputCEP.get()[0].value);
      ajax.open('GET', url);
      ajax.send();
      ajax.addEventListener('readystatechange', handleReadyStateChange);
    }

    function handleReadyStateChange() {
      if(ajax.readyState === 4 && ajax.status === 200) {
        console.log('Popular formulário', ajax.responseText);
      }
      console.log('Carregando...');
    }

})();
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>CEP</title>
</head>
<body>
  <form  data-js="form-cep">
    <input type="text" data-js="input-cep">
    <button type="submit">Consultar CEP</button>
  </form>

  <div data-js="status"></div>

  <div data-js="cep-info">
    <p><strong>Logradouro:</strong> <span data-js="logradouro"></span></p>
    <p><strong>Bairro:</strong> <span data-js="bairro"></span></p>
    <p><strong>Estado:</strong> <span data-js="estado"></span></p>
    <p><strong>Cidade:</strong> <span data-js="cidade"></span></p>
    <p><strong>CEP:</strong> <span data-js="cep"></span></p>
  </div>

  <script src="challenge-28.js"></script>
</body>
</html>
fdaciuk commented 10 months ago

O problema parece ser só na URL. Se você perceber, a request tá sendo feita para essa URL:

http://127.0.0.1:5500/challenge-28/viacep.com.br/ws/json/

O request deveria ser feito para a URL do viacep.com.br, não para 127.0.0.1, que é o caminho do seu servidor local.

Isso acontece porque, na URL do viacep, faltou o https://. Isso é meio implícito, mas realmente faltou adicionarem lá na documentação =)

Quando você não coloca o protocolo na URL (https://), o browser entende que aquele request é para um endpoint local, não para um domínio completamente diferente.

No seu exemplo faltou também passar o CEP ali logo depois do /ws, como está lá na doc do ViaCEP.

Olhando o código, ali onde você definiu a variável url, você tenta fazer um replace na string [CEP], mas essa string não existe na URL, ali você precisa adicionar manualmente depois do /ws/, senão o replace será ignorado e a string anterior vai ser retornada (que é a URL sem o CEP) :D

Fazendo essas alterações, tudo deve funcionar como esperado =)

anarsantos commented 10 months ago

Quantos erros, senhor! É bom para eu ficar atenta. Fiquei com o link que você tinha passado na aula na cabeça e não me atentei aos detalhes do "https://" e o CEP que não estava na url. Muito obrigada pela explicação.

fdaciuk commented 10 months ago

Sem problemas! Tem coisas que a gente vai percebendo com o tempo mesmo. Continue estudando e praticando, que encontrar problemas assim vai começar a se tornar cada vez mais fácil =)

anarsantos commented 10 months ago

Tô esperando esse momento de ficar mais fácil, parece que ele não vai chegar nunca😭. Finalizei a parte 4, mas eu não consegui exibir "Não encontramos o endereço para o CEP [CEP]."

Vi a aula algumas vezes e não consegui encontrar onde errei no código. Coloquei um CEP inválido e não mostrou a mensagem correta.

image

(function () {
  'use strict';
  /*
    No HTML:
    - Crie um formulário com um input de texto que receberá um CEP e um botão
    de submit;
    - Crie uma estrutura HTML para receber informações de endereço:
    "Logradouro, Bairro, Estado, Cidade e CEP." Essas informações serão
    preenchidas com os dados da requisição feita no JS.
    - Crie uma área que receberá mensagens com o status da requisição:
    "Carregando, sucesso ou erro."

    No JS:
    - O CEP pode ser entrado pelo usuário com qualquer tipo de caractere, mas
    deve ser limpo e enviado somente os números para a requisição abaixo;
    - Ao submeter esse formulário, deve ser feito um request Ajax para a URL:
    "https://viacep.com.br/ws/[CEP]/json/", onde [CEP] será o CEP passado
    no input criado no HTML;
    - Essa requisição trará dados de um CEP em JSON. Preencha campos na tela
    com os dados recebidos.
    - Enquanto os dados são buscados, na área de mensagens de status, deve mostrar
    a mensagem: "Buscando informações para o CEP [CEP]..."
    - Se não houver dados para o CEP entrado, mostrar a mensagem:
    "Não encontramos o endereço para o CEP [CEP]."
    - Se houver endereço para o CEP digitado, mostre a mensagem:
    "Endereço referente ao CEP [CEP]:"
    - Utilize a lib DOM criada anteriormente para facilitar a manipulação e
    adicionar as informações em tela.
    */
  function DOM(elements) {
    this.element = document.querySelectorAll(elements);
  }

  DOM.prototype.on = function on(eventType, callback) {
    Array.prototype.forEach.call(this.element, function (element) {
      element.addEventListener(eventType, callback, false);
    });
  };

  DOM.prototype.off = function off(eventType, callback) {
    Array.prototype.forEach.call(this.element, function (element) {
      element.removeEventListener(eventType, callback, false);
    });
  };

  DOM.prototype.get = function get() {
    return this.element;
  };

  //forEach, map, filter, reduce, reduceRight, every e some.
  DOM.prototype.forEach = function forEach() {
    return Array.prototype.forEach.apply(this.element, arguments);
  };

  DOM.prototype.map = function map() {
    return Array.prototype.map.apply(this.element, arguments);
  };

  DOM.prototype.filter = function filter() {
    return Array.prototype.filter.apply(this.element, arguments);
  };

  DOM.prototype.reduce = function reduce() {
    return Array.prototype.reduce.apply(this.element, arguments);
  };

  DOM.prototype.reduceRight = function reduceRight() {
    return Array.prototype.reduceRight.apply(this.element, arguments);
  };

  DOM.prototype.every = function every() {
    return Array.prototype.every.apply(this.element, arguments);
  };

  DOM.prototype.some = function some() {
    return Array.prototype.some.apply(this.element, arguments);
  };

  //isArray, isObject, isFunction, isNumber, isString, isBoolean, isNull.
  DOM.prototype.isArray = function isArray(param) {
    return Object.prototype.toString.call(param) === '[object Array]';
  };

  DOM.prototype.isObject = function isObject(param) {
    return Object.prototype.toString.call(param) === '[object Object]';
  };

  DOM.prototype.isFunction = function isFunction(param) {
    return Object.prototype.toString.call(param) === '[object Function]';
  };

  DOM.prototype.isNumber = function isNumber(param) {
    return Object.prototype.toString.call(param) === '[object Number]';
  };

  DOM.prototype.isString = function isString(param) {
    return Object.prototype.toString.call(param) === '[object String]';
  };

  DOM.prototype.isBoolean = function isBoolean(param) {
    return Object.prototype.toString.call(param) === '[object Boolean]';
  };

  DOM.prototype.isNull = function isNull(param) {
    return Object.prototype.toString.call(param) === '[object Null]' || Object.prototype.toString.call(param) === '[object undefined]';
  };

  var $formCEP = new DOM('[data-js="form-cep"]');
  var $inputCEP = new DOM('[data-js="input-cep"]');
  var $logradouro = new DOM('[data-js="logradouro"]');
  var $bairro = new DOM('[data-js="bairro"]');
  var $estado = new DOM('[data-js="estado"]');
  var $cidade = new DOM('[data-js="cidade"]');
  var $cep = new DOM('[data-js="cep"]');
  var $status = new DOM('[data-js="status"]');
  var ajax = new XMLHttpRequest();
  $formCEP.on('submit', handleSubmitFormCEP); //função callback

  function handleSubmitFormCEP(event) {
    event.preventDefault();
    var url = getUrl();
    ajax.open('GET', url);
    ajax.send();
    getMessage('loading');
    ajax.addEventListener('readystatechange', handleReadyStateChange);
  }

  function getUrl() {
    return replaceCEP('https://viacep.com.br/ws/[CEP]/json/');
  }

  function clearCEP() {
    return $inputCEP.get()[0].value.replace(/\D+/g, '');//o que não for n° vai trocar por string em branco
  }

  function handleReadyStateChange() {
    if (isRequestOk()) {
      getMessage('ok');
      fillCEPFields();//função para preencher os dados da request
    }
  }

  function isRequestOk() {
    return ajax.readyState === 4 && ajax.status === 200;
  }

  function fillCEPFields() {
    var data = parseData();
    if (!data) {
      getMessage('error');
      data = clearData();
    }

    $logradouro.get()[0].textContent = data.logradouro;
    $bairro.get()[0].textContent = data.bairro;
    $estado.get()[0].textContent = data.uf;
    $cidade.get()[0].textContent = data.localidade;
    $cep.get()[0].textContent = data.cep;
  }

  function clearData() {
    return {
      logradouro: '-',
      bairro: '-',
      uf: '-',
      localidade: '-',
      cep: '-'
    }
  }

  function parseData() {
    var result;
    try {
      result = JSON.parse(ajax.responseText);
    }
    catch (e) {
      result = null;
    }
    return result;
  }

  function getMessage(type) {
    var messages = {
      loading: replaceCEP('Buscando informações para o CEP [CEP]...'),
      ok: replaceCEP('Endereço referente ao CEP [CEP]:'),
      error: replaceCEP('Não encontramos o endereço para o CEP [CEP].')
    };
    $status.get()[0].textContent = messages[type];
    /*return { //outra forma de fazer
      loading: 'Buscando informações para o CEP [CEP]...',
      ok: 'Endereço referente ao CEP [CEP]:',
      error: 'Não encontramos o endereço para o CEP [CEP].'
    }[type];*/
  }

  function replaceCEP(message) {
    return message.replace('[CEP]', clearCEP());
  }
})();
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>CEP</title>
</head>
<body>
  <form  data-js="form-cep">
    <input type="text" data-js="input-cep">
    <button type="submit">Consultar CEP</button>
  </form>

  <div>
    <h2 data-js="status"></h2>
  </div>

  <div data-js="cep-info">
    <p><strong>Logradouro:</strong> <span data-js="logradouro"></span></p>
    <p><strong>Bairro:</strong> <span data-js="bairro"></span></p>
    <p><strong>Estado:</strong> <span data-js="estado"></span></p>
    <p><strong>Cidade:</strong> <span data-js="cidade"></span></p>
    <p><strong>CEP:</strong> <span data-js="cep"></span></p>
  </div>

  <script src="challenge-28.js"></script>
</body>
</html>
fdaciuk commented 10 months ago

Vai chegar sim, não desista!

Sobre a mensagem de erro, o que acontece é que essa API é um pouco diferente: ao invés dela retornar um status diferente de 200 para requisições com sucesso, ela continua retornando 200, mas no objeto de resultado vem uma propriedade error com valor true.

Não é o padrão recomendado para usar com HTTP, mas é como a API funciona, infelizmente.

Então o que você precisa fazer é verificar na função isRequestOk se existe essa propriedade error com o valor true. Se não existir, quer dizer que o resultado veio certo. Se existir, aí quer dizer que deu erro =)

anarsantos commented 10 months ago

Espero senhor chegar, valeu pelo apoio :)

Seu Fernando onde está esse tal objeto com a propriedade error valor true?

Essa última parte não entendi bem como fazer "verificar se a função isRequestOk existe essa propriedade error com o valor true. Se não existir, quer dizer que o resultado deu certo."?

anarsantos commented 10 months ago

Outra pergunta, no próximo vídeo 178, você melhora o código feito até aqui. Como eu faria para colocar em uma branch diferente?

Seria: git checkout -b challenge-28-II, por exemplo? Assim criaria uma branch no GitHub?

fdaciuk commented 10 months ago

Seu Fernando onde está esse tal objeto com a propriedade error valor true?

Esse é o valor que vem no ajax.responseText, que você usa lá na função parseData =)

Mas assim.. essa API dá dois erros diferentes, na verdade:

Não sei se você chegou a olhar a solução final do código desse desafio, mas lá eu mostrei como tratar esses dois erros: https://github.com/da2k/curso-javascript-ninja/blob/desafios-resolvidos/challenge-28/challenge-28.js

fdaciuk commented 10 months ago

Sobre a outra dúvida: sim, você pode criar uma branch nova, mas eu recomendaria você deixar na mesma branch, só criando um commit diferente. Aí você pode consultar depois pelo histórico de commits no GitHub, se quiser ver a solução anterior =)

fdaciuk commented 10 months ago

Ah, mais um detalhe: nessa linha você esqueceu de executar a função isRequestOk =)

anarsantos commented 10 months ago

Seu Fernando onde está esse tal objeto com a propriedade error valor true?

Esse é o valor que vem no ajax.responseText, que você usa lá na função parseData =)

Mas assim.. essa API dá dois erros diferentes, na verdade:

  • Quando um CEP é inválido (quantidade de números diferente de 8), o status vem como 0
  • Quando um CEP é válido, mas não foi encontrado, ele retorna o ajax.status como 200, mas no ajax.responseText vem um JSON assim: {"erro": true}

Não sei se você chegou a olhar a solução final do código desse desafio, mas lá eu mostrei como tratar esses dois erros: https://github.com/da2k/curso-javascript-ninja/blob/desafios-resolvidos/challenge-28/challenge-28.js

Legal, vou olhar a solução final, mas eu queria saber como vejo esses erros nesses lugares mirabolantes que você está falando rs, às vezes, você fala parace que tá falando grego rs, sou inciante e não entendo muito bem. Como faço para ver "o valor que vem no ajax.responseText"?

anarsantos commented 10 months ago

Sobre a outra dúvida: sim, você pode criar uma branch nova, mas eu recomendaria você deixar na mesma branch, só criando um commit diferente. Aí você pode consultar depois pelo histórico de commits no GitHub, se quiser ver a solução anterior =)

Ok, senhor! Seguirei sua recomendação. rs

anarsantos commented 10 months ago

Ah, mais um detalhe: nessa linha você esqueceu de executar a função isRequestOk =)

Vi ontem em algum momento à tarde, depois de olhar o código um milhão de vezes para ver se exibia a frase do error. Vou ver a solução final e arrumar meu código.

Só mais uma dúvida que surgiu agora, essa solução final vem antes da arrumação que o senhor fez na aula 178. Module Pattern?

anarsantos commented 10 months ago

Senhor, acabo de arrumar o código e daí deu bom. Agora consegui entender o que você estava falando, com o meu código do jeito que estava não dava para visualizar no "Preview" error valor true.

image

image

anarsantos commented 10 months ago

Tá difícil viu. Agora ele só mostra a mensagem de erro😭. Tudo que eu queria era terminar o curso em paz. Depois que arrumei o código conforme o link que você mandou e fiz a aula do Module Pattern e pé do frango azedou de vez.

image

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>CEP</title>
</head>
<body>
  <form  data-js="form-cep">
    <input type="text" data-js="input-cep">
    <button type="submit">Consultar CEP</button>
  </form>

  <div>
    <h2 data-js="status"></h2>
  </div>

  <div data-js="cep-info">
    <p><strong>Logradouro:</strong> <span data-js="logradouro"></span></p>
    <p><strong>Bairro:</strong> <span data-js="bairro"></span></p>
    <p><strong>Estado:</strong> <span data-js="estado"></span></p>
    <p><strong>Cidade:</strong> <span data-js="cidade"></span></p>
    <p><strong>CEP:</strong> <span data-js="cep"></span></p>
  </div>

  <script src="dom.js"></script>
  <script src="challenge-28.js"></script>
</body>
</html>
(function(win, document) {
  'use strict';

  function DOM(elements) {
    this.element = document.querySelectorAll(elements);
  }

  DOM.prototype.on = function on(eventType, callback) {
    Array.prototype.forEach.call(this.element, function (element) {
      element.addEventListener(eventType, callback, false);
    });
  };

  DOM.prototype.off = function off(eventType, callback) {
    Array.prototype.forEach.call(this.element, function (element) {
      element.removeEventListener(eventType, callback, false);
    });
  };

  DOM.prototype.get = function get() {
    return this.element;
  };

  //forEach, map, filter, reduce, reduceRight, every e some.
  DOM.prototype.forEach = function forEach() {
    return Array.prototype.forEach.apply(this.element, arguments);
  };

  DOM.prototype.map = function map() {
    return Array.prototype.map.apply(this.element, arguments);
  };

  DOM.prototype.filter = function filter() {
    return Array.prototype.filter.apply(this.element, arguments);
  };

  DOM.prototype.reduce = function reduce() {
    return Array.prototype.reduce.apply(this.element, arguments);
  };

  DOM.prototype.reduceRight = function reduceRight() {
    return Array.prototype.reduceRight.apply(this.element, arguments);
  };

  DOM.prototype.every = function every() {
    return Array.prototype.every.apply(this.element, arguments);
  };

  DOM.prototype.some = function some() {
    return Array.prototype.some.apply(this.element, arguments);
  };

  //isArray, isObject, isFunction, isNumber, isString, isBoolean, isNull.
  DOM.prototype.isArray = function isArray(param) {
    return Object.prototype.toString.call(param) === '[object Array]';
  };

  DOM.prototype.isObject = function isObject(param) {
    return Object.prototype.toString.call(param) === '[object Object]';
  };

  DOM.prototype.isFunction = function isFunction(param) {
    return Object.prototype.toString.call(param) === '[object Function]';
  };

  DOM.prototype.isNumber = function isNumber(param) {
    return Object.prototype.toString.call(param) === '[object Number]';
  };

  DOM.prototype.isString = function isString(param) {
    return Object.prototype.toString.call(param) === '[object String]';
  };

  DOM.prototype.isBoolean = function isBoolean(param) {
    return Object.prototype.toString.call(param) === '[object Boolean]';
  };

  DOM.prototype.isNull = function isNull(param) {
    return Object.prototype.toString.call(param) === '[object Null]' || Object.prototype.toString.call(param) === '[object undefined]';
  };

  win.DOM = DOM; //Propriedade DOM no objeto window que recebe a lib DOM.
})(window, document);

(function (DOM) {
  'use strict';
  /*
    No HTML:
    - Crie um formulário com um input de texto que receberá um CEP e um botão
    de submit;
    - Crie uma estrutura HTML para receber informações de endereço:
    "Logradouro, Bairro, Estado, Cidade e CEP." Essas informações serão
    preenchidas com os dados da requisição feita no JS.
    - Crie uma área que receberá mensagens com o status da requisição:
    "Carregando, sucesso ou erro."

    No JS:
    - O CEP pode ser entrado pelo usuário com qualquer tipo de caractere, mas
    deve ser limpo e enviado somente os números para a requisição abaixo;
    - Ao submeter esse formulário, deve ser feito um request Ajax para a URL:
    "https://viacep.com.br/ws/[CEP]/json/", onde [CEP] será o CEP passado
    no input criado no HTML;
    - Essa requisição trará dados de um CEP em JSON. Preencha campos na tela
    com os dados recebidos.
    - Enquanto os dados são buscados, na área de mensagens de status, deve mostrar
    a mensagem: "Buscando informações para o CEP [CEP]..."
    - Se não houver dados para o CEP entrado, mostrar a mensagem:
    "Não encontramos o endereço para o CEP [CEP]."
    - Se houver endereço para o CEP digitado, mostre a mensagem:
    "Endereço referente ao CEP [CEP]:"
    - Utilize a lib DOM criada anteriormente para facilitar a manipulação e
    adicionar as informações em tela.
    */

  function app() {
    var $formCEP = new DOM('[data-js="form-cep"]');
    var $inputCEP = new DOM('[data-js="input-cep"]');
    var $logradouro = new DOM('[data-js="logradouro"]');
    var $bairro = new DOM('[data-js="bairro"]');
    var $estado = new DOM('[data-js="estado"]');
    var $cidade = new DOM('[data-js="cidade"]');
    var $cep = new DOM('[data-js="cep"]');
    var $status = new DOM('[data-js="status"]');
    var ajax = new XMLHttpRequest();
    $formCEP.on('submit', handleSubmitFormCEP); //função callback

    function handleSubmitFormCEP(event) {
      event.preventDefault();
      var url = getUrl();
      ajax.open('GET', url, true);
      ajax.send();
      getMessage('loading');
      ajax.addEventListener('readystatechange', handleReadyStateChange);
    }

    function getUrl() {
      return replaceCEP('https://viacep.com.br/ws/[CEP]/json/');
    }

    function clearCEP() {
      return $inputCEP.get()[0].value.replace(/\D+/g, '');//o que não for n° vai trocar por string em branco
    }

    function handleReadyStateChange() {
      if (isRequestOk()) {
        getMessage('ok');
        fillCEPFields();//função para preencher os dados da request
      }

      if (isCepInvalid) {
        getMessage('error');
      }
    }

    function isRequestOk() {
      return ajax.readyState === 4 && ajax.status === 200;
    }

    function isCepInvalid() {
      return ajax.readyState === 4 && ajax.status === 0;
    }

    function fillCEPFields() {
      var data = parseData();
      if (!data) {
        getMessage('error');
        data = clearData();
      }

      $logradouro.get()[0].textContent = data.logradouro;
      $bairro.get()[0].textContent = data.bairro;
      $estado.get()[0].textContent = data.uf;
      $cidade.get()[0].textContent = data.localidade;
      $cep.get()[0].textContent = data.cep;
    }

    function clearData() {
      return {
        logradouro: '-',
        bairro: '-',
        uf: '-',
        localidade: '-',
        cep: '-'
      };
    }

    function parseData() {
      var result = JSON.parse(ajax.responseText);
      return result.erro ? null : result;
    }

    function getMessage(type) {
      var messages = {
        loading: 'Buscando informações para o CEP [CEP]...',
        ok: 'Endereço referente ao CEP [CEP]:',
        error: 'Não encontramos o endereço para o CEP [CEP].'
      };
      $status.get()[0].textContent = replaceCEP(messages[type]);
      /*return { //outra forma de fazer
        loading: 'Buscando informações para o CEP [CEP]...',
        ok: 'Endereço referente ao CEP [CEP]:',
        error: 'Não encontramos o endereço para o CEP [CEP].'
      }[type];*/
    }

    function replaceCEP(message) {
      return message.replace('[CEP]', clearCEP());
    }
  }

  app();

})(window.DOM);
fdaciuk commented 10 months ago

Legal, vou olhar a solução final, mas eu queria saber como vejo esses erros nesses lugares mirabolantes que você está falando rs, às vezes, você fala parace que tá falando grego rs, sou inciante e não entendo muito bem. Como faço para ver "o valor que vem no ajax.responseText"?

Sem problemas! Tudo o que você não entender, pode perguntar :D Mas se você olhar na função parseData, por exemplo, você faz o JSON.parse da resposta da request, certo? Essa resposta vem no objeto ajax.responseText. Então ali nessa função, por exemplo, você pode colocar um console.log para ver o que está vindo nessa variável.

Você também consegue ver isso à partir da aba Network do seu navegador, como você mandou ali no print. Essa aba mostra todas as informações do request, quando você clica na linha correspondente ao request =)


Só mais uma dúvida que surgiu agora, essa solução final vem antes da arrumação que o senhor fez na aula 178. Module Pattern?

Isso mesmo. A aula 178 não faz parte da resolução do desafio da aula 28 =)


Tá difícil viu. Agora ele só mostra a mensagem de erro😭. Tudo que eu queria era terminar o curso em paz. Depois que arrumei o código conforme o link que você mandou e fiz a aula do Module Pattern e pé do frango azedou de vez.

O código do seu repositório está atualizado? Que aí eu baixo aqui e faço o teste local pra entender onde está o problema =)

anarsantos commented 10 months ago

Não, só está a parte 4 da resolução do desafio.

anarsantos commented 10 months ago

Subi agora da aula 178.

anarsantos commented 10 months ago

Fernando, uma dúvida. Dá para fazer as próximas aulas mesmo aparendo essa mensagem errada? Hoje eu não fiz as aulas seguintes porque achei que não desse para finalizar os exercícios seguintes.

fdaciuk commented 10 months ago

Oi @anarsantos! Desculpe, o dia foi corrido ontem, não consegui responder =)

Dá para fazer as próximas aulas mesmo aparendo essa mensagem errada?

O ideal é tentar resolver antes, só pra não ficar pendência, porque algumas aulas vão usar códigos de aulas anteriores. Me dá uns minutinhos que vou olhar o seu código, já te retorno aqui =)

anarsantos commented 10 months ago

Beleza, Fernando! Só pra saber ;) Obrigada pela ajuda.

fdaciuk commented 10 months ago

Oi @anarsantos! Baixei aqui seu código pra testar, e ele está certinho, só faltou um detalhe: nessa função, primeiro você faz um if para verificar se o request está ok. Se estiver, você mostra a mensagem de sucesso e preenche os dados do endereço.

E logo depois tem outro if que verifica se o CEP é inválido, para mostrar a mensagem de erro.

Em teoria, não deveria nunca executar os dois ifs, mas é o que está acontecendo. Se os dois ifs executam, é porque o valor passado para os dois está retornando true, concorda?

O problema está no segundo if. É um detalhe que você já esqueceu antes, e está esquecendo de novo aqui. Vou deixar pra você resolver essa, tenho certeza que você vai saber qual é o problema dessa vez :D

anarsantos commented 10 months ago

Como assim estou errando de novo! rs Eu não lembro desse erro em outro momento rs

anarsantos commented 10 months ago

O senhor poderia muito bem ter falado: é um problema no parênteses. Que custava! Aff quanta maldade no coração rs. Mas a culpa é sempre do professor rs. Odeio parênteses afff

fdaciuk commented 10 months ago

Eu sabia que vc iria descobrir haha :D

anarsantos commented 10 months ago

Depois de muitos BOs finalmente consegui terminar essa aula. Juro que só quero terminar o curso o mais rápido possível. Mas os links não funcionam e eu fico cometendo o mesmo erro a todo momento rs. Vou tentar não incomodá-lo mais. ;)

fdaciuk commented 10 months ago

Boa! E é pra incomodar sim! Sempre que precisar, estou aqui pra ajudar =)