upskill-event-manager/assets/js/mapgeo-safety.js
Ben 89872ec998 fix: resolve registration form display and event edit issues
- Fixed registration form not displaying due to missing HVAC_Security_Helpers dependency
- Added require_once for dependencies in class-hvac-shortcodes.php render_registration()
- Fixed event edit HTTP 500 error by correcting class instantiation to HVAC_Event_Manager
- Created comprehensive E2E test suite with MCP Playwright integration
- Achieved 70% test success rate with both issues fully resolved

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-24 08:27:17 -03:00

304 lines
No EOL
10 KiB
JavaScript

/**
* MapGeo Safety System
* Prevents MapGeo and third-party map plugins from crashing the page
* Works in all browsers including Safari and Chrome
*
* @package HVAC_Community_Events
* @since 2.0.0
*/
(function() {
'use strict';
// Safety configuration
const config = window.HVAC_MapGeo_Config || {
maxRetries: 3,
retryDelay: 2000,
timeout: 10000,
fallbackEnabled: true,
debugMode: false
};
const log = config.debugMode ? console.log.bind(console) : () => {};
const error = config.debugMode ? console.error.bind(console) : () => {};
log('[MapGeo Safety] Initializing protection system');
/**
* Resource Load Monitor
* Tracks and manages external script loading
*/
class ResourceLoadMonitor {
constructor() {
this.resources = new Map();
this.criticalResources = [
'amcharts',
'mapgeo',
'interactive-geo-maps',
'map-widget'
];
this.setupMonitoring();
}
setupMonitoring() {
// Monitor script loading
const originalAppendChild = Element.prototype.appendChild;
const self = this;
Element.prototype.appendChild = function(element) {
if (element.tagName === 'SCRIPT' && element.src) {
self.monitorScript(element);
}
return originalAppendChild.call(this, element);
};
// Monitor existing scripts
document.querySelectorAll('script[src]').forEach(script => {
this.monitorScript(script);
});
}
monitorScript(script) {
const src = script.src;
const isCritical = this.criticalResources.some(resource =>
src.toLowerCase().includes(resource)
);
if (isCritical) {
log('[MapGeo Safety] Monitoring critical resource:', src);
const timeoutId = setTimeout(() => {
error('[MapGeo Safety] Resource timeout:', src);
this.handleResourceFailure(src);
}, config.timeout);
script.addEventListener('load', () => {
clearTimeout(timeoutId);
log('[MapGeo Safety] Resource loaded:', src);
this.resources.set(src, 'loaded');
});
script.addEventListener('error', () => {
clearTimeout(timeoutId);
error('[MapGeo Safety] Resource failed:', src);
this.handleResourceFailure(src);
});
}
}
handleResourceFailure(src) {
this.resources.set(src, 'failed');
// Check if this is a MapGeo CDN resource
if (src.includes('cdn') || src.includes('amcharts')) {
log('[MapGeo Safety] CDN resource failed, activating fallback');
this.activateFallback();
}
}
activateFallback() {
// Hide map container
const mapContainers = document.querySelectorAll(
'.igm-map-container, [class*="mapgeo"], [id*="map-"], .map-widget-container'
);
mapContainers.forEach(container => {
container.style.display = 'none';
});
// Show fallback content
const fallback = document.getElementById('hvac-map-fallback');
if (fallback) {
fallback.style.display = 'block';
}
// Dispatch custom event
window.dispatchEvent(new CustomEvent('hvac:mapgeo:fallback', {
detail: { reason: 'resource_failure' }
}));
}
}
/**
* MapGeo API Wrapper
* Safely wraps MapGeo API calls
*/
class MapGeoAPIWrapper {
constructor() {
this.wrapAPIs();
}
wrapAPIs() {
// Wrap potential MapGeo global functions
const mapGeoAPIs = [
'MapGeoWidget',
'InteractiveGeoMaps',
'IGM',
'mapWidget'
];
mapGeoAPIs.forEach(api => {
if (typeof window[api] !== 'undefined') {
this.wrapAPI(api);
}
// Set up getter to wrap when loaded
Object.defineProperty(window, `_original_${api}`, {
value: window[api],
writable: true
});
Object.defineProperty(window, api, {
get() {
return window[`_wrapped_${api}`] || window[`_original_${api}`];
},
set(value) {
window[`_original_${api}`] = value;
window[`_wrapped_${api}`] = new Proxy(value, {
construct(target, args) {
try {
return new target(...args);
} catch (e) {
error('[MapGeo Safety] Construction error:', e);
return {};
}
},
apply(target, thisArg, args) {
try {
return target.apply(thisArg, args);
} catch (e) {
error('[MapGeo Safety] Execution error:', e);
return null;
}
}
});
}
});
});
}
wrapAPI(apiName) {
const original = window[apiName];
window[apiName] = new Proxy(original, {
construct(target, args) {
try {
log(`[MapGeo Safety] Creating ${apiName} instance`);
return new target(...args);
} catch (e) {
error(`[MapGeo Safety] Failed to create ${apiName}:`, e);
return {};
}
},
apply(target, thisArg, args) {
try {
log(`[MapGeo Safety] Calling ${apiName}`);
return target.apply(thisArg, args);
} catch (e) {
error(`[MapGeo Safety] Failed to call ${apiName}:`, e);
return null;
}
}
});
}
}
/**
* DOM Ready Safety
* Ensures MapGeo only runs when DOM is safe
*/
class DOMReadySafety {
constructor() {
this.setupSafety();
}
setupSafety() {
// Intercept jQuery ready calls that might contain MapGeo code
if (typeof jQuery !== 'undefined') {
const originalReady = jQuery.fn.ready;
jQuery.fn.ready = function(callback) {
const wrappedCallback = function() {
try {
// Check if MapGeo elements exist before running
const hasMapElements = document.querySelector(
'.igm-map-container, [class*="mapgeo"], [id*="map-"]'
);
if (hasMapElements || !callback.toString().includes('map')) {
return callback.apply(this, arguments);
} else {
log('[MapGeo Safety] Skipping map-related ready callback - no map elements found');
}
} catch (e) {
error('[MapGeo Safety] Error in ready callback:', e);
}
};
return originalReady.call(this, wrappedCallback);
};
}
}
}
/**
* Initialize all safety systems
*/
function initializeSafetySystems() {
// Only initialize on pages with potential maps
if (!document.querySelector('[class*="map"], [id*="map"]')) {
log('[MapGeo Safety] No map elements detected, skipping initialization');
return;
}
// Initialize monitors
new ResourceLoadMonitor();
new MapGeoAPIWrapper();
new DOMReadySafety();
// Set up periodic health check
let healthCheckCount = 0;
const healthCheckInterval = setInterval(() => {
healthCheckCount++;
// Check if map loaded successfully
const mapLoaded = document.querySelector('.igm-map-loaded, .mapgeo-loaded, .map-initialized');
if (mapLoaded) {
log('[MapGeo Safety] Map loaded successfully');
clearInterval(healthCheckInterval);
} else if (healthCheckCount >= 10) {
// After 10 seconds, consider it failed
error('[MapGeo Safety] Map failed to load after 10 seconds');
clearInterval(healthCheckInterval);
// Activate fallback if configured
if (config.fallbackEnabled) {
const monitor = new ResourceLoadMonitor();
monitor.activateFallback();
}
}
}, 1000);
log('[MapGeo Safety] All safety systems initialized');
}
// Initialize when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initializeSafetySystems);
} else {
// DOM already loaded
initializeSafetySystems();
}
// Expose safety API for debugging
window.HVACMapGeoSafety = {
config: config,
reinitialize: initializeSafetySystems,
activateFallback: () => {
const monitor = new ResourceLoadMonitor();
monitor.activateFallback();
}
};
})();