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 <noreply@anthropic.com>
This commit is contained in:
ben 2026-02-09 17:32:17 -04:00
parent 83ef8f7463
commit f123c7a513
5 changed files with 66 additions and 9 deletions

View file

@ -1,8 +1,8 @@
# HVAC Community Events - Project Status # HVAC Community Events - Project Status
**Last Updated:** February 6, 2026 **Last Updated:** February 9, 2026
**Current Session:** Zoho CRM Sync Production Fix **Current Session:** Map Tile Drift Fix & Event Cost Display
**Version:** 2.2.11 (Deployed to Production) **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 `&#x24;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** ### 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 ### Production Environment
**URL:** https://upskillhvac.com **URL:** https://upskillhvac.com
**Version:** 2.2.11 (latest) **Version:** 2.2.13 (latest)
**Server:** Cloudways Shared VPS **Server:** Cloudways Shared VPS
--- ---

View file

@ -576,6 +576,15 @@ body .hvac-find-training-page {
background: #f0f0f0; 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 */ /* Map Loading State */
.hvac-map-loading { .hvac-map-loading {
display: flex; display: flex;

View file

@ -110,6 +110,7 @@
// Initialize responsive features // Initialize responsive features
this.handleWindowResize(); this.handleWindowResize();
this.initSidebarToggle(); this.initSidebarToggle();
}, },
/** /**
@ -169,9 +170,13 @@
mapElement.innerHTML = ''; mapElement.innerHTML = '';
// Create map with options // 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, { this.map = new google.maps.Map(mapElement, {
center: this.config.defaultCenter, center: this.config.defaultCenter,
zoom: this.config.defaultZoom, zoom: this.config.defaultZoom,
minZoom: 3,
mapTypeControl: true, mapTypeControl: true,
mapTypeControlOptions: { mapTypeControlOptions: {
position: google.maps.ControlPosition.TOP_RIGHT position: google.maps.ControlPosition.TOP_RIGHT

View file

@ -112,10 +112,10 @@ final class HVAC_Plugin {
*/ */
private function defineConstants(): void { private function defineConstants(): void {
if (!defined('HVAC_PLUGIN_VERSION')) { if (!defined('HVAC_PLUGIN_VERSION')) {
define('HVAC_PLUGIN_VERSION', '2.2.11'); define('HVAC_PLUGIN_VERSION', '2.2.13');
} }
if (!defined('HVAC_VERSION')) { if (!defined('HVAC_VERSION')) {
define('HVAC_VERSION', '2.2.11'); define('HVAC_VERSION', '2.2.13');
} }
if (!defined('HVAC_PLUGIN_FILE')) { if (!defined('HVAC_PLUGIN_FILE')) {
define('HVAC_PLUGIN_FILE', dirname(__DIR__) . '/hvac-community-events.php'); define('HVAC_PLUGIN_FILE', dirname(__DIR__) . '/hvac-community-events.php');

View file

@ -956,8 +956,8 @@ class HVAC_Training_Map_Data {
$event_end = tribe_get_end_date($event->ID, false, 'U'); $event_end = tribe_get_end_date($event->ID, false, 'U');
$is_past = $event_end < time(); $is_past = $event_end < time();
// Get cost // Get cost (decode HTML entities so JS doesn't double-escape &#x24; → $)
$cost = tribe_get_formatted_cost($event->ID); $cost = html_entity_decode(tribe_get_formatted_cost($event->ID), ENT_QUOTES | ENT_HTML5, 'UTF-8');
if (empty($cost)) { if (empty($cost)) {
$cost = 'Free'; $cost = 'Free';
} }