Resolves critical Safari hanging issues through multi-layered protection: Core Safari Resource Loading Bypass: - Added Safari-specific minimal asset loading in HVAC_Scripts_Styles - Prevents 35+ CSS file cascade that overwhelmed Safari rendering - Implements intelligent browser detection with fallback systems - Loads only essential CSS/JS files for Safari browsers - Dequeues non-critical assets to prevent resource overload Browser Detection Infrastructure: - Created HVAC_Browser_Detection class with accurate Safari identification - Added User-Agent parsing with version detection - Implements fallback detection methods for edge cases - Provides centralized browser compatibility services Find Trainer Assets Management: - Added HVAC_Find_Trainer_Assets class for proper WordPress hook timing - Ensures Safari-compatible script loading order - Prevents asset loading conflicts with theme integration Safari Debugging System: - Implemented HVAC_Safari_Request_Debugger for server-side monitoring - Added comprehensive Safari debugging with error tracking - Created detailed investigation documentation - Provides real-time Safari compatibility insights Performance Optimizations: - Optimized database queries in find-trainer template to prevent hanging - Implemented lazy component loading in HVAC_Plugin initialization - Reduced Astra theme override hook priorities from 999 to 50 - Removed CSS @import statements causing Safari render blocking MapGeo Integration Fixes: - Fixed JavaScript syntax error (dangling }) in MapGeo integration - Removed problematic console.log override causing Safari conflicts - Maintained full MapGeo functionality while preventing browser hangs Testing Results: - Verified with Playwright WebKit engine (Safari emulation) - Page loads successfully with complete functionality - Interactive map, trainer cards, and navigation all functional - Reduced CSS files from 35+ to 3 core files for optimal performance - No hanging or blank page issues detected 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			271 lines
		
	
	
		
			No EOL
		
	
	
		
			9.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			271 lines
		
	
	
		
			No EOL
		
	
	
		
			9.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * HVAC Safari Debugger
 | |
|  * 
 | |
|  * Comprehensive debugging for Safari browser issues
 | |
|  *
 | |
|  * @package HVAC_Community_Events
 | |
|  * @since 1.0.0
 | |
|  */
 | |
| 
 | |
| // Exit if accessed directly
 | |
