UNABLE TO CLICK ENTER AFTER WRITING A CITY, DO AUTO-COMPLETION ALSO WHEN TYPING THE NAME OF THE CITY AND CORRECT THE SEARCH ISSUE SINCE IT'S NOT WORKING
Browse files- index.html +84 -10
index.html
CHANGED
|
@@ -131,15 +131,88 @@
|
|
| 131 |
|
| 132 |
<script>
|
| 133 |
feather.replace();
|
|
|
|
|
|
|
|
|
|
| 134 |
|
| 135 |
-
|
| 136 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 137 |
if (e.key === 'Enter') {
|
|
|
|
|
|
|
| 138 |
fetchWeather();
|
| 139 |
}
|
| 140 |
});
|
| 141 |
-
|
| 142 |
-
async function fetchWeather() {
|
| 143 |
const location = document.getElementById('location-input').value.trim();
|
| 144 |
if (!location) return;
|
| 145 |
|
|
@@ -159,8 +232,9 @@
|
|
| 159 |
if (!geoData || geoData.length === 0) {
|
| 160 |
throw new Error('City not found. Try a different spelling or nearby location.');
|
| 161 |
}
|
| 162 |
-
|
| 163 |
-
const { lat: latitude, lon: longitude } =
|
|
|
|
| 164 |
// Fetch current weather and forecast in one call
|
| 165 |
// Use OpenWeatherMap API for weather data
|
| 166 |
const weatherResponse = await fetch(`https://api.openweathermap.org/data/2.5/onecall?lat=${latitude}&lon=${longitude}&exclude=minutely,hourly,alerts&units=metric&appid=3fd7e0e3b5f5bf7f3a6cee1c6af5f8e0`);
|
|
@@ -191,9 +265,8 @@ if (!weatherResponse.ok) throw new Error('Weather service unavailable');
|
|
| 191 |
function updateCurrentWeather(data) {
|
| 192 |
const current = data.current;
|
| 193 |
const date = new Date(current.dt * 1000);
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
document.getElementById('date').textContent = date.toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
|
| 197 |
document.getElementById('temp').textContent = `${Math.round(current.temp)}°C`;
|
| 198 |
|
| 199 |
const weatherDesc = current.weather[0].description;
|
|
@@ -230,8 +303,9 @@ const forecastItem = document.createElement('div');
|
|
| 230 |
forecastContainer.appendChild(forecastItem);
|
| 231 |
}
|
| 232 |
// Example: Load default weather for London on page load (more reliable)
|
|
|
|
| 233 |
window.addEventListener('load', () => {
|
| 234 |
-
|
| 235 |
fetchWeather();
|
| 236 |
});
|
| 237 |
</script>
|
|
|
|
| 131 |
|
| 132 |
<script>
|
| 133 |
feather.replace();
|
| 134 |
+
// Initialize autocomplete
|
| 135 |
+
const locationInput = document.getElementById('location-input');
|
| 136 |
+
const searchBtn = document.getElementById('search-btn');
|
| 137 |
|
| 138 |
+
// Debounce function to limit API calls
|
| 139 |
+
function debounce(func, delay) {
|
| 140 |
+
let timeout;
|
| 141 |
+
return function() {
|
| 142 |
+
const context = this;
|
| 143 |
+
const args = arguments;
|
| 144 |
+
clearTimeout(timeout);
|
| 145 |
+
timeout = setTimeout(() => func.apply(context, args), delay);
|
| 146 |
+
};
|
| 147 |
+
}
|
| 148 |
+
|
| 149 |
+
// Fetch location suggestions
|
| 150 |
+
async function fetchSuggestions(query) {
|
| 151 |
+
if (!query || query.length < 2) return;
|
| 152 |
+
try {
|
| 153 |
+
const response = await fetch(`https://api.openweathermap.org/geo/1.0/direct?q=${query}&limit=5&appid=3fd7e0e3b5f5bf7f3a6cee1c6af5f8e0`);
|
| 154 |
+
if (!response.ok) return;
|
| 155 |
+
const data = await response.json();
|
| 156 |
+
return data;
|
| 157 |
+
} catch (error) {
|
| 158 |
+
console.error('Error fetching suggestions:', error);
|
| 159 |
+
}
|
| 160 |
+
}
|
| 161 |
+
|
| 162 |
+
// Show suggestions dropdown
|
| 163 |
+
function showSuggestions(suggestions) {
|
| 164 |
+
const dropdown = document.createElement('div');
|
| 165 |
+
dropdown.className = 'absolute z-10 w-full mt-1 bg-white rounded-md shadow-lg max-h-60 overflow-auto';
|
| 166 |
+
dropdown.id = 'suggestions-dropdown';
|
| 167 |
+
|
| 168 |
+
suggestions.forEach(item => {
|
| 169 |
+
const suggestion = document.createElement('div');
|
| 170 |
+
suggestion.className = 'px-4 py-2 hover:bg-gray-100 cursor-pointer';
|
| 171 |
+
suggestion.textContent = `${item.name}, ${item.country}`;
|
| 172 |
+
suggestion.addEventListener('click', () => {
|
| 173 |
+
locationInput.value = `${item.name}, ${item.country}`;
|
| 174 |
+
dropdown.remove();
|
| 175 |
+
fetchWeather();
|
| 176 |
+
});
|
| 177 |
+
dropdown.appendChild(suggestion);
|
| 178 |
+
});
|
| 179 |
+
|
| 180 |
+
// Remove existing dropdown if any
|
| 181 |
+
const existing = document.getElementById('suggestions-dropdown');
|
| 182 |
+
if (existing) existing.remove();
|
| 183 |
+
|
| 184 |
+
locationInput.parentNode.appendChild(dropdown);
|
| 185 |
+
}
|
| 186 |
+
|
| 187 |
+
// Handle input changes with debounce
|
| 188 |
+
locationInput.addEventListener('input', debounce(async (e) => {
|
| 189 |
+
const query = e.target.value.trim();
|
| 190 |
+
if (query.length >= 2) {
|
| 191 |
+
const suggestions = await fetchSuggestions(query);
|
| 192 |
+
if (suggestions && suggestions.length) {
|
| 193 |
+
showSuggestions(suggestions);
|
| 194 |
+
}
|
| 195 |
+
}
|
| 196 |
+
}, 300));
|
| 197 |
+
|
| 198 |
+
// Handle click outside to close dropdown
|
| 199 |
+
document.addEventListener('click', (e) => {
|
| 200 |
+
if (!e.target.closest('#suggestions-dropdown') && e.target !== locationInput) {
|
| 201 |
+
const dropdown = document.getElementById('suggestions-dropdown');
|
| 202 |
+
if (dropdown) dropdown.remove();
|
| 203 |
+
}
|
| 204 |
+
});
|
| 205 |
+
|
| 206 |
+
// Handle search button and enter key
|
| 207 |
+
searchBtn.addEventListener('click', fetchWeather);
|
| 208 |
+
locationInput.addEventListener('keydown', function(e) {
|
| 209 |
if (e.key === 'Enter') {
|
| 210 |
+
const dropdown = document.getElementById('suggestions-dropdown');
|
| 211 |
+
if (dropdown) dropdown.remove();
|
| 212 |
fetchWeather();
|
| 213 |
}
|
| 214 |
});
|
| 215 |
+
async function fetchWeather() {
|
|
|
|
| 216 |
const location = document.getElementById('location-input').value.trim();
|
| 217 |
if (!location) return;
|
| 218 |
|
|
|
|
| 232 |
if (!geoData || geoData.length === 0) {
|
| 233 |
throw new Error('City not found. Try a different spelling or nearby location.');
|
| 234 |
}
|
| 235 |
+
const city = geoData[0];
|
| 236 |
+
const { lat: latitude, lon: longitude } = city;
|
| 237 |
+
const locationName = `${city.name}${city.state ? ', ' + city.state : ''}, ${city.country}`;
|
| 238 |
// Fetch current weather and forecast in one call
|
| 239 |
// Use OpenWeatherMap API for weather data
|
| 240 |
const weatherResponse = await fetch(`https://api.openweathermap.org/data/2.5/onecall?lat=${latitude}&lon=${longitude}&exclude=minutely,hourly,alerts&units=metric&appid=3fd7e0e3b5f5bf7f3a6cee1c6af5f8e0`);
|
|
|
|
| 265 |
function updateCurrentWeather(data) {
|
| 266 |
const current = data.current;
|
| 267 |
const date = new Date(current.dt * 1000);
|
| 268 |
+
document.getElementById('location').textContent = locationName;
|
| 269 |
+
document.getElementById('date').textContent = date.toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
|
|
|
|
| 270 |
document.getElementById('temp').textContent = `${Math.round(current.temp)}°C`;
|
| 271 |
|
| 272 |
const weatherDesc = current.weather[0].description;
|
|
|
|
| 303 |
forecastContainer.appendChild(forecastItem);
|
| 304 |
}
|
| 305 |
// Example: Load default weather for London on page load (more reliable)
|
| 306 |
+
// Load default weather for London on page load
|
| 307 |
window.addEventListener('load', () => {
|
| 308 |
+
locationInput.value = 'London, UK';
|
| 309 |
fetchWeather();
|
| 310 |
});
|
| 311 |
</script>
|