Τελικός κώδικας για το πρόγραμμα καιρού
Αντιγράψτε και αποθηκεύστε τον παρακάτω κώδικα στα αντίστοιχα αρχεία (index.html
, style.css
, script.js
).
1. Αρχείο: index.html
(Η βασική δομή της εφαρμογής. Περιέχει τη φόρμα εισαγωγής και το "κοντέινερ" όπου θα εμφανιστούν οι πληροφορίες του καιρού.)
<!DOCTYPE html>
<html lang="el">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Εφαρμογή Καιρού</title>
<link rel="stylesheet" href="style.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
</head>
<body>
<div class="app-container">
<header>
<h1>Εφαρμογή Καιρού</h1>
</header>
<main>
<form id="city-form">
<input type="text" id="city-input" placeholder="π.χ. Αθήνα, Θεσσαλονίκη..." required>
<button type="submit">Αναζήτηση</button>
</form>
<div id="weather-display" class="hidden">
<h2 id="city-name"></h2>
<div class="weather-main">
<img id="weather-icon" src="" alt="Εικονίδιο καιρού">
<p id="temperature"></p>
</div>
<p id="weather-description"></p>
</div>
<div id="loading-spinner" class="hidden"></div>
</main>
</div>
<script src="script.js"></script>
</body>
</html>
2. Αρχείο: style.css
(Το styling που κάνει την εφαρμογή να φαίνεται καθαρή, μοντέρνα και responsive. Περιλαμβάνει και ένα απλό spinner για την ώρα της φόρτωσης.)
/* --- Basic Resets & Body Styles --- */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Roboto', sans-serif;
background: linear-gradient(135deg, #71b7e6, #9b59b6);
color: #333;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
/* --- App Container --- */
.app-container {
background: rgba(255, 255, 255, 0.9);
padding: 2rem;
border-radius: 15px;
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);
backdrop-filter: blur(4px);
-webkit-backdrop-filter: blur(4px);
border: 1px solid rgba(255, 255, 255, 0.18);
width: 90%;
max-width: 450px;
text-align: center;
}
header h1 {
margin-bottom: 1.5rem;
color: #333;
font-weight: 700;
}
/* --- Form Styles --- */
#city-form {
display: flex;
margin-bottom: 2rem;
}
#city-input {
flex-grow: 1;
padding: 0.8rem;
border: 1px solid #ccc;
border-radius: 8px 0 0 8px;
font-size: 1rem;
outline: none;
}
#city-input:focus {
border-color: #007bff;
}
#city-form button {
padding: 0.8rem 1rem;
border: none;
background: #007bff;
color: white;
font-size: 1rem;
cursor: pointer;
border-radius: 0 8px 8px 0;
transition: background-color 0.3s;
}
#city-form button:hover {
background: #0056b3;
}
/* --- Weather Display --- */
#weather-display {
animation: fadeIn 0.5s ease-in-out;
}
#city-name {
margin-bottom: 1rem;
font-size: 2rem;
}
.weather-main {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 1rem;
}
#temperature {
font-size: 3.5rem;
font-weight: 700;
margin-left: 1rem;
}
#weather-icon {
width: 100px;
height: 100px;
}
#weather-description {
font-size: 1.2rem;
text-transform: capitalize;
}
/* --- Utility & Animation --- */
.hidden {
display: none;
}
#loading-spinner {
border: 5px solid #f3f3f3;
border-top: 5px solid #007bff;
border-radius: 50%;
width: 50px;
height: 50px;
animation: spin 1s linear infinite;
margin: 20px auto;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@keyframes fadeIn {
from { opacity: 0; transform: scale(0.9); }
to { opacity: 1; transform: scale(1); }
}
3. Αρχείο: script.js
(Η καρδιά της εφαρμογής. Περιλαμβάνει την επικοινωνία με το API, τον χειρισμό των δεδομένων και την ενημέρωση της σελίδας.)
// ΣΗΜΑΝΤΙΚΟ: Αντικαταστήστε αυτό με το δικό σας, προσωπικό API Key από το openweathermap.org
const apiKey = 'YOUR_SECRET_API_KEY';
// --- Επιλογή Στοιχείων του DOM ---
const cityForm = document.getElementById('city-form');
const cityInput = document.getElementById('city-input');
const weatherDisplay = document.getElementById('weather-display');
const loadingSpinner = document.getElementById('loading-spinner');
// --- Προσθήκη Event Listener στη Φόρμα ---
cityForm.addEventListener('submit', async (event) => {
// 1. Αποτρέπουμε την προκαθορισμένη συμπεριφορά της φόρμας (ανανέωση σελίδας)
event.preventDefault();
// 2. Παίρνουμε την πόλη που έγραψε ο χρήστης και αφαιρούμε τυχόν κενά
const city = cityInput.value.trim();
// Αν δεν έχει γράψει τίποτα, δεν κάνουμε κάτι
if (!city) {
alert('Παρακαλώ εισάγετε μια πόλη.');
return;
}
// Εμφανίζουμε το spinner και κρύβουμε τις παλιές πληροφορίες
loadingSpinner.classList.remove('hidden');
weatherDisplay.classList.add('hidden');
// 3. Καλούμε τη συνάρτηση για να φέρει τα δεδομένα του καιρού
getWeatherData(city);
});
// --- Συνάρτηση για την κλήση του API ---
async function getWeatherData(city) {
// Κατασκευάζουμε το URL του API με τις απαραίτητες παραμέτρους
const apiUrl = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${apiKey}&units=metric&lang=el`;
try {
const response = await fetch(apiUrl);
// Αν η απάντηση δεν είναι ΟΚ (π.χ. 404 Not Found), δημιουργούμε ένα σφάλμα
if (!response.ok) {
throw new Error(`Η πόλη "${city}" δεν βρέθηκε. Δοκιμάστε ξανά.`);
}
const data = await response.json();
// Αν όλα πήγαν καλά, καλούμε τη συνάρτηση για την εμφάνιση των δεδομένων
displayWeatherData(data);
} catch (error) {
// Αν υπάρξει οποιοδήποτε σφάλμα, το εμφανίζουμε στον χρήστη
alert(error.message);
console.error("Fetch Error:", error);
} finally {
// Κρύβουμε το spinner σε κάθε περίπτωση (είτε επιτυχία είτε αποτυχία)
loadingSpinner.classList.add('hidden');
}
}
// --- Συνάρτηση για την Εμφάνιση των Δεδομένων στο DOM ---
function displayWeatherData(data) {
// Παίρνουμε τις πληροφορίες που χρειαζόμαστε από το αντικείμενο 'data'
const cityName = data.name;
const temperature = data.main.temp;
const description = data.weather[0].description;
const iconCode = data.weather[0].icon;
const iconUrl = `https://openweathermap.org/img/wn/${iconCode}@2x.png`;
// Ενημερώνουμε τα στοιχεία της σελίδας με τις νέες πληροφορίες
document.getElementById('city-name').textContent = cityName;
document.getElementById('temperature').textContent = `${Math.round(temperature)}°C`;
document.getElementById('weather-description').textContent = description;
document.getElementById('weather-icon').src = iconUrl;
document.getElementById('weather-icon').alt = `Εικονίδιο για ${description}`;
// Εμφανίζουμε το κοντέινερ των πληροφοριών
weatherDisplay.classList.remove('hidden');
}