FreeCodeCamp Show the Local Weather

using plain Javascript


Recently I got some time to continue my progress on FreeCodeCamp. My latest project is Show the local Weather. I am going to write how I implemented this project from start to end.

The reason why I do not include any framework or library into this project is understand and learn more about Javascript. It took me a few nights to finish this project since I needed to wrap my head around the Geolocation thing and the API thing. The rest is quite straightforward.

I am not going to write much about design as it is quite straightforward and simple.


The user stories in this project were:

  • Users can see their current location.
  • Users can see a different icon or background image (e.g. snowy mountain, hot desert) depending on the weather.
  • Users can push a button to toggle between Fahrenheit and Celsius.

The steps in this project were:

  • Use HTML5 Geolocation to get user location
  • Use the location data from above to fetch weather data from freeCodeCamp Weather API https://fcc-weather-api.glitch.me (I took advantage of fetch API)
  • Update the data from API to the UI
  • Create a function to handle the toggle between Fahrenheit and Celsius

First thing first, the HTML structure

<div class="container">
<div class="title">Weather App</div>
<div class="subtitle">Free code camp</div>
<div class="weather-info">
<div id="location" class="info"></div>
<div id="temperature" class="info">
<span id="temperature-num"></span>
<span>°</span>
<span id="temperature-scale">C</span>
</div>
<div id="weather-condition" class="info"></div>
<div id="weather-icon" class="info"></div>
</div>
</div>

My initial temperature scale is Celsius, so I put “C” into HTML to make it easy.

Next, we are going to deal with JS.

First, I declared some variables to get the DOM nodes

const loc = document.getElementById("location");
const temNum = document.getElementById("temperature-num");
const temScale = document.getElementById("temperature-scale");
const weatherCon = document.getElementById("weather-condition");
const weatherIcon = document.getElementById("weather-icon");

Next, I got user current location using HTML5 Geolocation before fetching data from API

// get location
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(position => {
getWeather(position.coords.latitude, position.coords.longitude);
});
} else {
loc.innerHTML = "Geolocation is not supported by this browser.";
}
}

After having the user current location, I executed an API request using fetch API, if the call was successful, then it would updated the data to the DOM. If it failed, it would caught the error and printed it out. I am not going discuss how the fetch API works in this article since it is all over the internet.

// get weather data according to the location
function getWeather(lat, long) {
const root = "https://fcc-weather-api.glitch.me/api/current?";
fetch(`${root}lat=${lat}&lon=${long}`, { method: "get" })
.then(resp => resp.json())
.then(data => {
updateDataToUI(data.name, data.weather, data.main.temp);
})
.catch(function(err) {
console.error(err);
});
}

The sample response looks like this

Response: { "coord":{ "lon":159, "lat":35 }, "weather":[ { "id":500, "main":"Rain", "description":"light rain", "icon":"https://cdn.glitch.com/6e8889e5-7a72-48f0-a061-863548450de5%2F10n.png?1499366021399" } ], "base":"stations", "main":{ "temp":22.59, "pressure":1027.45, "humidity":100, "temp_min":22.59, "temp_max":22.59, "sea_level":1027.47, "grnd_level":1027.45 }, "wind":{ "speed":8.12, "deg":246.503 }, "rain":{ "3h":0.45 }, "clouds":{ "all":92 }, "dt":1499521932, "sys":{ "message":0.0034, "sunrise":1499451436, "sunset":1499503246 }, "id":0, "name":"", "cod":200 }

At this step, I created a function to overwrite the data into the DOM.

// update the data from API to DOM
function updateDataToUI(location, weather, temp) {
weatherIcon.innerHTML = `<img src="${weather[0].icon}" />`;
weatherCon.innerHTML = weather[0].main;
loc.innerHTML = location;
temNum.innerHTML = `${temp}`;
}

Since I did not use all the data from API, so I only inputted which data I need as params into the function.

At this point, to make it work, simply called the first function

window.onload = function() {
getLocation();
};

So I got location, weather condition, weather icon and temperature to show on the DOM.

So far it looks like this

First load

Next step is to create a function to handle the toggle between Fahrenheit and Celsius.

First of all, I created two small functions to help convert between these two scale

// helper function change from C to F
function cToF(celsius) {
return celsius * 9 / 5 + 32;
}
// helper function: change from F to C
function fToC(fahrenheit) {
return (fahrenheit - 32) * 5 / 9;
}

Next one is the handle function. In this function, it will look into the scale letter, if it is C then convert the temperature into F and vice versa. Oh and I rounded it up to two decimals with toFixed.

function toggleScale() {
if (temScale.innerHTML === "C") {
temNum.innerHTML = cToF(temNum.innerHTML).toFixed(2);
temScale.innerHTML = "F";
} else if (temScale.innerHTML === 'F') {
temNum.innerHTML = fToC(temNum.innerHTML).toFixed(2);
temScale.innerHTML = "C";
}
}

The function will be triggered every time user click on the temperature scale. Therefore, an EventListener is needed in this case

// toggle the temperature scale
temScale.addEventListener("click", toggleScale);
After toggling

That was how I created the local weather app. I am currently working on the next project which is the Wikipedia Viewer. I think I will use React to on the next project.

Thanks for reading.