HTML5 Weather App
Due Date
Due before 6:00 pm on Friday October 2, 2020.
Using two third-party API services (OpenWeather and LocationIQ) create a simple HTML5 app to allow the user to look up weather forecasts for various locations.
Some starter code for accessing the two API services is provided.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Weather | C1</title>
</head>
<body>
<div id="root"></div>
<script src="index.js" type="module"></script>
</body>
</html>
index.js
import { getForecast, createWeatherIcon } from './weather.service.js'
import { getGeolocation } from './map.service.js'
main()
// This is a demo of how to use the two API services.
// You should replace this with your own application logic.
async function main () {
const location = 'Algonquin College, Nepean, ON, CA'
try {
const coord = await getGeolocation(location)
const forecast = await getForecast({ coord })
console.log(forecast)
} catch (error) {
console.log(error.message)
}
}
map.service.js
const API_TOKEN = 'THIS_NEEDS_TO_BE_YOUR_API_KEY'
const BASE_URL = 'https://us1.locationiq.com/v1'
export async function getGeolocation (location) {
const url = `${BASE_URL}/search.php?key=${API_TOKEN}&q=${location}&format=json`
const response = await fetch(url)
if (!response.ok) {
throw new Error(response.statusText)
}
const data = await response.json()
return { lat: data[0].lat, lon: data[0].lon }
}
weather.service.js
'use strict'
const BASE_URL = 'https://api.openweathermap.org/data/2.5/onecall'
const API_KEY = 'THIS_NEEDS_TO_BE_YOUR_API_KEY'
const DEFAULT_OPTIONS = {
coord: { lon: -75.76, lat: 45.35 }, // Algonquin College
units: 'metric'
}
const cache = new Map()
/**
* @typedef {Object} APIOptions
* @property {string} units [metric, imperial, standard]
* @property {Object} coord Location coordinates
* @property {number} coord.lon Longitude
* @property {number} coord.lat Latitude
*/
/**
* Get the latest weather forecast for the given location.
* Results are cached for 10 minutes.
* @param {APIOptions} options
* @returns {Object} Forecast results
* @see https://openweathermap.org/api/one-call-api#data
*/
export async function getForecast (options) {
const { coord, units } = Object.assign({}, DEFAULT_OPTIONS, options)
const cacheItem = cache.get(coord)
if (cacheItem && !isExpired(cacheItem.current.dt)) {
return cacheItem
}
const forecast = await fetchForecast({ units, coord })
cache.set(coord, forecast)
return forecast
/**
* Helper function to check cache expiry
* @param {number} cacheTime UNIX timestamp in seconds
*/
function isExpired (cacheTime) {
const TEN_MINUTES = 600 // seconds
const currentTime = Math.floor(Date.now() / 1000) // convert from ms to s
const elapsedTime = currentTime - cacheTime
return elapsedTime > TEN_MINUTES
}
}
/**
* Private function to make the actual `fetch()` call to the API
* @param {APIOptions} options
*/
async function fetchForecast ({ coord: { lat, lon }, units }) {
const url = `${BASE_URL}?lat=${lat}&lon=${lon}&units=${units}&appid=${API_KEY}`
const response = await fetch(url)
if (!response.ok) throw new Error(response.statusText)
return response.json()
}
/**
* Returns an <img> HTMLElement with the correct URL to display
* the OpenWeather image corresponding to the given `iconCode`.
* @param {string} iconCode
*/
export function createWeatherIcon (iconCode) {
let img = document.createElement('img')
img.setAttribute(
'src',
'https://openweathermap.org/img/w/' + iconCode + '.png'
)
img.setAttribute('alt', '')
return img
}
# Requirements
# Open Weather Map
Use the one-call-api from openweathermap.org
You will need to register for your own API Key — its free.
# LocationIQ
You will need to register for your own API Key — there is a free usage tier.
The user should be prompted for their target location.
They should be able to type in a place name e.g. 'Kanata, ON, CA'.The user should also have the option to allow the browser to access the Geolocation API and calculate the current longitude and latitude position.
If entering the location by name, you will need to call the LocationIQ API to get the longitude and latitude coordinates for the given location.
# User Interface
The user interface should be mobile first, responsive and accessible.
In addition to the user input elements ...
The forecast data should be display the
current
stats more prominently with one of the two future forecast views below.Allow the user to switch between an hourly forecast for the next 6 hours or a daily forecast for the next 6 days.
The forecast display should incorporate the iconography from OpenWeather service.
The exact layout and stats to include or exclude in the display is up to you. Make it useful and make it look professional.
You may choose to use a CSS library like Bootstrap or Bulma, or you may choose to create all of the CSS by hand.
The display should be dynamically refreshed when the forecast is updated, or the location is changed.
# localStorage
- Store the most recent location and forecast data in
localStorage
. Display this data by default when the user first opens (or refreshes) the page.
Remember
Make commits as you complete each requirement. They should be atomic and have a meaningfully descriptive message.
# Submission
- Create a private repo on GitHub with the name mad9135-c1-html5-weather.
- Be sure to enable GitHub Pages on the repo.
- Invite GitHub user
rlmckenney
as a collaborator on your private repo. - Submit the URLs for both the code repo and GitHub Pages to Brightspace.