More Featured
Webinars, Podcasts & Videos

Editor’s Pick This Week

Continuity Insights ACP
2 min read

Continuity Insights, Association of Continuity Professionals Launch Strategic Media Partnership

Collaboration will elevate thought leadership, professional development, and community engagement across the resilience profession

Latest Products & Services
3 min read

Verified Mapping Data Bridges Emergency Response, Daily Operations

life-safety data
Critical Response Group’s new Map Builder turns field-verified life-safety data into customizable maps to support continuity planning, emergency response, and day-to-day operational readiness.
3 min read

New Dashboard Measures Cybersecurity Progress

cyber risk management
CTG’s new cyber resilience scoring dashboard helps organizations quantify risk, prioritize remediation, and track measurable improvement over time.
2 min read

Watch Duty Expands To Deliver Real-Time Wildfire Alerts Across The U.S.

Wildfire Alerts
Watch Duty now offers nationwide coverage, ensuring that every community has access to verified, real-time wildfire information.
Subscribe To ENews
Submit a Press Release
Webinars & Podcasts
Job Board

Receive the latest articles in your inbox

`; if (isWallpaper) { container.classList.remove('is-active'); iframe.addEventListener('load', () => { requestAnimationFrame(() => { container.classList.add('is-active'); }); }, { once: true }); } container.appendChild(iframe); container.setAttribute('data-active-id', String(spot.id)); container.style.display = 'block'; if (!isWallpaper) { requestAnimationFrame(() => { container.classList.add('is-active'); }); } } function clearSlot(container) { const activeId = container.getAttribute('data-active-id'); if (activeId) { loadedAdKeys.delete(container.id + ':' + activeId); } clearRefreshTimer(container.id); container.classList.remove('is-active'); container.style.display = 'none'; container.setAttribute('data-active-id', ''); container.innerHTML = ''; } function startRefreshTimer(slot, spot) { clearRefreshTimer(slot.containerId); const timer = setInterval(() => { if (!canRefreshAds()) return; const container = document.getElementById(slot.containerId); if (!container) { clearRefreshTimer(slot.containerId); return; } if (!window.matchMedia(spot.query).matches) { clearRefreshTimer(slot.containerId); clearSlot(container); return; } injectIframeAd(container, spot, { force: true }); }, REFRESH_MS); refreshTimers.set(slot.containerId, timer); } function processSlot(slot) { const container = document.getElementById(slot.containerId); if (!container) return; const match = slot.responsive.find(res => window.matchMedia(res.query).matches); if (match) { injectIframeAd(container, match); container.style.display = 'block'; if (REFRESH_SLOT_IDS.has(slot.containerId)) { startRefreshTimer(slot, match); } else { clearRefreshTimer(slot.containerId); } } else { clearSlot(container); } } function checkSlots(mode = 'all') { adSlots.forEach(slot => { const isCritical = CRITICAL_SLOT_IDS.has(slot.containerId); const isScrollBound = SCROLL_SLOT_IDS.has(slot.containerId); if (mode === 'critical') { if (!isCritical) return; } else if (mode === 'delayed') { if (isCritical || isScrollBound) return; } else if (mode === 'scroll') { if (!isScrollBound) return; } processSlot(slot); }); } function debounce(fn, wait) { let t; return function() { clearTimeout(t); t = setTimeout(fn, wait); }; } const handleChange = debounce(() => { let mode = 'critical'; if (delayedStarted) mode = 'all'; else if (scrollStarted) mode = 'all'; adSlots.forEach(slot => { const isCritical = CRITICAL_SLOT_IDS.has(slot.containerId); const isScrollBound = SCROLL_SLOT_IDS.has(slot.containerId); if (mode === 'critical' && !isCritical) return; if (!delayedStarted && !isCritical && !isScrollBound) return; if (!scrollStarted && isScrollBound) return; processSlot(slot); }); }, 150); function bindMediaListeners() { const allQueries = [...new Set(adSlots.flatMap(s => s.responsive.map(r => r.query)))]; allQueries.forEach(q => { const mql = window.matchMedia(q); if (typeof mql.addEventListener === 'function') { mql.addEventListener('change', handleChange); } else if (typeof mql.addListener === 'function') { mql.addListener(handleChange); } }); window.addEventListener('resize', handleChange, { passive: true }); window.addEventListener('orientationchange', handleChange, { passive: true }); } function startDelayed() { if (delayedStarted) return; delayedStarted = true; checkSlots('delayed'); } function startScrollAds() { if (scrollStarted) return; scrollStarted = true; checkSlots('scroll'); } function setupScrollTrigger() { const handleScroll = () => { if (window.scrollY >= 200) { startScrollAds(); window.removeEventListener('scroll', handleScroll); } }; window.addEventListener('scroll', handleScroll, { passive: true }); } function setupFocusVisibilityRefresh() { document.addEventListener('visibilitychange', () => { pageHasFocus = document.hasFocus(); if (!canRefreshAds()) { REFRESH_SLOT_IDS.forEach(clearRefreshTimer); return; } adSlots.forEach(slot => { if (!REFRESH_SLOT_IDS.has(slot.containerId)) return; processSlot(slot); }); }); window.addEventListener('focus', () => { pageHasFocus = true; adSlots.forEach(slot => { if (!REFRESH_SLOT_IDS.has(slot.containerId)) return; processSlot(slot); }); }); window.addEventListener('blur', () => { pageHasFocus = false; REFRESH_SLOT_IDS.forEach(clearRefreshTimer); }); } function init() { bindMediaListeners(); setupFocusVisibilityRefresh(); // Load only the critical slots immediately. checkSlots('critical'); // Load adhesion slots only after user scroll. setupScrollTrigger(); // Load all other non-critical / non-scroll slots after a short delay. const launchDelayed = () => { setTimeout(startDelayed, DELAY_MS); }; if (document.visibilityState === 'visible') { launchDelayed(); } else { document.addEventListener('visibilitychange', function onVis() { if (document.visibilityState === 'visible') { document.removeEventListener('visibilitychange', onVis); launchDelayed(); } }); } } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init, { once: true }); } else { init(); } })();