From 5059d1c7c2d06dca1f6dd80f2e8e3b957c7c068e Mon Sep 17 00:00:00 2001 From: jlneuser Date: Fri, 6 Dec 2024 11:16:32 -0600 Subject: [PATCH 1/6] initial commit --- index.html | 0 main.js | 0 style.css | 0 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 index.html create mode 100644 main.js create mode 100644 style.css diff --git a/index.html b/index.html new file mode 100644 index 00000000..e69de29b diff --git a/main.js b/main.js new file mode 100644 index 00000000..e69de29b diff --git a/style.css b/style.css new file mode 100644 index 00000000..e69de29b From e1980c1f05d44cc9026f3e9ed474947331f4991f Mon Sep 17 00:00:00 2001 From: jlneuser Date: Fri, 6 Dec 2024 11:53:18 -0600 Subject: [PATCH 2/6] Get input, button, text added --- index.html | 24 ++++++++++++++++++++++++ style.css | 17 +++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/index.html b/index.html index e69de29b..06dcef8e 100644 --- a/index.html +++ b/index.html @@ -0,0 +1,24 @@ + + + + + + + Document + + + + + +

Weather Project

+
+
+ + +
+ + + + \ No newline at end of file diff --git a/style.css b/style.css index e69de29b..f6833244 100644 --- a/style.css +++ b/style.css @@ -0,0 +1,17 @@ +h1 { + margin-left: 500px; + padding-bottom: 20px; +} + +hr { + width: 50%; + margin-left: 320px; + +} + +.input-group { + + width: 50%; + margin-top: 50px; + margin-left: 321px; +} From fe4c8a965c157f56de9c3caa911ec4018c34d0d8 Mon Sep 17 00:00:00 2001 From: jlneuser Date: Fri, 6 Dec 2024 12:15:08 -0600 Subject: [PATCH 3/6] more styling to the page --- style.css | 1 + 1 file changed, 1 insertion(+) diff --git a/style.css b/style.css index f6833244..f741a6f7 100644 --- a/style.css +++ b/style.css @@ -1,4 +1,5 @@ h1 { + margin-top: 30px; margin-left: 500px; padding-bottom: 20px; } From 17fa049a17a1177f17191202ec38f2a84928871e Mon Sep 17 00:00:00 2001 From: jlneuser Date: Fri, 6 Dec 2024 13:36:21 -0600 Subject: [PATCH 4/6] got api data to display --- index.html | 4 ++++ main.js | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/index.html b/index.html index 06dcef8e..c6c6aa52 100644 --- a/index.html +++ b/index.html @@ -8,6 +8,7 @@ + @@ -18,6 +19,9 @@

Weather Project

aria-describedby="basic-addon1"> +
+ +
diff --git a/main.js b/main.js index e69de29b..7e651e18 100644 --- a/main.js +++ b/main.js @@ -0,0 +1,35 @@ +document.addEventListener('DOMContentLoaded', () => { + const input = document.querySelector('.form-control'); + const button = document.querySelector('.btn'); + const container = document.querySelector('#weather-container'); + + button.addEventListener('click', () => { + + const apiKey = 'ee02afd279ba852f5518dbe94195f595'; + const cityInput = input.value.toLowerCase().trim(); + + fetch(`https://api.openweathermap.org/data/2.5/weather?q=${cityInput}&appid=${apiKey}&units=metric`) + .then(response => { + if (!response) { + throw new Error(`City not found: ${response.statusText}`); + } + return response.json() + + }) + .then(data => { + + const weatherDiv = document.createElement('div'); // Correctly use document.createElement +weatherDiv.innerHTML = ` +

Weather in ${data.name}

+

${data.weather[0].description}

+

Temperature: ${data.main.temp}°C

+

Feels like: ${data.main.feels_like}°C

+`; +container.innerHTML = ''; +container.appendChild(weatherDiv); + + + }) + .catch(error => console.error('Uh oh...', error)); + }); +}); From 084a597f5867359e071046823a5e025e70e01583 Mon Sep 17 00:00:00 2001 From: jlneuser Date: Tue, 10 Dec 2024 19:40:50 -0600 Subject: [PATCH 5/6] finish CSS and JS before deleting comments --- main.js | 117 ++++++++++++++++++++++++++++++++++++++---------------- style.css | 65 ++++++++++++++++++++++++------ 2 files changed, 135 insertions(+), 47 deletions(-) diff --git a/main.js b/main.js index 7e651e18..4d25ceee 100644 --- a/main.js +++ b/main.js @@ -1,35 +1,84 @@ -document.addEventListener('DOMContentLoaded', () => { - const input = document.querySelector('.form-control'); - const button = document.querySelector('.btn'); - const container = document.querySelector('#weather-container'); - - button.addEventListener('click', () => { - - const apiKey = 'ee02afd279ba852f5518dbe94195f595'; - const cityInput = input.value.toLowerCase().trim(); - - fetch(`https://api.openweathermap.org/data/2.5/weather?q=${cityInput}&appid=${apiKey}&units=metric`) - .then(response => { - if (!response) { - throw new Error(`City not found: ${response.statusText}`); - } - return response.json() - - }) - .then(data => { - - const weatherDiv = document.createElement('div'); // Correctly use document.createElement -weatherDiv.innerHTML = ` -

Weather in ${data.name}

-

${data.weather[0].description}

-

Temperature: ${data.main.temp}°C

-

Feels like: ${data.main.feels_like}°C

-`; -container.innerHTML = ''; -container.appendChild(weatherDiv); - - - }) - .catch(error => console.error('Uh oh...', error)); - }); + + +const apiKey = "ee02afd279ba852f5518dbe94195f595"; + +// Variables to resuse +const searchButton = document.querySelector(".btn-primary"); +const cityInput = document.querySelector(".form-control"); +const weatherContainer = document.getElementById("weather-container"); + +// Search button + +searchButton.addEventListener("click", async () => { + const city = cityInput.value; + if (!city) { + alert("Please enter a city name"); + return; + } + + try { + // current weather data + const currentWeatherData = await fetch( + `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=imperial&appid=${apiKey}` + ).then((response) => response.json()); + + // 5-day forecast data + const forecastData = await fetch( + `https://api.openweathermap.org/data/2.5/forecast?q=${city}&units=imperial&appid=${apiKey}` + ).then((response) => response.json()); + + // Update weather container + updateWeatherContainer(currentWeatherData, forecastData); + } catch (error) { + console.error("Error fetching weather data:", error); + alert("Unable to fetch weather data. Please try again later."); + } }); + +function updateWeatherContainer(currentData, forecastData) { + const currentIconUrl = `https://openweathermap.org/img/wn/${currentData.weather[0].icon}@2x.png`; + + const currentWeatherTemplate = ` +
+

Current Weather in ${currentData.name}

+ ${currentData.weather[0].description} +

Temperature: ${currentData.main.temp} °F

+

Conditions: ${currentData.weather[0].description}

+
+ `; + + const daysOfWeek = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; + const forecastByDay = {}; + + // Group forecast data by day + forecastData.list.forEach((entry) => { + const date = new Date(entry.dt * 1000); + const day = daysOfWeek[date.getDay()]; + + if (!forecastByDay[day]) { + forecastByDay[day] = []; + } + + forecastByDay[day].push(entry); + }); + + let forecastTemplate = "

5-Day Forecast

"; + + Object.keys(forecastByDay).slice(0, 5).forEach((day) => { + const dayData = forecastByDay[day][0]; + const dayIconUrl = `https://openweathermap.org/img/wn/${dayData.weather[0].icon}@2x.png`; + + forecastTemplate += ` +
+

${day}

+ ${dayData.weather[0].description} +

Temperature: ${dayData.main.temp} °F

+

Conditions: ${dayData.weather[0].description}

+
+ `; + }); + + weatherContainer.innerHTML = currentWeatherTemplate + forecastTemplate; +} + + diff --git a/style.css b/style.css index f741a6f7..1cdfd742 100644 --- a/style.css +++ b/style.css @@ -1,18 +1,57 @@ -h1 { - margin-top: 30px; - margin-left: 500px; - padding-bottom: 20px; + +/* General styling for the weather container */ +#weather-container { + background-color: #f8f9fa; + +} + +/* Current weather section */ +.current-weather { + text-align: center; + margin-bottom: 40px; +} + +.current-weather img { + width: 5px; + height: 20px; +} + +.current-weather h2 { + margin-bottom: 10px; + font-size: 1.5rem; } -hr { - width: 50%; - margin-left: 320px; - +.current-weather p { + margin: 5px 0; + font-size: 1.1rem; } -.input-group { - - width: 50%; - margin-top: 50px; - margin-left: 321px; +/* Forecast styling */ +.forecast-day { + display: inline-block; + width: calc(20% - 16px); + margin: 0 8px; + text-align: center; + padding: 10px; + background-color: #ffffff; + border: 1px solid #dee2e6; + border-radius: 8px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } + +.forecast-day img { + width: 80px; + height: 80px; +} + +.forecast-day h3 { + margin-bottom: 8px; + font-size: 1.2rem; +} + +.forecast-day p { + margin: 4px 0; + font-size: 1rem; +} + + From bab6b484c8067b56960db998a5419495edd9edfe Mon Sep 17 00:00:00 2001 From: jlneuser Date: Tue, 10 Dec 2024 21:04:48 -0600 Subject: [PATCH 6/6] clean up alignment and finalize before submit --- index.html | 16 ++++-- main.js | 139 ++++++++++++++++++++++++++--------------------------- style.css | 37 +++++++++----- 3 files changed, 103 insertions(+), 89 deletions(-) diff --git a/index.html b/index.html index c6c6aa52..a50b456b 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ - Document + Weather App Project @@ -15,14 +15,22 @@

Weather Project


- +
+
+

+ Weather icon +

+
+
+

5-Day Forecast

+
+
+
- \ No newline at end of file diff --git a/main.js b/main.js index 4d25ceee..a7cb3faa 100644 --- a/main.js +++ b/main.js @@ -1,84 +1,79 @@ - - const apiKey = "ee02afd279ba852f5518dbe94195f595"; -// Variables to resuse const searchButton = document.querySelector(".btn-primary"); -const cityInput = document.querySelector(".form-control"); -const weatherContainer = document.getElementById("weather-container"); +const cityInput = document.querySelector('.form-control'); +const weatherContainer = document.getElementById('weather-container'); +const currentWeatherDiv = document.querySelector('.current-weather'); +const forecastDiv = document.querySelector('.forecast'); -// Search button +currentWeatherDiv.style.display = 'none'; +forecastDiv.style.display = 'none'; -searchButton.addEventListener("click", async () => { +searchButton.addEventListener('click', () => { const city = cityInput.value; if (!city) { - alert("Please enter a city name"); - return; - } - - try { - // current weather data - const currentWeatherData = await fetch( - `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=imperial&appid=${apiKey}` - ).then((response) => response.json()); - - // 5-day forecast data - const forecastData = await fetch( - `https://api.openweathermap.org/data/2.5/forecast?q=${city}&units=imperial&appid=${apiKey}` - ).then((response) => response.json()); - - // Update weather container - updateWeatherContainer(currentWeatherData, forecastData); - } catch (error) { - console.error("Error fetching weather data:", error); - alert("Unable to fetch weather data. Please try again later."); + alert('No city name given'); + return; } + fetchCurrentWeather(city); + fetchForecast(city); }); -function updateWeatherContainer(currentData, forecastData) { - const currentIconUrl = `https://openweathermap.org/img/wn/${currentData.weather[0].icon}@2x.png`; - - const currentWeatherTemplate = ` -
-

Current Weather in ${currentData.name}

- ${currentData.weather[0].description} -

Temperature: ${currentData.main.temp} °F

-

Conditions: ${currentData.weather[0].description}

-
- `; - - const daysOfWeek = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; - const forecastByDay = {}; - - // Group forecast data by day - forecastData.list.forEach((entry) => { - const date = new Date(entry.dt * 1000); - const day = daysOfWeek[date.getDay()]; - - if (!forecastByDay[day]) { - forecastByDay[day] = []; - } - - forecastByDay[day].push(entry); - }); - - let forecastTemplate = "

5-Day Forecast

"; - - Object.keys(forecastByDay).slice(0, 5).forEach((day) => { - const dayData = forecastByDay[day][0]; - const dayIconUrl = `https://openweathermap.org/img/wn/${dayData.weather[0].icon}@2x.png`; - - forecastTemplate += ` -
-

${day}

- ${dayData.weather[0].description} -

Temperature: ${dayData.main.temp} °F

-

Conditions: ${dayData.weather[0].description}

-
- `; - }); - - weatherContainer.innerHTML = currentWeatherTemplate + forecastTemplate; +function fetchCurrentWeather(city) { + const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=imperial&appid=${apiKey}`; + fetch(url) + .then((response) => response.json()) + .then(function (data) { + const cityNameElement = document.getElementById('city-name'); + const weatherIconElement = document.getElementById('current-weather-icon'); + const tempElement = document.getElementById('current-temp'); + + cityNameElement.textContent = data.name; + weatherIconElement.src = `https://openweathermap.org/img/wn/${data.weather[0].icon}@2x.png`; + weatherIconElement.alt = data.weather[0].description; + tempElement.textContent = `${data.main.temp} °F - ${data.weather[0].description}`; + + currentWeatherDiv.style.display = 'block'; + }) + .catch((error) => { + console.error('Error, didn\'t fetch weather', error); + }); } - +function fetchForecast(city) { + const url = `https://api.openweathermap.org/data/2.5/forecast?q=${city}&units=imperial&appid=${apiKey}`; + fetch(url) + .then((response) => response.json()) + .then(function (data) { + const forecastDaysElement = document.getElementById("forecast-days"); + forecastDaysElement.innerHTML = ''; // + + for (let i = 0; i < data.list.length; i += 8) { // + const entry = data.list[i]; + const date = new Date(entry.dt * 1000); + const dayName = date.toLocaleDateString("en-US", { weekday: "long" }); + + const forecastDayDiv = document.createElement('div'); + forecastDayDiv.className = 'forecast-day'; + + const dayElement = document.createElement('h3'); + dayElement.textContent = dayName; + + const weatherIcon = document.createElement('img'); + weatherIcon.src = `https://openweathermap.org/img/wn/${entry.weather[0].icon}@2x.png`; + + const tempElement = document.createElement('p'); + tempElement.textContent = `${entry.main.temp} °F - ${entry.weather[0].description}`; + + forecastDayDiv.appendChild(dayElement); + forecastDayDiv.appendChild(weatherIcon); + forecastDayDiv.appendChild(tempElement); + forecastDaysElement.appendChild(forecastDayDiv); + } + + forecastDiv.style.display = 'block'; + }) + .catch((error) => { + console.error('Error, didn\'t fetch forecast:', error); + }); +} diff --git a/style.css b/style.css index 1cdfd742..e510fd73 100644 --- a/style.css +++ b/style.css @@ -1,36 +1,47 @@ +h1 { + text-align: center; +} -/* General styling for the weather container */ -#weather-container { - background-color: #f8f9fa; +.form-control { + padding-left: 5; + margin-left: 502px; +} +.btn { + margin-right: 500px; } -/* Current weather section */ .current-weather { text-align: center; - margin-bottom: 40px; } .current-weather img { - width: 5px; - height: 20px; + width: 100px; + height: 100px; } .current-weather h2 { margin-bottom: 10px; - font-size: 1.5rem; + } .current-weather p { margin: 5px 0; - font-size: 1.1rem; } -/* Forecast styling */ +.forecast { + margin-top: 20px; +} + +.forecast h2 { + text-align: center; + margin-bottom: 20px; +} + .forecast-day { display: inline-block; width: calc(20% - 16px); - margin: 0 8px; + margin: 0 3px; text-align: center; padding: 10px; background-color: #ffffff; @@ -40,18 +51,18 @@ } .forecast-day img { + display: block; + margin: 0 auto 10px; width: 80px; height: 80px; } .forecast-day h3 { margin-bottom: 8px; - font-size: 1.2rem; } .forecast-day p { margin: 4px 0; - font-size: 1rem; }