| if (!defined('ABSPATH')) {
 | |
|     exit;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * HVAC Safari Debugger
 | |
|  */
 | |
| class HVAC_Safari_Debugger {
 | |
|     
 | |
|     /**
 | |
|      * Instance
 | |
|      *
 | |
|      * @var HVAC_Safari_Debugger
 | |
|      */
 | |
|     private static $instance = null;
 | |
|     
 | |
|     /**
 | |
|      * Get instance
 | |
|      */
 | |
|     public static function instance() {
 | |
|         if (null === self::$instance) {
 | |
|             self::$instance = new self();
 | |
|         }
 | |
|         return self::$instance;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Constructor
 | |
|      */
 | |
|     private function __construct() {
 | |
|         $this->init_hooks();
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Initialize hooks
 | |
|      */
 | |
|     private function init_hooks() {
 | |
|         // Add debugging scripts to find-a-trainer page
 | |
|         add_action('wp_footer', [$this, 'add_safari_debugging_script']);
 | |
|         
 | |
|         // Add debugging info to page source
 | |
|         add_action('wp_head', [$this, 'add_debug_info_to_head']);
 | |
|         
 | |
|         // AJAX handler for debug logging
 | |
|         add_action('wp_ajax_hvac_safari_debug', [$this, 'handle_safari_debug_ajax']);
 | |
|         add_action('wp_ajax_nopriv_hvac_safari_debug', [$this, 'handle_safari_debug_ajax']);
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Check if current page is find-a-trainer
 | |
|      */
 | |
|     private function is_find_trainer_page() {
 | |
|         return is_page('find-a-trainer') || 
 | |
|                strpos($_SERVER['REQUEST_URI'], 'find-a-trainer') !== false;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Add debug info to page head
 | |
|      */
 | |
|     public function add_debug_info_to_head() {
 | |
|         if (!$this->is_find_trainer_page()) {
 | |
|             return;
 | |
|         }
 | |
|         
 | |
|         $browser_detection = HVAC_Browser_Detection::instance();
 | |
|         $browser_info = $browser_detection->get_browser_info();
 | |
|         
 | |
|         ?>
 | |
|         <!-- HVAC Safari Debug Info -->
 | |
|         <script type="text/javascript">
 | |
|         console.log('=== HVAC SAFARI DEBUG INFO ===');
 | |
|         console.log('Server-side browser detection:', <?php echo json_encode($browser_info); ?>);
 | |
|         console.log('User Agent:', navigator.userAgent);
 | |
|         console.log('=== END SAFARI DEBUG INFO ===');
 | |
|         </script>
 | |
|         <?php
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Add comprehensive Safari debugging script
 | |
|      */
 | |
|     public function add_safari_debugging_script() {
 | |
|         if (!$this->is_find_trainer_page()) {
 | |
|             return;
 | |
|         }
 | |
|         
 | |
|         ?>
 | |
|         <script type="text/javascript">
 | |
|         (function() {
 | |
|             'use strict';
 | |
|             
 | |
|             console.log('🔍 HVAC Safari Debugging Started');
 | |
|             
 | |
|             // Detect browser client-side
 | |
|             var userAgent = navigator.userAgent;
 | |
|             var isSafari = /Safari/.test(userAgent) && !/Chrome/.test(userAgent) && !/Chromium/.test(userAgent);
 | |
|             var safariVersion = null;
 | |
|             
 | |
|             if (isSafari) {
 | |
|                 var versionMatch = userAgent.match(/Version\/([0-9]+(?:\.[0-9]+)*)/);
 | |
|                 if (versionMatch) {
 | |
|                     safariVersion = versionMatch[1];
 | |
|                 }
 | |
|             }
 | |
|             
 | |
|             console.log('🌐 Client-side browser detection:');
 | |
|             console.log('  - Is Safari:', isSafari);
 | |
|             console.log('  - Safari Version:', safariVersion);
 | |
|             console.log('  - User Agent:', userAgent);
 | |
|             
 | |
|             // Check script loading
 | |
|             console.log('📜 Script loading check:');
 | |
|             var scripts = document.querySelectorAll('script[src*="find-trainer"]');
 | |
|             scripts.forEach(function(script, index) {
 | |
|                 console.log('  - Script ' + (index + 1) + ':', script.src);
 | |
|                 console.log('    Loaded:', script.readyState || 'unknown');
 | |
|             });
 | |
|             
 | |
|             // Check for JavaScript errors
 | |
|             console.log('⚠️  JavaScript error monitoring active');
 | |
|             window.addEventListener('error', function(e) {
 | |
|                 console.error('🚨 JavaScript Error Detected:');
 | |
|                 console.error('  - Message:', e.message);
 | |
|                 console.error('  - Source:', e.filename);
 | |
|                 console.error('  - Line:', e.lineno);
 | |
|                 console.error('  - Column:', e.colno);
 | |
|                 console.error('  - Error:', e.error);
 | |
|                 
 | |
|                 // Send error to server for logging
 | |
|                 if (typeof hvac_find_trainer !== 'undefined' && hvac_find_trainer.ajax_url) {
 | |
|                     var xhr = new XMLHttpRequest();
 | |
|                     xhr.open('POST', hvac_find_trainer.ajax_url);
 | |
|                     xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
 | |
|                     xhr.send('action=hvac_safari_debug&type=js_error&message=' + encodeURIComponent(e.message) + '&source=' + encodeURIComponent(e.filename) + '&line=' + e.lineno);
 | |
|                 }
 | |
|             });
 | |
|             
 | |
|             // Check DOM ready state
 | |
|             console.log('📄 DOM State:', document.readyState);
 | |
|             
 | |
|             // Check jQuery
 | |
|             console.log('💰 jQuery check:');
 | |
|             if (typeof $ !== 'undefined') {
 | |
|                 console.log('  - jQuery loaded:', true);
 | |
|                 console.log('  - jQuery version:', $.fn.jquery);
 | |
|             } else {
 | |
|                 console.error('  - jQuery not loaded!');
 | |
|             }
 | |
|             
 | |
|             // Check hvac_find_trainer object
 | |
|             console.log('🎯 HVAC Find Trainer object:');
 | |
|             if (typeof hvac_find_trainer !== 'undefined') {
 | |
|                 console.log('  - Object exists:', true);
 | |
|                 console.log('  - Browser info:', hvac_find_trainer.browser_info);
 | |
|                 console.log('  - AJAX URL:', hvac_find_trainer.ajax_url);
 | |
|             } else {
 | |
|                 console.error('  - hvac_find_trainer object missing!');
 | |
|             }
 | |
|             
 | |
|             // Test ES6 features
 | |
|             console.log('🧪 ES6 Feature Tests:');
 | |
|             try {
 | |
|                 // Test arrow functions
 | |
|                 eval('var testArrow = () => "arrow works"');
 | |
|                 console.log('  - Arrow functions: ✅');
 | |
|             } catch (e) {
 | |
|                 console.log('  - Arrow functions: ❌ (' + e.message + ')');
 | |
|             }
 | |
|             
 | |
|             try {
 | |
|                 // Test template literals
 | |
|                 eval('var testTemplate = `template works`');
 | |
|                 console.log('  - Template literals: ✅');
 | |
|             } catch (e) {
 | |
|                 console.log('  - Template literals: ❌ (' + e.message + ')');
 | |
|             }
 | |
|             
 | |
|             try {
 | |
|                 // Test const/let
 | |
|                 eval('const testConst = "const works"');
 | |
|                 console.log('  - const/let: ✅');
 | |
|             } catch (e) {
 | |
|                 console.log('  - const/let: ❌ (' + e.message + ')');
 | |
|             }
 | |
|             
 | |
|             // Check page elements
 | |
|             setTimeout(function() {
 | |
|                 console.log('🎨 Page Elements Check:');
 | |
|                 console.log('  - Filter buttons:', document.querySelectorAll('.hvac-filter-btn').length);
 | |
|                 console.log('  - Trainer cards:', document.querySelectorAll('.hvac-trainer-card').length);
 | |
|                 console.log('  - Search box:', !!document.querySelector('#hvac-trainer-search'));
 | |
|                 console.log('  - Map container:', !!document.querySelector('.hvac-map-section'));
 | |
|                 
 | |
|                 // Test click functionality
 | |
|                 var filterBtn = document.querySelector('.hvac-filter-btn');
 | |
|                 if (filterBtn) {
 | |
|                     console.log('  - First filter button clickable:', typeof filterBtn.onclick !== 'undefined' || filterBtn.addEventListener !== undefined);
 | |
|                 }
 | |
|                 
 | |
|                 console.log('🔍 Safari Debug Complete - Check console for any errors above');
 | |
|                 
 | |
|                 // Send completion status to server
 | |
|                 if (typeof hvac_find_trainer !== 'undefined' && hvac_find_trainer.ajax_url) {
 | |
|                     var xhr = new XMLHttpRequest();
 | |
|                     xhr.open('POST', hvac_find_trainer.ajax_url);
 | |
|                     xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
 | |
|                     xhr.send('action=hvac_safari_debug&type=debug_complete&safari=' + isSafari + '&version=' + safariVersion);
 | |
|                 }
 | |
|             }, 2000);
 | |
|             
 | |
|         })();
 | |
|         </script>
 | |
|         <?php
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Handle AJAX debug requests
 | |
|      */
 | |
|     public function handle_safari_debug_ajax() {
 | |
|         $type = sanitize_text_field($_POST['type'] ?? '');
 | |
|         
 | |
|         switch ($type) {
 | |
|             case 'js_error':
 | |
|                 $message = sanitize_text_field($_POST['message'] ?? '');
 | |
|                 $source = sanitize_text_field($_POST['source'] ?? '');
 | |
|                 $line = intval($_POST['line'] ?? 0);
 | |
|                 
 | |
|                 error_log("[HVAC Safari Debug] JS Error: {$message} in {$source}:{$line}");
 | |
|                 break;
 | |
|                 
 | |
|             case 'debug_complete':
 | |
|                 $is_safari = sanitize_text_field($_POST['safari'] ?? 'false');
 | |
|                 $version = sanitize_text_field($_POST['version'] ?? '');
 | |
|                 
 | |
|                 error_log("[HVAC Safari Debug] Debug complete - Safari: {$is_safari}, Version: {$version}");
 | |
|                 break;
 | |
|         }
 | |
|         
 | |
|         wp_die();
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Get debug report for admin
 | |
|      */
 | |
|     public function get_debug_report() {
 | |
|         $browser_detection = HVAC_Browser_Detection::instance();
 | |
|         
 | |
|         return [
 | |
|             'browser_info' => $browser_detection->get_browser_info(),
 | |
|             'find_trainer_assets' => class_exists('HVAC_Find_Trainer_Assets') ? 
 | |
|                 HVAC_Find_Trainer_Assets::instance()->get_compatibility_info() : 'Class not found',
 | |
|             'server_info' => [
 | |
|                 'php_version' => PHP_VERSION,
 | |
|                 'wp_version' => get_bloginfo('version'),
 | |
|                 'theme' => get_template(),
 | |
|                 'plugins' => get_option('active_plugins'),
 | |
|             ]
 | |
|         ];
 | |
|     }
 | |
| }
 |