My JavaScript Weather Widget is fetching live weather warnings via the Met Office website’s RSS feed. The problem is that the warnings display twice on the page, so I think there must be duplicate call to the fetch function that I can’t find. The weather-widget.js script is only included once on the page. I have run a stack trace and the console shows only one call, so I can’t work out why the warning is being displayed twice. I am using axios for the http request and Bootstrap 5 to display the warnings.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Weather Widget</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
<div class="container mt-5">
<div class="card shadow-lg">
<div class="card-header bg-primary text-white">
<h5 class="mb-0">Weather Warnings</h5>
</div>
<div class="card-body">
<div id="weather-widget">
<p>Loading weather warnings...</p>
</div>
</div>
</div>
</div>
<script src="weather-widget.js"></script>
</body>
</html>
weather-widget.js
document.addEventListener("DOMContentLoaded", function () {
const widgetContainer = document.getElementById("weather-widget");
const rssFeedUrl = "https://corsproxy.io/https://www.metoffice.gov.uk/public/data/PWSCache/WarningsRSS/Region/yh";
// Fetch and parse the RSS feed
async function fetchWeatherWarnings() {
console.trace("fetchWeatherWarnings() trace");
try {
const response = await axios.get(rssFeedUrl, {
headers: {
'Accept': 'application/rss+xml'
}
});
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(response.data, "application/xml");
// Extract warning items
const items = xmlDoc.querySelectorAll("item");
if (items.length === 0) {
widgetContainer.innerHTML = "<p>No weather warnings available at the moment.</p>";
return;
}
// Generate HTML for warnings
let warningsHtml = "";
items.forEach((item) => {
const title = item.querySelector("title").textContent;
const link = item.querySelector("link").textContent;
const description = item.querySelector("description").textContent;
const enclosure = item.querySelector("enclosure")?.getAttribute("url");
warningsHtml += `
<div class="mb-3">
<h6 class="fw-bold">${title}</h6>
<p>${description}</p>
${enclosure ? `<img src="${enclosure}" alt="Warning icon" class="img-fluid mb-2">` : ""}
<a href="${link}" target="_blank" class="btn btn-sm btn-outline-primary">Read More</a>
</div>
<hr>
`;
});
widgetContainer.innerHTML = warningsHtml;
} catch (error) {
console.error("Error fetching weather warnings:", error);
widgetContainer.innerHTML = "<p>Unable to load weather warnings. Please try again later.</p>";
}
}
// Fetch warnings on load
fetchWeatherWarnings(console.log("Script executed"));
});