Compare commits
5 commits
83ef8f7463
...
0b033f7f4f
| Author | SHA1 | Date | |
|---|---|---|---|
| 0b033f7f4f | |||
| 95382ac3a3 | |||
| 9dbe472c45 | |||
| 4104c80669 | |||
| f123c7a513 |
6 changed files with 390 additions and 1184 deletions
|
|
@ -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;
|
||||||
|
|
@ -659,6 +668,37 @@ body .hvac-find-training-page {
|
||||||
background: var(--hvac-event-color);
|
background: var(--hvac-event-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reset Map View Button */
|
||||||
|
.hvac-reset-map-btn {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 24px;
|
||||||
|
right: 12px;
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
background: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 10;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
transition: background 0.2s, box-shadow 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hvac-reset-map-btn:hover {
|
||||||
|
background: #f0f0f0;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hvac-reset-map-btn .dashicons {
|
||||||
|
font-size: 18px;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
color: var(--hvac-text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
/* Map Toggles Overlay */
|
/* Map Toggles Overlay */
|
||||||
.hvac-map-toggles {
|
.hvac-map-toggles {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
@ -1220,19 +1260,49 @@ body .hvac-find-training-page {
|
||||||
--hvac-sidebar-width: 320px;
|
--hvac-sidebar-width: 320px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* On mobile/tablet, allow natural page scrolling instead of fixed viewport */
|
||||||
|
.hvac-find-training-page {
|
||||||
|
height: auto !important;
|
||||||
|
overflow: visible !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Keep filter bar visible while scrolling */
|
||||||
|
.hvac-filter-bar {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-bar .hvac-filter-bar {
|
||||||
|
top: 46px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Switch to stacked layout - map on top, sidebar below */
|
/* Switch to stacked layout - map on top, sidebar below */
|
||||||
.hvac-map-layout {
|
.hvac-map-layout {
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
"map"
|
"map"
|
||||||
"sidebar" !important;
|
"sidebar" !important;
|
||||||
grid-template-columns: 1fr !important;
|
grid-template-columns: 1fr !important;
|
||||||
grid-template-rows: 55vh 1fr !important;
|
grid-template-rows: 55vh auto !important;
|
||||||
|
overflow: visible !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Map needs explicit height since page no longer constrains it */
|
||||||
|
.hvac-map-container {
|
||||||
|
min-height: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hvac-sidebar {
|
.hvac-sidebar {
|
||||||
border-right: none;
|
border-right: none;
|
||||||
border-top: 1px solid var(--hvac-border);
|
border-top: 1px solid var(--hvac-border);
|
||||||
max-height: 45vh;
|
overflow-x: hidden !important;
|
||||||
|
overflow-y: visible !important;
|
||||||
|
max-height: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sidebar content scrolls with page, not independently */
|
||||||
|
.hvac-sidebar-content {
|
||||||
|
overflow-y: visible !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Show sidebar toggle on tablet/mobile */
|
/* Show sidebar toggle on tablet/mobile */
|
||||||
|
|
@ -1243,7 +1313,7 @@ body .hvac-find-training-page {
|
||||||
/* Collapsible sidebar */
|
/* Collapsible sidebar */
|
||||||
.hvac-sidebar.collapsed {
|
.hvac-sidebar.collapsed {
|
||||||
max-height: 80px;
|
max-height: 80px;
|
||||||
overflow: hidden;
|
overflow: hidden !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hvac-sidebar.collapsed .hvac-sidebar-content {
|
.hvac-sidebar.collapsed .hvac-sidebar-content {
|
||||||
|
|
@ -1292,14 +1362,20 @@ body .hvac-find-training-page {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hvac-visibility-toggles {
|
.hvac-marker-checkbox {
|
||||||
gap: 8px;
|
width: 12px;
|
||||||
padding: 4px 0;
|
height: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hvac-toggle-dot {
|
.hvac-marker-checkbox::after {
|
||||||
width: 14px;
|
left: 2px;
|
||||||
height: 14px;
|
top: 0px;
|
||||||
|
width: 3px;
|
||||||
|
height: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hvac-marker-toggle {
|
||||||
|
margin-right: 2px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1309,11 +1385,7 @@ body .hvac-find-training-page {
|
||||||
|
|
||||||
@media (max-width: 767px) {
|
@media (max-width: 767px) {
|
||||||
.hvac-map-layout {
|
.hvac-map-layout {
|
||||||
grid-template-rows: 50vh 1fr;
|
grid-template-rows: 50vh auto;
|
||||||
}
|
|
||||||
|
|
||||||
.hvac-sidebar {
|
|
||||||
max-height: 50vh;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Filter bar adjustments */
|
/* Filter bar adjustments */
|
||||||
|
|
@ -1382,7 +1454,7 @@ body .hvac-find-training-page {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hvac-visibility-toggles {
|
.hvac-marker-toggle {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1443,11 +1515,7 @@ body .hvac-find-training-page {
|
||||||
|
|
||||||
@media (max-width: 480px) {
|
@media (max-width: 480px) {
|
||||||
.hvac-map-layout {
|
.hvac-map-layout {
|
||||||
grid-template-rows: 45vh 1fr;
|
grid-template-rows: 45vh auto;
|
||||||
}
|
|
||||||
|
|
||||||
.hvac-sidebar {
|
|
||||||
max-height: 55vh;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hvac-map-legend {
|
.hvac-map-legend {
|
||||||
|
|
@ -1702,10 +1770,12 @@ body .hvac-find-training-page {
|
||||||
border-bottom: 2px solid var(--hvac-border);
|
border-bottom: 2px solid var(--hvac-border);
|
||||||
margin: 0 -16px;
|
margin: 0 -16px;
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hvac-tab {
|
.hvac-tab {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
padding: 10px 8px;
|
padding: 10px 8px;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
|
|
@ -1717,6 +1787,8 @@ body .hvac-find-training-page {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hvac-tab:hover {
|
.hvac-tab:hover {
|
||||||
|
|
@ -1738,57 +1810,71 @@ body .hvac-find-training-page {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Visibility Toggles */
|
/* Marker Toggle Checkboxes (inline in tab buttons) */
|
||||||
.hvac-visibility-toggles {
|
.hvac-marker-toggle {
|
||||||
display: flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
|
||||||
gap: 12px;
|
|
||||||
padding: 8px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hvac-visibility-toggle {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
margin-right: 4px;
|
||||||
|
vertical-align: middle;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hvac-visibility-toggle input {
|
.hvac-marker-toggle input {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hvac-toggle-dot {
|
.hvac-marker-checkbox {
|
||||||
width: 18px;
|
width: 14px;
|
||||||
height: 18px;
|
height: 14px;
|
||||||
border-radius: 50%;
|
border: 2px solid #999;
|
||||||
border: 2px solid;
|
border-radius: 3px;
|
||||||
transition: all 0.2s;
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
transition: all 0.15s ease;
|
||||||
|
background: #fff;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hvac-toggle-trainer {
|
.hvac-marker-checkbox::after {
|
||||||
background: var(--hvac-trainer-color);
|
content: '';
|
||||||
border-color: #5a8a1a;
|
position: absolute;
|
||||||
|
left: 3px;
|
||||||
|
top: 0px;
|
||||||
|
width: 4px;
|
||||||
|
height: 8px;
|
||||||
|
border: solid #fff;
|
||||||
|
border-width: 0 2px 2px 0;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.15s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hvac-toggle-venue {
|
.hvac-marker-toggle input:checked + .hvac-marker-checkbox::after {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Category-specific checkbox colors */
|
||||||
|
.hvac-marker-toggle-trainer input:checked + .hvac-marker-checkbox {
|
||||||
|
background: #6aad1e;
|
||||||
|
border-color: #6aad1e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hvac-marker-toggle-venue input:checked + .hvac-marker-checkbox {
|
||||||
background: var(--hvac-venue-color);
|
background: var(--hvac-venue-color);
|
||||||
border-color: #6fa024;
|
border-color: var(--hvac-venue-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.hvac-toggle-event {
|
.hvac-marker-toggle-event input:checked + .hvac-marker-checkbox {
|
||||||
background: var(--hvac-event-color);
|
background: var(--hvac-event-color);
|
||||||
border-color: #0a9a8a;
|
border-color: var(--hvac-event-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.hvac-visibility-toggle input:not(:checked) + .hvac-toggle-dot {
|
.hvac-marker-toggle:hover .hvac-marker-checkbox {
|
||||||
background: #f5f5f5;
|
border-color: #666;
|
||||||
border-color: #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hvac-visibility-toggle:hover .hvac-toggle-dot {
|
|
||||||
transform: scale(1.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tab Panels */
|
/* Tab Panels */
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
visibleEvents: [],
|
visibleEvents: [],
|
||||||
|
|
||||||
// Active tab
|
// Active tab
|
||||||
activeTab: 'trainers',
|
activeTab: 'events',
|
||||||
|
|
||||||
// Items per page for load more
|
// Items per page for load more
|
||||||
itemsPerPage: 6,
|
itemsPerPage: 6,
|
||||||
|
|
@ -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
|
||||||
|
|
@ -322,6 +327,9 @@
|
||||||
|
|
||||||
// Fit bounds if we have markers
|
// Fit bounds if we have markers
|
||||||
this.fitBounds();
|
this.fitBounds();
|
||||||
|
|
||||||
|
// Highlight markers for active tab
|
||||||
|
this.highlightMarkersForTab(this.activeTab);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -505,6 +513,122 @@
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get highlighted trainer marker icon (larger, brighter stroke)
|
||||||
|
*/
|
||||||
|
getTrainerIconHighlighted: function() {
|
||||||
|
if (hvacFindTraining.marker_icons?.trainer) {
|
||||||
|
return {
|
||||||
|
url: hvacFindTraining.marker_icons.trainer,
|
||||||
|
scaledSize: new google.maps.Size(40, 40),
|
||||||
|
anchor: new google.maps.Point(20, 20)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
path: google.maps.SymbolPath.CIRCLE,
|
||||||
|
fillColor: '#f0f7e8',
|
||||||
|
fillOpacity: 1,
|
||||||
|
strokeColor: '#3d6e00',
|
||||||
|
strokeWeight: 3,
|
||||||
|
scale: 14
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get highlighted champion marker icon (larger, brighter stroke)
|
||||||
|
*/
|
||||||
|
getChampionIconHighlighted: function() {
|
||||||
|
return {
|
||||||
|
path: google.maps.SymbolPath.CIRCLE,
|
||||||
|
fillColor: '#f0f7e8',
|
||||||
|
fillOpacity: 1,
|
||||||
|
strokeColor: '#e0e0e0',
|
||||||
|
strokeWeight: 3.5,
|
||||||
|
scale: 14
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get highlighted venue marker icon (larger, brighter stroke)
|
||||||
|
*/
|
||||||
|
getVenueIconHighlighted: function() {
|
||||||
|
if (hvacFindTraining.marker_icons?.venue) {
|
||||||
|
return {
|
||||||
|
url: hvacFindTraining.marker_icons.venue,
|
||||||
|
scaledSize: new google.maps.Size(40, 40),
|
||||||
|
anchor: new google.maps.Point(20, 20)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
path: google.maps.SymbolPath.BACKWARD_CLOSED_ARROW,
|
||||||
|
fillColor: '#89c92e',
|
||||||
|
fillOpacity: 1,
|
||||||
|
strokeColor: '#e0e0e0',
|
||||||
|
strokeWeight: 3,
|
||||||
|
scale: 8
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get highlighted event marker icon (larger, brighter stroke)
|
||||||
|
*/
|
||||||
|
getEventIconHighlighted: function() {
|
||||||
|
if (hvacFindTraining.marker_icons?.event) {
|
||||||
|
return {
|
||||||
|
url: hvacFindTraining.marker_icons.event,
|
||||||
|
scaledSize: new google.maps.Size(40, 40),
|
||||||
|
anchor: new google.maps.Point(20, 20)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
path: google.maps.SymbolPath.CIRCLE,
|
||||||
|
fillColor: '#0ebaa6',
|
||||||
|
fillOpacity: 1,
|
||||||
|
strokeColor: '#e0e0e0',
|
||||||
|
strokeWeight: 3,
|
||||||
|
scale: 11
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Highlight markers for the active tab category.
|
||||||
|
* Active tab markers get larger icons + higher zIndex.
|
||||||
|
* Inactive tab markers revert to normal icons + default zIndex.
|
||||||
|
*/
|
||||||
|
highlightMarkersForTab: function(tab) {
|
||||||
|
if (!this.map) return;
|
||||||
|
|
||||||
|
const DEFAULT_Z = 1;
|
||||||
|
const HIGHLIGHT_Z = 100;
|
||||||
|
|
||||||
|
// Trainer markers
|
||||||
|
const trainerHighlighted = (tab === 'trainers');
|
||||||
|
this.trainerMarkers.forEach(function(marker) {
|
||||||
|
const isChampion = marker.trainerData && marker.trainerData.is_champion;
|
||||||
|
if (trainerHighlighted) {
|
||||||
|
marker.setIcon(isChampion ? HVACTrainingMap.getChampionIconHighlighted() : HVACTrainingMap.getTrainerIconHighlighted());
|
||||||
|
marker.setZIndex(HIGHLIGHT_Z);
|
||||||
|
} else {
|
||||||
|
marker.setIcon(isChampion ? HVACTrainingMap.getChampionIcon() : HVACTrainingMap.getTrainerIcon());
|
||||||
|
marker.setZIndex(DEFAULT_Z);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Venue markers
|
||||||
|
const venueHighlighted = (tab === 'venues');
|
||||||
|
this.venueMarkers.forEach(function(marker) {
|
||||||
|
marker.setIcon(venueHighlighted ? HVACTrainingMap.getVenueIconHighlighted() : HVACTrainingMap.getVenueIcon());
|
||||||
|
marker.setZIndex(venueHighlighted ? HIGHLIGHT_Z : DEFAULT_Z);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Event markers
|
||||||
|
const eventHighlighted = (tab === 'events');
|
||||||
|
this.eventMarkers.forEach(function(marker) {
|
||||||
|
marker.setIcon(eventHighlighted ? HVACTrainingMap.getEventIconHighlighted() : HVACTrainingMap.getEventIcon());
|
||||||
|
marker.setZIndex(eventHighlighted ? HIGHLIGHT_Z : DEFAULT_Z);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize marker clustering
|
* Initialize marker clustering
|
||||||
*/
|
*/
|
||||||
|
|
@ -1152,6 +1276,11 @@
|
||||||
$('#hvac-load-more').on('click', function() {
|
$('#hvac-load-more').on('click', function() {
|
||||||
self.loadMoreTrainers();
|
self.loadMoreTrainers();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Reset map view button
|
||||||
|
$('#hvac-reset-map').on('click', function() {
|
||||||
|
self.resetMapView();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1357,6 +1486,14 @@
|
||||||
this.map.setZoom(zoom || 10);
|
this.map.setZoom(zoom || 10);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset map to fit all markers (or default view if none)
|
||||||
|
*/
|
||||||
|
resetMapView: function() {
|
||||||
|
if (!this.map) return;
|
||||||
|
this.fitBounds();
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sync sidebar lists with visible map viewport
|
* Sync sidebar lists with visible map viewport
|
||||||
*/
|
*/
|
||||||
|
|
@ -1412,14 +1549,16 @@
|
||||||
* Show loading state
|
* Show loading state
|
||||||
*/
|
*/
|
||||||
showLoading: function() {
|
showLoading: function() {
|
||||||
$('#hvac-trainer-grid').html('<div class="hvac-grid-loading"><span class="dashicons dashicons-update-alt hvac-spin"></span> Loading trainers...</div>');
|
const gridId = this.activeTab === 'events' ? '#hvac-event-grid' : this.activeTab === 'venues' ? '#hvac-venue-grid' : '#hvac-trainer-grid';
|
||||||
|
const label = this.activeTab === 'events' ? 'events' : this.activeTab === 'venues' ? 'venues' : 'trainers';
|
||||||
|
$(gridId).html('<div class="hvac-grid-loading"><span class="dashicons dashicons-update-alt hvac-spin"></span> Loading ' + label + '...</div>');
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hide loading state
|
* Hide loading state
|
||||||
*/
|
*/
|
||||||
hideLoading: function() {
|
hideLoading: function() {
|
||||||
$('#hvac-trainer-grid .hvac-grid-loading').remove();
|
$('.hvac-grid-loading').remove();
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1502,6 +1641,9 @@
|
||||||
// Update search placeholder
|
// Update search placeholder
|
||||||
this.updateSearchPlaceholder(tab);
|
this.updateSearchPlaceholder(tab);
|
||||||
|
|
||||||
|
// Highlight markers for active tab
|
||||||
|
this.highlightMarkersForTab(tab);
|
||||||
|
|
||||||
// Reset displayed count for current tab
|
// Reset displayed count for current tab
|
||||||
this.displayedCounts[tab] = 0;
|
this.displayedCounts[tab] = 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.18');
|
||||||
}
|
}
|
||||||
if (!defined('HVAC_VERSION')) {
|
if (!defined('HVAC_VERSION')) {
|
||||||
define('HVAC_VERSION', '2.2.11');
|
define('HVAC_VERSION', '2.2.18');
|
||||||
}
|
}
|
||||||
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');
|
||||||
|
|
|
||||||
|
|
@ -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 $ → $)
|
||||||
$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';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,15 +22,15 @@ $api_key_configured = $find_training->is_api_key_configured();
|
||||||
|
|
||||||
<div class="hvac-find-training-page">
|
<div class="hvac-find-training-page">
|
||||||
<!-- Skip link for accessibility -->
|
<!-- Skip link for accessibility -->
|
||||||
<a href="#hvac-trainer-grid" class="hvac-skip-link">Skip to trainer results</a>
|
<a href="#hvac-event-grid" class="hvac-skip-link">Skip to event results</a>
|
||||||
|
|
||||||
<!-- Compact Filter Bar -->
|
<!-- Compact Filter Bar -->
|
||||||
<div class="hvac-filter-bar" role="search" aria-label="Filter trainers and venues">
|
<div class="hvac-filter-bar" role="search" aria-label="Filter events, trainers, and venues">
|
||||||
<div class="hvac-filter-bar-inner">
|
<div class="hvac-filter-bar-inner">
|
||||||
<!-- Search -->
|
<!-- Search -->
|
||||||
<div class="hvac-filter-item hvac-filter-search">
|
<div class="hvac-filter-item hvac-filter-search">
|
||||||
<span class="dashicons dashicons-search" aria-hidden="true"></span>
|
<span class="dashicons dashicons-search" aria-hidden="true"></span>
|
||||||
<input type="text" id="hvac-training-search" placeholder="Search trainers..." aria-label="Search trainers">
|
<input type="text" id="hvac-training-search" placeholder="Search events..." aria-label="Search events">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Info Button -->
|
<!-- Info Button -->
|
||||||
|
|
@ -137,31 +137,27 @@ $api_key_configured = $find_training->is_api_key_configured();
|
||||||
<div class="hvac-sidebar-header">
|
<div class="hvac-sidebar-header">
|
||||||
<!-- Tab Navigation -->
|
<!-- Tab Navigation -->
|
||||||
<div class="hvac-sidebar-tabs" role="tablist" aria-label="Browse by category">
|
<div class="hvac-sidebar-tabs" role="tablist" aria-label="Browse by category">
|
||||||
<button role="tab" class="hvac-tab active" data-tab="trainers" aria-selected="true" aria-controls="hvac-panel-trainers">
|
<button role="tab" class="hvac-tab active" data-tab="events" aria-selected="true" aria-controls="hvac-panel-events">
|
||||||
|
<label class="hvac-marker-toggle hvac-marker-toggle-event" title="Show events on map" onclick="event.stopPropagation()">
|
||||||
|
<input type="checkbox" id="hvac-show-events" checked>
|
||||||
|
<span class="hvac-marker-checkbox"></span>
|
||||||
|
</label>
|
||||||
|
Events (<span data-count="events">0</span>)
|
||||||
|
</button>
|
||||||
|
<button role="tab" class="hvac-tab" data-tab="trainers" aria-selected="false" aria-controls="hvac-panel-trainers">
|
||||||
|
<label class="hvac-marker-toggle hvac-marker-toggle-trainer" title="Show trainers on map" onclick="event.stopPropagation()">
|
||||||
|
<input type="checkbox" id="hvac-show-trainers" checked>
|
||||||
|
<span class="hvac-marker-checkbox"></span>
|
||||||
|
</label>
|
||||||
Trainers (<span data-count="trainers">0</span>)
|
Trainers (<span data-count="trainers">0</span>)
|
||||||
</button>
|
</button>
|
||||||
<button role="tab" class="hvac-tab" data-tab="venues" aria-selected="false" aria-controls="hvac-panel-venues">
|
<button role="tab" class="hvac-tab" data-tab="venues" aria-selected="false" aria-controls="hvac-panel-venues">
|
||||||
|
<label class="hvac-marker-toggle hvac-marker-toggle-venue" title="Show venues on map" onclick="event.stopPropagation()">
|
||||||
|
<input type="checkbox" id="hvac-show-venues" checked>
|
||||||
|
<span class="hvac-marker-checkbox"></span>
|
||||||
|
</label>
|
||||||
Venues (<span data-count="venues">0</span>)
|
Venues (<span data-count="venues">0</span>)
|
||||||
</button>
|
</button>
|
||||||
<button role="tab" class="hvac-tab" data-tab="events" aria-selected="false" aria-controls="hvac-panel-events">
|
|
||||||
Events (<span data-count="events">0</span>)
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Visibility Toggles (moved from map overlay) -->
|
|
||||||
<div class="hvac-visibility-toggles">
|
|
||||||
<label class="hvac-visibility-toggle" title="Show trainers on map">
|
|
||||||
<input type="checkbox" id="hvac-show-trainers" checked>
|
|
||||||
<span class="hvac-toggle-dot hvac-toggle-trainer"></span>
|
|
||||||
</label>
|
|
||||||
<label class="hvac-visibility-toggle" title="Show venues on map">
|
|
||||||
<input type="checkbox" id="hvac-show-venues" checked>
|
|
||||||
<span class="hvac-toggle-dot hvac-toggle-venue"></span>
|
|
||||||
</label>
|
|
||||||
<label class="hvac-visibility-toggle" title="Show events on map">
|
|
||||||
<input type="checkbox" id="hvac-show-events" checked>
|
|
||||||
<span class="hvac-toggle-dot hvac-toggle-event"></span>
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Mobile collapse toggle -->
|
<!-- Mobile collapse toggle -->
|
||||||
|
|
@ -175,26 +171,26 @@ $api_key_configured = $find_training->is_api_key_configured();
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="hvac-sidebar-content" class="hvac-sidebar-content">
|
<div id="hvac-sidebar-content" class="hvac-sidebar-content">
|
||||||
<!-- Trainers Panel -->
|
<!-- Events Panel -->
|
||||||
<div role="tabpanel" id="hvac-panel-trainers" class="hvac-tab-panel active" aria-labelledby="tab-trainers">
|
<div role="tabpanel" id="hvac-panel-events" class="hvac-tab-panel active" aria-labelledby="tab-events">
|
||||||
<div id="hvac-trainer-grid" class="hvac-item-list">
|
<div id="hvac-event-grid" class="hvac-item-list">
|
||||||
<div class="hvac-grid-loading">
|
<div class="hvac-grid-loading">
|
||||||
<span class="dashicons dashicons-update-alt hvac-spin" aria-hidden="true"></span>
|
<span class="dashicons dashicons-update-alt hvac-spin" aria-hidden="true"></span>
|
||||||
Loading trainers...
|
Loading events...
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Trainers Panel -->
|
||||||
|
<div role="tabpanel" id="hvac-panel-trainers" class="hvac-tab-panel" aria-labelledby="tab-trainers" hidden>
|
||||||
|
<div id="hvac-trainer-grid" class="hvac-item-list"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Venues Panel -->
|
<!-- Venues Panel -->
|
||||||
<div role="tabpanel" id="hvac-panel-venues" class="hvac-tab-panel" aria-labelledby="tab-venues" hidden>
|
<div role="tabpanel" id="hvac-panel-venues" class="hvac-tab-panel" aria-labelledby="tab-venues" hidden>
|
||||||
<div id="hvac-venue-grid" class="hvac-item-list"></div>
|
<div id="hvac-venue-grid" class="hvac-item-list"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Events Panel -->
|
|
||||||
<div role="tabpanel" id="hvac-panel-events" class="hvac-tab-panel" aria-labelledby="tab-events" hidden>
|
|
||||||
<div id="hvac-event-grid" class="hvac-item-list"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Load More Button -->
|
<!-- Load More Button -->
|
||||||
<div class="hvac-load-more-wrapper" style="display: none;">
|
<div class="hvac-load-more-wrapper" style="display: none;">
|
||||||
<button type="button" id="hvac-load-more" class="hvac-btn-secondary">
|
<button type="button" id="hvac-load-more" class="hvac-btn-secondary">
|
||||||
|
|
@ -229,6 +225,11 @@ $api_key_configured = $find_training->is_api_key_configured();
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Reset Map View Button -->
|
||||||
|
<button type="button" id="hvac-reset-map" class="hvac-reset-map-btn" aria-label="Reset map view" title="Reset map view">
|
||||||
|
<span class="dashicons dashicons-image-rotate" aria-hidden="true"></span>
|
||||||
|
</button>
|
||||||
|
|
||||||
<!-- Map Legend Overlay -->
|
<!-- Map Legend Overlay -->
|
||||||
<div class="hvac-map-legend">
|
<div class="hvac-map-legend">
|
||||||
<div class="hvac-legend-item">
|
<div class="hvac-legend-item">
|
||||||
|
|
@ -335,6 +336,9 @@ $api_key_configured = $find_training->is_api_key_configured();
|
||||||
<label for="venue-contact-message">Message</label>
|
<label for="venue-contact-message">Message</label>
|
||||||
<textarea id="venue-contact-message" name="message" rows="4" placeholder="Tell us about your training needs..."></textarea>
|
<textarea id="venue-contact-message" name="message" rows="4" placeholder="Tell us about your training needs..."></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="hvac-form-group hvac-recaptcha-wrapper">
|
||||||
|
<div class="g-recaptcha" data-sitekey="<?php echo esc_attr(class_exists('HVAC_Recaptcha') ? HVAC_Recaptcha::SITE_KEY : ''); ?>"></div>
|
||||||
|
</div>
|
||||||
<button type="submit" class="hvac-btn-primary">Send Message</button>
|
<button type="submit" class="hvac-btn-primary">Send Message</button>
|
||||||
</form>
|
</form>
|
||||||
<div class="hvac-form-success" style="display: none;">
|
<div class="hvac-form-success" style="display: none;">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue