From f123c7a5134b511a99a494179163449d94c46285 Mon Sep 17 00:00:00 2001 From: ben Date: Mon, 9 Feb 2026 17:32:17 -0400 Subject: [PATCH] fix(find-training): Fix map tile drift at low zoom and event cost HTML entities Add minZoom: 3 to prevent Google Maps WebGL tile/marker drift caused by viewport width mismatch in CSS Grid layouts. Fix event cost displaying $ instead of $ by decoding HTML entities before passing to JS. Bump version to 2.2.13 for CDN cache busting. Co-Authored-By: Claude Opus 4.6 --- Status.md | 53 +++++++++++++++++-- assets/css/find-training-map.css | 9 ++++ assets/js/find-training-map.js | 5 ++ includes/class-hvac-plugin.php | 4 +- .../class-hvac-training-map-data.php | 4 +- 5 files changed, 66 insertions(+), 9 deletions(-) diff --git a/Status.md b/Status.md index 135a1314..3b22d2db 100644 --- a/Status.md +++ b/Status.md @@ -1,8 +1,8 @@ # HVAC Community Events - Project Status -**Last Updated:** February 6, 2026 -**Current Session:** Zoho CRM Sync Production Fix -**Version:** 2.2.11 (Deployed to Production) +**Last Updated:** February 9, 2026 +**Current Session:** Map Tile Drift Fix & Event Cost Display +**Version:** 2.2.13 (Deployed to Production) --- @@ -20,7 +20,50 @@ --- -## 🎯 CURRENT SESSION - ZOHO CRM SYNC PRODUCTION FIX (Feb 6, 2026) +## 🎯 CURRENT SESSION - MAP TILE DRIFT FIX & EVENT COST DISPLAY (Feb 9, 2026) + +### Status: ✅ **COMPLETE - Deployed to Production (v2.2.13)** + +**Objective:** Fix Google Maps tile/marker drift at low zoom levels on the Find Training page, and fix event cost display showing HTML entities. + +### Issues Found & Fixed + +1. **Map Tile/Marker Drift at Low Zoom** (`assets/js/find-training-map.js`) + - **Symptom:** When zooming out to zoom 1-2, map tiles shifted ~190px right, placing markers over the ocean instead of over the US + - **Root Cause:** Google Maps WebGL renderer reads viewport width (1400px) instead of container width (1020px) in CSS Grid layouts. Tile drift = exactly `(1400 - 1020) / 2 = 190px` + - **Attempted fixes that did NOT work:** `google.maps.event.trigger(map, 'resize')`, CSS `contain: layout`, body `display: block` override, map destroy/recreate, `requestAnimationFrame` timing + - **Fix:** Added `minZoom: 3` to map options - drift is invisible at zoom 3+ but severe at zoom 1-2. Users searching for US HVAC training have no need for world-view zoom levels + - **Also added:** CSS `max-width: none !important` on Google Maps tile images to prevent theme CSS interference + +2. **Event Cost HTML Entities** (`includes/find-training/class-hvac-training-map-data.php`) + - **Symptom:** Event costs displayed as `$50` instead of `$50` in sidebar cards + - **Root Cause:** `tribe_get_formatted_cost()` returns HTML-encoded entities, which JS doesn't decode + - **Fix:** Added `html_entity_decode()` before passing cost to JavaScript + +3. **Version Bump for Cache Busting** (`includes/class-hvac-plugin.php`) + - Bumped `HVAC_VERSION` and `HVAC_PLUGIN_VERSION` from `2.2.11` to `2.2.13` + - Required because CDN/server-side caching served old JS even after deployment + - Script enqueue uses `HVAC_VERSION` as query string parameter for cache invalidation + +### Files Modified + +| File | Change | +|------|--------| +| `assets/js/find-training-map.js` | Added `minZoom: 3` to Google Maps options | +| `assets/css/find-training-map.css` | Added `max-width: none !important` for Google Maps tile images | +| `includes/find-training/class-hvac-training-map-data.php` | Added `html_entity_decode()` for event cost display | +| `includes/class-hvac-plugin.php` | Version bump `2.2.11` → `2.2.13` | + +### Verification + +- ✅ Staging: `setZoom(1)` correctly clamped to zoom 3 +- ✅ Production: `minZoom` option confirmed as 3, zoom clamping verified +- ✅ Production: Map loads at zoom 4 with all 42 trainers, 9 venues, 8 events correctly positioned +- ✅ Production: Zoom out button disables at zoom 3 + +--- + +## 📋 PREVIOUS SESSION - ZOHO CRM SYNC PRODUCTION FIX (Feb 6, 2026) ### Status: ✅ **COMPLETE - Deployed to Production (v2.2.11) - 64/64 Trainers Syncing** @@ -1047,7 +1090,7 @@ DISPLAY=:1 HEADLESS=false node test-comprehensive-validation.js ### Production Environment **URL:** https://upskillhvac.com -**Version:** 2.2.11 (latest) +**Version:** 2.2.13 (latest) **Server:** Cloudways Shared VPS --- diff --git a/assets/css/find-training-map.css b/assets/css/find-training-map.css index 37d2308f..9b9b9fc2 100644 --- a/assets/css/find-training-map.css +++ b/assets/css/find-training-map.css @@ -576,6 +576,15 @@ body .hvac-find-training-page { background: #f0f0f0; } +/* Override global img { max-width: 100% } from theme/WP that shrinks + Google Maps tile images, causing markers to drift from tiles on zoom. + See: https://developers.google.com/maps/documentation/javascript/best-practices */ +#hvac-training-map img, +#hvac-training-map .gm-style img { + max-width: none !important; + max-height: none !important; +} + /* Map Loading State */ .hvac-map-loading { display: flex; diff --git a/assets/js/find-training-map.js b/assets/js/find-training-map.js index 26950e13..9a9fda92 100644 --- a/assets/js/find-training-map.js +++ b/assets/js/find-training-map.js @@ -110,6 +110,7 @@ // Initialize responsive features this.handleWindowResize(); this.initSidebarToggle(); + }, /** @@ -169,9 +170,13 @@ mapElement.innerHTML = ''; // Create map with options + // minZoom: 3 prevents tile/marker drift at low zoom levels caused by + // Google Maps WebGL renderer reading viewport width instead of container width + // in CSS Grid layouts. Drift is invisible at zoom 4+ but severe at zoom 1-2. this.map = new google.maps.Map(mapElement, { center: this.config.defaultCenter, zoom: this.config.defaultZoom, + minZoom: 3, mapTypeControl: true, mapTypeControlOptions: { position: google.maps.ControlPosition.TOP_RIGHT diff --git a/includes/class-hvac-plugin.php b/includes/class-hvac-plugin.php index 5af78387..dd76d590 100644 --- a/includes/class-hvac-plugin.php +++ b/includes/class-hvac-plugin.php @@ -112,10 +112,10 @@ final class HVAC_Plugin { */ private function defineConstants(): void { if (!defined('HVAC_PLUGIN_VERSION')) { - define('HVAC_PLUGIN_VERSION', '2.2.11'); + define('HVAC_PLUGIN_VERSION', '2.2.13'); } if (!defined('HVAC_VERSION')) { - define('HVAC_VERSION', '2.2.11'); + define('HVAC_VERSION', '2.2.13'); } if (!defined('HVAC_PLUGIN_FILE')) { define('HVAC_PLUGIN_FILE', dirname(__DIR__) . '/hvac-community-events.php'); diff --git a/includes/find-training/class-hvac-training-map-data.php b/includes/find-training/class-hvac-training-map-data.php index 0df138ee..166cd664 100644 --- a/includes/find-training/class-hvac-training-map-data.php +++ b/includes/find-training/class-hvac-training-map-data.php @@ -956,8 +956,8 @@ class HVAC_Training_Map_Data { $event_end = tribe_get_end_date($event->ID, false, 'U'); $is_past = $event_end < time(); - // Get cost - $cost = tribe_get_formatted_cost($event->ID); + // Get cost (decode HTML entities so JS doesn't double-escape $ → $) + $cost = html_entity_decode(tribe_get_formatted_cost($event->ID), ENT_QUOTES | ENT_HTML5, 'UTF-8'); if (empty($cost)) { $cost = 'Free'; }