Step 1: Open your browser of choice Step 2: navigate to http://vfox-dt.thefurrycollective.ca/counties-auto.html (or wheverever this folder is located) Step 3: Open Developer Tools or Inspect, or whatever the technical debugging part of the browser is called. Step 4: To do a TEST for WAYNE COUNTY, put this code in: // Simulate a "Watch" alert for Wayne County const countyId = "Wayne"; // must match your SVG id const fakeClass = "alert-watch"; // yellow fill // Find the county element in the SVG const el = getCountyElement(countyId); // Apply the alert class if not manually overridden if (el && !manualOverrides[countyId]) { applyAlertClass(el, fakeClass); } // Also update the summary box manually const summaryEl = document.getElementById("noaa-alert-summary"); if (summaryEl) { summaryEl.innerHTML = `${countyId.toUpperCase()}: TEST WATCH`; } If you want to have it also change the LED: // Wayne County: Watch (yellow) const countyId = "Wayne"; const fakeClass = "alert-watch"; const el = getCountyElement(countyId); if (el && !manualOverrides[countyId]) applyAlertClass(el, fakeClass); // Update NOAA summary const summaryEl = document.getElementById("noaa-alert-summary"); if (summaryEl) { summaryEl.innerHTML = `${countyId.toUpperCase()}: TEST WATCH`; } // Turn NOAA LED red showNOAALed(true); Step 5: To do a MULTI-COUNTY MULTI-ALERT, such as a WARNING for ESSEX COUNTY and ADVISORY for CHATHAM-KENT, put this code in: // Simulate multiple alerts at once // Wayne County: Watch (yellow) { const countyId = "Wayne"; const fakeClass = "alert-watch"; const el = getCountyElement(countyId); if (el && !manualOverrides[countyId]) applyAlertClass(el, fakeClass); const summaryEl = document.getElementById("noaa-alert-summary"); if (summaryEl) { summaryEl.innerHTML += `${countyId.toUpperCase()}: TEST WATCH
`; } } // Essex County + Pelee Island: Warning (red) { const countyId = "Windsor-Essex-Pelee"; // group id in your SVG const fakeClass = "alert-warning"; const el = getCountyElement(countyId); if (el && !manualOverrides[countyId]) applyAlertClass(el, fakeClass); const summaryEl = document.getElementById("ec-alert-summary"); if (summaryEl) { summaryEl.innerHTML += `${countyId.toUpperCase()}: TEST WARNING
`; } } // Chatham-Kent + Moraviantown: Advisory (blue) { const countyId = "Chatham-Kent-Moraviantown"; const fakeClass = "alert-advisory"; const el = getCountyElement(countyId); if (el && !manualOverrides[countyId]) applyAlertClass(el, fakeClass); const summaryEl = document.getElementById("ec-alert-summary"); if (summaryEl) { summaryEl.innerHTML += `${countyId.toUpperCase()}: TEST ADVISORY
`; } } If you want it to also change the LED: // Wayne County: Watch { const countyId = "Wayne"; const fakeClass = "alert-watch"; const el = getCountyElement(countyId); if (el && !manualOverrides[countyId]) applyAlertClass(el, fakeClass); const summaryEl = document.getElementById("noaa-alert-summary"); if (summaryEl) { summaryEl.innerHTML += `${countyId.toUpperCase()}: TEST WATCH
`; } showNOAALed(true); // LED red } // Essex County: Warning { const countyId = "Windsor-Essex-Pelee"; const fakeClass = "alert-warning"; const el = getCountyElement(countyId); if (el && !manualOverrides[countyId]) applyAlertClass(el, fakeClass); const summaryEl = document.getElementById("ec-alert-summary"); if (summaryEl) { summaryEl.innerHTML += `${countyId.toUpperCase()}: TEST WARNING
`; } showECLed(true); // LED red } // Chatham-Kent: Advisory { const countyId = "Chatham-Kent-Moraviantown"; const fakeClass = "alert-advisory"; const el = getCountyElement(countyId); if (el && !manualOverrides[countyId]) applyAlertClass(el, fakeClass); const summaryEl = document.getElementById("ec-alert-summary"); if (summaryEl) { summaryEl.innerHTML += `${countyId.toUpperCase()}: TEST ADVISORY
`; } showECLed(true); // LED red } Step 5: To clear all alerts, type this in to the browser console: // Reset all counties back to "alert-none" document.querySelectorAll('.county').forEach(el => { // Remove any existing alert-* classes el.classList.remove( 'alert-watch', 'alert-warning', 'alert-emergency', 'alert-advisory', 'alert-sws' ); // Apply the neutral state el.classList.add('alert-none'); }); // Clear summaries const noaaSummary = document.getElementById("noaa-alert-summary"); const ecSummary = document.getElementById("ec-alert-summary"); if (noaaSummary) noaaSummary.innerHTML = `No active NOAA alerts for SE Michigan.`; if (ecSummary) ecSummary.innerHTML = `No active EC alerts for SW Ontario.`; // Reset LEDs document.getElementById("noaa-led")?.classList.remove("alert-active"); document.getElementById("ec-led")?.classList.remove("alert-active"); or try this: resetAlerts(); // clears counties, summaries, timestamps, and LEDs back to neutral Step 5: How to test for a service outage (being unable to access NOAA.gov or weather.gc.ca): Run these commands, seperately, into your browser console: // Simulate NOAA fetch failure showNOAALed(false); const summaryEl = document.getElementById("noaa-alert-summary"); if (summaryEl) { summaryEl.innerHTML = `Unable to fetch NOAA alerts (service error).`; } // Simulate EC fetch failure showECLed(false); const summaryEl = document.getElementById("ec-alert-summary"); if (summaryEl) { summaryEl.innerHTML = `Unable to fetch EC alerts (service error).`; } to make the LEDs turn amber too.... // Simulate NOAA fetch failure const led = document.getElementById("noaa-led"); if (led) { led.classList.remove("alert-active", "alert-none", "alert-outage"); // clear old states led.classList.add("alert-outage"); // amber state } const summaryEl = document.getElementById("noaa-alert-summary"); if (summaryEl) { summaryEl.innerHTML = `Unable to fetch EC alerts (service error).`; } // Simulate EC fetch failure const led = document.getElementById("ec-led"); if (led) { led.classList.remove("alert-active", "alert-none", "alert-outage"); // clear old states led.classList.add("alert-outage"); // amber state } const summaryEl = document.getElementById("ec-alert-summary"); if (summaryEl) { summaryEl.innerHTML = `Unable to fetch EC alerts (service error).`; } or try these: // NOAA outage const noaaLed = document.getElementById("noaa-led"); if (noaaLed) { noaaLed.classList.remove("alert-active"); noaaLed.classList.add("alert-outage"); // amber } const noaaSummary = document.getElementById("noaa-alert-summary"); if (noaaSummary) { noaaSummary.innerHTML = `Unable to fetch NOAA alerts (service error).`; } // EC outage const ecLed = document.getElementById("ec-led"); if (ecLed) { ecLed.classList.remove("alert-active"); ecLed.classList.add("alert-outage"); // amber } const ecSummary = document.getElementById("ec-alert-summary"); if (ecSummary) { ecSummary.innerHTML = `Unable to fetch EC alerts (service error).`; } Step 6: To refresh on command, just type this into console: pollAlerts(); Step 7: Since we've updated a lot of code, we can run multi-alerts better, and it auto-detects where the timestamps are, to not touch them. just insert this into your browser's console: // Mock NOAA + EC alerts (no timestamps included) const summaryLines = [ "WAYNE COUNTY: Severe Thunderstorm Warning", "WAYNE COUNTY: Tornado Watch", "OAKLAND COUNTY: Flood Advisory", "WINDSOR-ESSEX-PELEE: Tornado Watch", "CHATHAM-KENT-MORAVIANTOWN: Severe Thunderstorm Warning", "LAMBTON COUNTY: Flood Advisory" ]; // regroup alerts by county const alertsByCounty = {}; summaryLines.forEach(line => { const parts = line.split(": "); if (parts.length < 2) return; const [county, type] = parts; if (!alertsByCounty[county]) alertsByCounty[county] = []; alertsByCounty[county].push(type); }); // build summary with bullets + color coding let summaryHTML = ""; for (const county in alertsByCounty) { summaryHTML += `${county}:"; } // inject into NOAA summary element const noaaSummaryEl = document.getElementById("noaa-alert-summary"); if (noaaSummaryEl) { // preserve any existing timestamp node const timestampNode = noaaSummaryEl.querySelector(".timestamp"); noaaSummaryEl.innerHTML = summaryHTML; if (timestampNode) { noaaSummaryEl.appendChild(timestampNode); } } // inject into EC summary element const ecSummaryEl = document.getElementById("ec-alert-summary"); if (ecSummaryEl) { // preserve any existing timestamp node const timestampNode = ecSummaryEl.querySelector(".timestamp"); ecSummaryEl.innerHTML = summaryHTML; if (timestampNode) { ecSummaryEl.appendChild(timestampNode); } } Step 8: to seperate NOAA and EC alerts from each other, and to avoid duplication, try this in browser console: // Mock NOAA alerts const noaaSummaryLines = [ "WAYNE COUNTY: Severe Thunderstorm Warning (until 5:00 PM ET)", "WAYNE COUNTY: Tornado Watch (until 7:30 PM ET)", "OAKLAND COUNTY: Flood Advisory (until 9:00 PM ET)" ]; // Mock EC alerts const ecSummaryLines = [ "WINDSOR-ESSEX-PELEE: Tornado Watch (until 8:00 PM ET)", "CHATHAM-KENT-MORAVIANTOWN: Severe Thunderstorm Warning (until 5:30 PM ET)", "LAMBTON COUNTY: Flood Advisory (until 11:00 PM ET)" ]; function buildSummaryHTML(summaryLines) { const alertsByCounty = {}; summaryLines.forEach(line => { const parts = line.split(": "); if (parts.length < 2) return; const [county, type] = parts; if (!alertsByCounty[county]) alertsByCounty[county] = []; alertsByCounty[county].push(type); }); let summaryHTML = ""; for (const county in alertsByCounty) { summaryHTML += `${county}:"; } return summaryHTML; } // inject into NOAA summary element const noaaSummaryEl = document.getElementById("noaa-alert-summary"); if (noaaSummaryEl) { const timestampNode = noaaSummaryEl.querySelector(".timestamp"); noaaSummaryEl.innerHTML = buildSummaryHTML(noaaSummaryLines); if (timestampNode) noaaSummaryEl.appendChild(timestampNode); } // inject into EC summary element const ecSummaryEl = document.getElementById("ec-alert-summary"); if (ecSummaryEl) { const timestampNode = ecSummaryEl.querySelector(".timestamp"); ecSummaryEl.innerHTML = buildSummaryHTML(ecSummaryLines); if (timestampNode) ecSummaryEl.appendChild(timestampNode); } // Simulate LEDs turning red (alert active) showNOAALed(true); showECLed(true); to test if there is an outage: // Simulate NOAA outage const noaaLed = document.getElementById("noaa-led"); noaaLed.classList.remove("alert-active"); // clear red noaaLed.classList.add("alert-outage"); // amber outage // Simulate EC outage const ecLed = document.getElementById("ec-led"); ecLed.classList.remove("alert-active"); // clear red ecLed.classList.add("alert-outage"); // amber outage Since i've added a test mode, you can even simulate another alert by calling another alert from the same state and modifying the UGC for the counties: You want to intercept the fetch inside fetchUSAlerts() and return your own fake data. Here’s how to do it safely in the console: ⭐ Step 1 - Save the original fetch by running: window.originalFetch = window.fetch; ⭐ Step 2 - Override fetch for NOAA alerts window.fetch = async (url) => { if (url.includes("api.weather.gov/alerts/active")) { return new Response(JSON.stringify({ features: [ { properties: { event: "Winter Weather Advisory", expires: new Date(Date.now() + 36 * 3600 * 1000).toISOString(), geocode: { UGC: ["MIZ068", "MIZ063", "MIZ069"] }, "@id": "urn:oid:fake-test-alert-12345" } } ] }), { status: 200 }); } return window.originalFetch(url); }; ⭐ Step 3- Run your dashboard fetch fetchUSAlerts(); Your dashboard will now: - skip the real NOAA API - use your injected alert - run through the full real pipeline - update summary - apply auto‑painting - update timestamp ⭐ Step 4 - Restore original fetch when done: window.fetch = window.originalFetch; For Environment Canada, it's similar but simpler and easier and faster: ⭐ Step 1 — Override EC fetch (same as before) window.originalFetch = window.fetch; window.fetch = async (url) => { if (url.includes("onrm")) { return new Response(` Snow Squall Warning for Niagara Region Heavy snow expected. CHATHAM TEST TOKEN. ON019 `, { status: 200 }); } return window.originalFetch(url); }; The magic is here: CHATHAM TEST TOKEN Your detection logic sees “Chatham” and goes: - “Oh! This alert belongs to Chatham‑Kent‑Moraviantown” - Lights up the CK county box - Adds it to summaryLines - Applies the correct CSS class - Updates timestamp - Turns on the EC LED All without touching your code. ⭐ Step 2 — Replace EC feeds with Niagara ecFeeds.length = 0; ecFeeds.push("https://cors-proxy.thefurrycollective.ca/ec/onrm19_e.xml"); ⭐ Step 3 — Run the EC fetch fetchECAlertsRSS(); You will now see: - EC LED ON - Chatham‑Kent box lit up - Summary shows Niagara alert - Timestamp updates - No recursion - No stack overflow - No file edits ⭐ Step 4 — Restore normal behavior window.fetch = window.originalFetch; Reloading the page also resets everything.