0

My Issue: enter image description here Please help me run this code as it should. I am getting a null form error when typing a City name in the place holder and I'm not sure why I am practicing this code from here: https://webdesign.tutsplus.com/tutorials/build-a-simple-weather-app-with-vanilla-javascript--cms-33893

/*SEARCH BY USING A CITY NAME (e.g. athens) OR A COMMA-SEPARATED CITY NAME ALONG WITH THE COUNTRY CODE (e.g. athens,gr)*/
const form = document.querySelector(".top-banner form");
const input = document.querySelector(".top-banner input");
const msg = document.querySelector(".top-banner .msg");
const list = document.querySelector(".ajax-section .cities");
/*SUBSCRIBE HERE FOR API KEY: https://home.openweathermap.org/users/sign_up*/
const apiKey = "f077e7d6167270fa866a36699ab528fe"; /*REPLACE THIS WITH YOUR API KEY FROM OPENWEATHERMAP.ORG*/

form.addEventListener("submit", e => {
  e.preventDefault();
  let inputVal = input.value;

  //check if there's already a city
  const listItems = list.querySelectorAll(".ajax-section .city");
  const listItemsArray = Array.from(listItems);

  if (listItemsArray.length > 0) {
    const filteredArray = listItemsArray.filter(el => {
      let content = "";
      //athens,gr
      if (inputVal.includes(",")) {
        //athens,grrrrrr->invalid country code, so we keep only the first part of inputVal
        if (inputVal.split(",")[1].length > 2) {
          inputVal = inputVal.split(",")[0];
          content = el
            .querySelector(".city-name span")
            .textContent.toLowerCase();
        } else {
          content = el.querySelector(".city-name").dataset.name.toLowerCase();
        }
      } else {
        //athens
        content = el.querySelector(".city-name span").textContent.toLowerCase();
      }
      return content == inputVal.toLowerCase();
    });

    if (filteredArray.length > 0) {
      msg.textContent = `You already know the weather for ${
            filteredArray[0].querySelector(".city-name span").textContent
          } ...otherwise be more specific by providing the country code as well `;
      form.reset();
      input.focus();
      return;
    }
  }

  //ajax here
  const url = `https://api.openweathermap.org/data/2.5/weather?q=${inputVal}&appid=${apiKey}&units=metric`;

  fetch(url)
    .then(response => response.json())
    .then(data => {
      const {
        main,
        name,
        sys,
        weather
      } = data;
      const icon = `https://s3-us-west-2.amazonaws.com/s.cdpn.io/162656/${
            weather[0]["icon"]
          }.svg`;

      const li = document.createElement("li");
      li.classList.add("city");
      const markup = `
            <h2 class="city-name" data-name="${name},${sys.country}">
              <span>${name}</span>
              <sup>${sys.country}</sup>
            </h2>
            <div class="city-temp">${Math.round(main.temp)}<sup>°C</sup></div>
            <figure>
              <img class="city-icon" src="${icon}" alt="${
            weather[0]["description"]
          }">
              <figcaption>${weather[0]["description"]}</figcaption>
            </figure>
          `;
      li.innerHTML = markup;
      list.appendChild(li);
    })
    .catch(() => {
      msg.textContent = "Please search for a valid city ";
    });

  msg.textContent = "";
  form.reset();
  input.focus();
});
<!DOCTYPE html>
<html>

<head>
  <script src="main.js"></script>
</head>

<body>
  <div class="api">
    <div class="container"> This demo needs an OpenWeather API key to work. <a target="_blank" href="https://home.openweathermap.org/users/sign_up">Get yours here for free!</a>
    </div>
  </div>
  <section class="top-banner">
    <div class="container">
      <h1 class="heading">Simple Weather App</h1>
      <form>
        <input type="text" placeholder="Search for a city" autofocus>
        <button type="submit">SUBMIT</button>
        <span class="msg"></span>
      </form>
    </div>
  </section>
  <section class="ajax-section">
    <div class="container">
      <ul class="cities"></ul>
    </div>
  </section>
  <footer class="page-footer">
    <div class="container">
    </div>
    <small>Made with <span>❤</span> by <a href="http://georgemartsoukos.com/" target="_blank">George Martsoukos</a>
      </small>
    <li class="city">
      <h2 class="city-name" data-name="...">
        <span>...</span>
        <sup>...</sup>
      </h2>
      <span class="city-temp">...<sup>°C</sup></span>
      <figure>
        <img class="city-icon" src="..." alt="...">
        <figcaption>...</figcaption>
      </figure>
    </li>
  </footer>
</body>

</html>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
eddie
  • 35
  • 5

1 Answers1

3

It's because your javascript code is executed before DOM is fully loaded. So you have two choices, either move <script src="main.js"></script> as the last item inside body (before </body>)

or place all your javascript code inside:

document.addEventListener("DOMContentLoaded", e =>
{
// your code here
});
vanowm
  • 9,466
  • 2
  • 21
  • 37