[Solved] Forecaster App with Firebase (Async Programming Task)

  

3
Topic starter

Write a JS program that requests a weather report from a server and displays it to the user. Use the following HTML to test your code:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Forecatser</title>
  <style>
    #content { width: 400px; }
    #request { text-align: center; }
    .bl { width: 300px; }
    #current { text-align: center; font-size: 2em; }
    #upcoming { text-align: center; }
    .condition { text-align: left; display: inline-block; }
    .symbol { font-size: 4em; display: inline-block; }
    .forecast-data { display: block; }
    .upcoming { display: inline-block; margin: 1.5em; }
    .label { margin-top: 1em; font-size: 1.5em; background-color: aquamarine; font-weight: 400; }
  </style>
  <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
</head>
<body>
<div id="content">
  <div id="request">
    <input id="location" class='bl' type="text">
    <input id="submit" class="bl" type="button" value="Get Weather">
  </div>
  <div id="forecast" style="display:none">
    <div id="current">
      <div class="label">Current conditions</div>
    </div>
    <div id="upcoming">
      <div class="label">Three-day forecast</div>
    </div>
  </div>
</div>
<script src="forecaster.js"></script>
<script>
  attachEvents();
</script>
</body>

When the user writes the name of a location and clicks “Get Weather”, make a GET request to the server. The response will be an array of objects, with structure:

{

code: locationCode,

name: locationName 

}

Find the object, corresponding to the name the user submitted in the input field with ID "location" and use its code value to make two more requests:

  • For current conditions, make a GET request. The response from the server will be an object as follows:

{ name: locationName,

  forecast: { low: temp,

              high: temp,

              condition: condition } }

  • For a 3-day forecast, make a GET request. The response from the server will be an object as follows:

{ name: locationName,

  forecast: [{ low: temp,

               high: temp,

               condition: condition }, … ] }

Use the information from these two objects to compose a forecast in HTML and insert it inside the page. Note that the <div> with ID "forecast" must be set to visible. See the examples for details.

If an error occurs (the server doesn’t respond or the location name cannot be found) or the data is not in the correct format, display "Error" in the forecast section.

Use the following codes for the weather sumbols:

  • Sunny // ☀
  • Partly sunny // ⛅
  • Overcast // ☁
  • Rain // ☂
  • Degrees °   // °

Examples:

When the app starts, the forecast div is hidden. When the user enters a name and clicks submit, the requests being.

forecast javascript app with firebase

The server at the address listed above will respond with valid data for location names:

  • London
  • New York
  • Barcelona
1 Answer
2

>> HERE YOU CAN VIEW AND TEST THE PROJECT ONLINE << (on GitHub io)


My solution is (HTML code first):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Forecatser</title>
    <style>
        #content {
            width: 400px;
        }
 
        #request {
            text-align: center;
        }
 
        .bl {
            width: 300px;
        }
 
        #current {
            text-align: center;
            font-size: 2em;
        }
 
        #upcoming {
            text-align: center;
        }
 
        .condition {
            text-align: left;
            display: inline-block;
        }
 
        .symbol {
            font-size: 4em;
            display: inline-block;
        }
 
        .forecast-data {
            display: block;
        }
 
        .upcoming {
            display: inline-block;
            margin: 1.5em;
        }
 
        .label {
            margin-top: 1em;
            font-size: 1.5em;
            background-color: aquamarine;
            font-weight: 400;
        }
    </style>
    <script src="https://code.jquery.com/jquery-3.2.1.js"></script>
    <script src="forecaster.js"></script>
</head>
<body>
<div id="content">
    <div id="request">
        <input id="location" class='bl' type="text"><br><br>
        <input id="submit" class="bl" type="button" value="Get Weather">
    </div>
    <h3>3 Towns to Check:</h3>
    <ul>
        <li>New York</li>
        <li>London</li>
        <li>Barcelona</li>
    </ul>
    <div id="forecast" style="display:none">
        <div id="current">
            <div class="label">Current conditions</div>
        </div>
        <div id="upcoming">
            <div class="label">Three-day forecast</div>
        </div>
    </div>
</div>
<script>
    attachEvents();
</script>
 
</body>
</html>

forecaster.js file from line #55 with the attachEvents() function inside:

function attachEvents() {
    const baseUrl = "https://judgetests.firebaseio.com";
    $("#submit").click(loadForecast);
 
    function request(endpoint) {
        return $.ajax({
            method: "GET",
            url: baseUrl + endpoint
        })
    }
 
    function loadForecast() {
        request("/locations.json")//get the endpoint of the request function
            .then(displayLocations)
            .catch(handleError);
    }
 
    //AJAX GET all locations
    function displayLocations(dataArr) {
        let inputLocation = $("#location").val();
        let code = dataArr
            .filter(loc => loc["name"] === inputLocation)
            .map(loc => loc["code"])[0];
 
        if (!code) {
            handleError();//displays error if no such code exists
        }
 
        let todayForecastP = request(`/forecast/today/${code}.json`);
        let upcomingForecastP = request(`/forecast/upcoming/${code}.json`);
 
        Promise.all([todayForecastP, upcomingForecastP])
            .then(displayAllForecastInfo)
            .catch(handleError)
    }
 
    function displayAllForecastInfo([todayWeather, upcomingWeather]) {
        let weatherSymbols = {
            "Sunny": "☀",// ☀
            "Partly sunny": "⛅",// ⛅
            "Overcast": "☁",// ☁
            "Rain": "☔",// ☂
            //"Degrees": "°"// °
        };
 
        let forecast = $("#forecast");
        forecast.css("display", "block");
 
        displayToCurrent(todayWeather, weatherSymbols);
        displayToUpcoming(upcomingWeather, weatherSymbols);
    }
 
    function displayToCurrent(todayWeather, weatherSymbols) {
        let current = $("#current");
        current.empty();
        current
            .append($('<div class="label">Current conditions</div>'))
            .append($(`<span class="condition symbol">${weatherSymbols[todayWeather["forecast"]["condition"]]}</span>`))
            .append($('<span class="condition"></span>')
                .append($(`<span class="forecast-data">${todayWeather["name"]}</span>`))
                .append($(`<span class="forecast-data">${todayWeather["forecast"]["low"]}°/${todayWeather["forecast"]["high"]}°</span>`))
                .append($(`<span class="forecast-data">${todayWeather["forecast"]["condition"]}</span>`)));
    }
 
    function displayToUpcoming(upcomingWeather, weatherSymbols) {
        let upcoming = $('#upcoming');
        upcoming.empty();
        upcoming.append($('<div class="label">Three-day forecast</div>'))
        let data = upcomingWeather["forecast"];
        for (let info of data) {
            upcoming
                .append($('<span class="upcoming"></span>')
                    .append($(`<span class="symbol">${weatherSymbols[info["condition"]]}</span>`))
                    .append($(`<span class="forecast-data">${info["low"]}°/${info["high"]}°</span>`))
                    .append($(`<span class="forecast-data">${info["condition"]}</span>`)));
        }
    }
 
    //Handle the Errors
    function handleError() {
        $('#forecast')
            .css("display", "block")
            .text("Error");
    }
}
Share: