Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
key.txt
34 changes: 34 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<!DOCTYPE html>
<html lang="en">
<head>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
crossorigin="anonymous"
/>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
crossorigin="anonymous"
></script>
<link rel="stylesheet" href="style.css" />
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Weather App</title>
</head>
<body>
<header class="text-center app-header">
<h1>Weather App</h1>
<hr />
</header>
<div class="container input-group justify-content-center">
<input id="city-input" type="text" placeholder="City Name" />
<button id="submit" class="btn btn-primary">Submit</button>
</div>
<br />
<div id="current-weather" class="justify-content-center row"></div>
<div id="five-day-forecast" class="row container weather-info"></div>
<script src="main.js"></script>
</body>
</html>
143 changes: 143 additions & 0 deletions main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
let fiveDayForecast = [];
const key = 'c09e162aa897c3130ce9f6bfd5698b9b'

// City Submission //
document.querySelector('#submit').addEventListener('click', function () {
const cityInput = document.querySelector('#city-input');

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here you need to trim it to remove empty spaces

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also you could have done the lower case here

if (!cityInput.value) {
alert('Error: You must enter a city name to seach.')
} else {
getLocation(cityInput.value);
cityInput.value = '';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good practice!

}
});

// Gets city latitude and longitude //
function getLocation(cityInput) {
const url = `http://api.openweathermap.org/geo/1.0/direct?q=${cityInput}&limit=5&appid=${key}&units=imperial`;
fetch(url, {
method: 'GET',
dataType: 'json',
})
.then(data => data.json())
.then(data => getWeather(data, cityInput));
};

// Gets five day forecast //
function getForecast(data, cityInput) {
const dataIndex = data.findIndex(data => data.name.toLowerCase() === cityInput.toLowerCase());
const dataLat = data[dataIndex].lat;
const dataLon = data[dataIndex].lon;
const url = `http://api.openweathermap.org/data/2.5/forecast?lat=${dataLat}&lon=${dataLon}&appid=${key}&units=imperial`;
fetch(url, {
method: 'GET',
dataType: 'json'
})
.then(forecastData => forecastData.json())
.then(forecastData => renderForecast(forecastData))
}

// Gets one day weather data //
function getWeather(data, cityInput) {
if (cityInput.split('.')[0].toLowerCase() == 'st') {
cityInput = 'saint ' + cityInput.split('.')[1]
}
const dataIndex = data.findIndex(data => data.name.toLowerCase() === cityInput.toLowerCase());
if (dataIndex === -1) {
alert('Error: Error finding City information');
return;
} else {
const dataLat = data[dataIndex].lat;
const dataLon = data[dataIndex].lon;
const url = `https://api.openweathermap.org/data/2.5/weather?lat=${dataLat}&lon=${dataLon}&appid=${key}&units=imperial`;
fetch(url, {
method: 'GET',
dataType: 'json'
})
.then(singleWeatherData => singleWeatherData.json())
.then(singleWeatherData => oneDayWeather(singleWeatherData));
};

getForecast(data, cityInput)
};

// Adds current day weather to currWeather array //
function oneDayWeather(singleWeatherData) {
const weatherData = singleWeatherData;
const data = {
name: weatherData.name,
temp: Math.floor(weatherData.main.temp),
condition: weatherData.weather[0].description,
imageURL: `https://openweathermap.org/img/wn/${weatherData.weather[0].icon}@2x.png`
};

renderCurrWeather(data);
};

// Renders Current Weather Data to Page //
function renderCurrWeather(data) {
const currWeatherDiv = document.querySelector('#current-weather');
currWeatherDiv.replaceChildren();
const currWeatherInfo = document.createElement('div');
currWeatherInfo.className = 'col-md-2 weather-info';
currWeatherInfo.id = 'currInfo'
const currWeatherImage = document.createElement('div');
currWeatherImage.className = 'col-md-2 weather-info';
const currWeatherHeading = document.createElement('h1')
currWeatherHeading.className = 'lead weather-info'
currWeatherHeading.textContent = 'Currently:'
const seperator = document.createElement('hr')

const infoTemplate = `
<h2>${data.temp}</h2>
<p>${data.name}</p>`;

const imageTemplate = `
<p id="currDesc">${data.condition}</p>
<img src="${data.imageURL}"/>`;

currWeatherDiv.appendChild(currWeatherHeading)
currWeatherDiv.appendChild(currWeatherInfo)
currWeatherDiv.appendChild(currWeatherImage)
currWeatherDiv.appendChild(seperator)
currWeatherInfo.insertAdjacentHTML('beforeend', infoTemplate)
currWeatherImage.insertAdjacentHTML('beforeend', imageTemplate)
}

// Renders five day forecast //
function renderForecast(forecastData) {
const days = ['Sunday','Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
const forecastArr = forecastData.list;

const dayOne = forecastArr[0];
const dayTwo = forecastArr[8];
const dayThree = forecastArr[16]
const dayFour = forecastArr[24]
const dayFive = forecastArr[32]
fiveDayForecast = [];
fiveDayForecast.push(dayOne, dayTwo, dayThree, dayFour, dayFive)
const forecastDiv = document.querySelector('#five-day-forecast');
const forecastHeading = document.createElement('h1')
forecastHeading.className = 'lead weather-info'
forecastHeading.textContent = 'Five Day Forecast:'
forecastDiv.replaceChildren();
forecastDiv.appendChild(forecastHeading)

fiveDayForecast.forEach(day => {
const dailyWeatherInfo = document.createElement('div');
dailyWeatherInfo.className = 'col weather-info forecast border';
const temp = Math.floor(day.main.temp);
const dayIndex = new Date(day.dt_txt)
const dayOfWeek = dayIndex.getDay(days)

const template = `
<h2>${temp}</h2>
<p>${days[dayOfWeek]}</p>
<p>${day.weather[0].description}</p>
<img src="https://openweathermap.org/img/wn/${day.weather[0].icon}@2x.png"/>`;

forecastDiv.appendChild(dailyWeatherInfo);
dailyWeatherInfo.insertAdjacentHTML('beforeend', template)
})

}
25 changes: 25 additions & 0 deletions style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.app-header {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some classes here are not needed and you could have used bootstrap for them
example mt-5 (margin-top) and w-auto (fit content)

margin-top: 50px;
}

hr {
border-top-width: 3px;
}

.weather-info {
text-align: center;
}

#five-day-forecast {
max-width: fit-content;
margin-left: auto;
margin-right: auto;
}

#currDesc {
margin-bottom: 0;
}

#currInfo {
margin-top: 15px;
}