/** * Find Training Filters * * Handles filtering, searching, and geolocation functionality * for the Find Training page. * * @package HVAC_Community_Events * @since 2.2.0 */ (function($) { 'use strict'; // Namespace for filters module window.HVACTrainingFilters = { // Debounce timer for search searchTimer: null, // Current AJAX request (for aborting) currentRequest: null, // Active filters activeFilters: { state: '', certification: '', training_format: '', search: '' }, // User location (if obtained) userLocation: null, /** * Initialize filters */ init: function() { this.bindEvents(); this.initMobileFilterToggle(); }, /** * Bind event handlers */ bindEvents: function() { const self = this; // Search input with debounce $('#hvac-training-search').on('input', function() { clearTimeout(self.searchTimer); const value = $(this).val(); self.searchTimer = setTimeout(function() { self.activeFilters.search = value; self.applyFilters(); }, 300); }); // State filter $('#hvac-filter-state').on('change', function() { self.activeFilters.state = $(this).val(); self.applyFilters(); self.updateActiveFiltersDisplay(); }); // Certification filter $('#hvac-filter-certification').on('change', function() { self.activeFilters.certification = $(this).val(); self.applyFilters(); self.updateActiveFiltersDisplay(); }); // Training format filter $('#hvac-filter-format').on('change', function() { self.activeFilters.training_format = $(this).val(); self.applyFilters(); self.updateActiveFiltersDisplay(); }); // Near Me button $('#hvac-near-me-btn').on('click', function() { self.handleNearMeClick($(this)); }); // Clear all filters $('.hvac-clear-filters').on('click', function() { self.clearAllFilters(); }); // Remove individual filter $(document).on('click', '.hvac-active-filter button', function() { const filterType = $(this).parent().data('filter'); self.removeFilter(filterType); }); }, /** * Apply current filters */ applyFilters: function() { const self = this; // Abort any pending request to prevent race conditions if (this.currentRequest && this.currentRequest.readyState !== 4) { this.currentRequest.abort(); } // Build filter data const filterData = { action: 'hvac_filter_training_map', nonce: hvacFindTraining.nonce, state: this.activeFilters.state, certification: this.activeFilters.certification, training_format: this.activeFilters.training_format, search: this.activeFilters.search, show_trainers: $('#hvac-show-trainers').is(':checked'), show_venues: $('#hvac-show-venues').is(':checked') }; // Add user location if available if (this.userLocation) { filterData.lat = this.userLocation.lat; filterData.lng = this.userLocation.lng; filterData.radius = 100; // km } // Send filter request and store reference this.currentRequest = $.ajax({ url: hvacFindTraining.ajax_url, type: 'POST', data: filterData, success: function(response) { if (response.success) { // Update map data HVACTrainingMap.trainers = response.data.trainers || []; HVACTrainingMap.venues = response.data.venues || []; HVACTrainingMap.visibleTrainers = HVACTrainingMap.trainers.slice(); // Reset to all HVACTrainingMap.updateMarkers(); HVACTrainingMap.updateCounts(HVACTrainingMap.trainers.length); HVACTrainingMap.updateTrainerGrid(); // Note: syncSidebarWithViewport will be called by map 'idle' event } }, complete: function() { self.currentRequest = null; } }); // Show/hide clear button this.updateClearButtonVisibility(); }, /** * Handle Near Me button click */ handleNearMeClick: function($button) { const self = this; // Show loading state $button.prop('disabled', true); $button.html(' Locating...'); // Clear any previous error message this.clearLocationError(); // Get user location HVACTrainingMap.getUserLocation(function(location, error) { if (location) { self.userLocation = location; // Center map on user location HVACTrainingMap.centerOnLocation(location.lat, location.lng, 9); // Apply filters with location self.applyFilters(); // Update button state $button.html(' Near Me'); $button.addClass('active'); // Add to active filters display self.addActiveFilter('location', 'Near Me'); } else { // Show inline error instead of alert self.showLocationError(error || 'Unable to get your location. Please check browser permissions.'); // Reset button $button.html(' Near Me'); $button.prop('disabled', false); } }); }, /** * Show location error message inline */ showLocationError: function(message) { // Remove any existing error this.clearLocationError(); // Create error element const $error = $('
' + ' ' + this.escapeHtml(message) + '' + '
'); // Insert after Near Me button $('#hvac-near-me-btn').after($error); // Auto-dismiss after 5 seconds setTimeout(function() { $error.fadeOut(300, function() { $(this).remove(); }); }, 5000); // Click to dismiss $error.find('.hvac-dismiss-error').on('click', function() { $error.remove(); }); }, /** * Clear location error message */ clearLocationError: function() { $('.hvac-location-error').remove(); }, /** * Clear all filters */ clearAllFilters: function() { // Reset filter values this.activeFilters = { state: '', certification: '', training_format: '', search: '' }; // Reset user location this.userLocation = null; // Reset form elements $('#hvac-filter-state').val(''); $('#hvac-filter-certification').val(''); $('#hvac-filter-format').val(''); $('#hvac-training-search').val(''); // Reset Near Me button $('#hvac-near-me-btn') .removeClass('active') .html(' Near Me') .prop('disabled', false); // Clear active filters display $('.hvac-active-filters').empty(); // Hide clear button $('.hvac-clear-filters').hide(); // Reset map to default view HVACTrainingMap.map.setCenter(HVACTrainingMap.config.defaultCenter); HVACTrainingMap.map.setZoom(HVACTrainingMap.config.defaultZoom); // Reload data without filters HVACTrainingMap.loadMapData(); }, /** * Remove a specific filter */ removeFilter: function(filterType) { switch (filterType) { case 'state': this.activeFilters.state = ''; $('#hvac-filter-state').val(''); break; case 'certification': this.activeFilters.certification = ''; $('#hvac-filter-certification').val(''); break; case 'training_format': this.activeFilters.training_format = ''; $('#hvac-filter-format').val(''); break; case 'search': this.activeFilters.search = ''; $('#hvac-training-search').val(''); break; case 'location': this.userLocation = null; $('#hvac-near-me-btn') .removeClass('active') .html(' Near Me') .prop('disabled', false); break; } this.applyFilters(); this.updateActiveFiltersDisplay(); }, /** * Update active filters display */ updateActiveFiltersDisplay: function() { const $container = $('.hvac-active-filters'); $container.empty(); // State filter if (this.activeFilters.state) { this.addActiveFilter('state', `State: ${this.activeFilters.state}`); } // Certification filter if (this.activeFilters.certification) { this.addActiveFilter('certification', this.activeFilters.certification); } // Training format filter if (this.activeFilters.training_format) { this.addActiveFilter('training_format', this.activeFilters.training_format); } // Search filter if (this.activeFilters.search) { this.addActiveFilter('search', `"${this.activeFilters.search}"`); } // Location filter if (this.userLocation) { this.addActiveFilter('location', 'Near Me'); } this.updateClearButtonVisibility(); }, /** * Add an active filter chip */ addActiveFilter: function(type, label) { const $container = $('.hvac-active-filters'); const $chip = $(` ${this.escapeHtml(label)} `); $container.append($chip); }, /** * Update clear button visibility */ updateClearButtonVisibility: function() { const hasFilters = this.activeFilters.state || this.activeFilters.certification || this.activeFilters.training_format || this.activeFilters.search || this.userLocation; if (hasFilters) { $('.hvac-clear-filters').show(); } else { $('.hvac-clear-filters').hide(); } }, /** * Escape HTML for safe output */ escapeHtml: function(text) { if (!text) return ''; const div = document.createElement('div'); div.textContent = text; return div.innerHTML; }, /** * Initialize mobile filter toggle */ initMobileFilterToggle: function() { const self = this; // Mobile filter panel toggle $(document).on('click', '.hvac-mobile-filter-toggle', function() { const $toggle = $(this); const $panel = $('#hvac-mobile-filter-panel'); const isExpanded = $toggle.attr('aria-expanded') === 'true'; if (isExpanded) { $panel.attr('hidden', ''); $toggle.attr('aria-expanded', 'false'); } else { $panel.removeAttr('hidden'); $toggle.attr('aria-expanded', 'true'); } }); // Sync mobile filter selects with desktop selects $('#hvac-filter-state-mobile').on('change', function() { const value = $(this).val(); $('#hvac-filter-state').val(value); self.activeFilters.state = value; self.applyFilters(); self.updateActiveFiltersDisplay(); }); $('#hvac-filter-certification-mobile').on('change', function() { const value = $(this).val(); $('#hvac-filter-certification').val(value); self.activeFilters.certification = value; self.applyFilters(); self.updateActiveFiltersDisplay(); }); $('#hvac-filter-format-mobile').on('change', function() { const value = $(this).val(); $('#hvac-filter-format').val(value); self.activeFilters.training_format = value; self.applyFilters(); self.updateActiveFiltersDisplay(); }); // Also sync desktop to mobile when desktop changes $('#hvac-filter-state').on('change', function() { $('#hvac-filter-state-mobile').val($(this).val()); }); $('#hvac-filter-certification').on('change', function() { $('#hvac-filter-certification-mobile').val($(this).val()); }); $('#hvac-filter-format').on('change', function() { $('#hvac-filter-format-mobile').val($(this).val()); }); } }; // Initialize when document is ready $(document).ready(function() { if ($('#hvac-training-map').length) { HVACTrainingFilters.init(); } }); })(jQuery);