/** * Listing Pages JavaScript * Handles filter sidebar interactions and view toggles * * @package Yatra */ (function() { 'use strict'; // Initialize when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } function init() { initFilterToggles(); initViewToggle(); initPriceRange(); initAdvancedSearch(); initTravelersSelect(); // Search functionality moved to shortcode-specific JS // initHorizontalSearchDropdowns(); // initDurationSlider(); } // Advanced search toggle function initAdvancedSearch() { const toggleBtn = document.getElementById('advancedToggle'); const advancedOptions = document.getElementById('advancedOptions'); if (toggleBtn && advancedOptions) { toggleBtn.addEventListener('click', function() { const isOpen = advancedOptions.style.display !== 'none'; advancedOptions.style.display = isOpen ? 'none' : 'block'; toggleBtn.classList.toggle('active'); }); } } // Travelers selector function initTravelersSelect() { const travelersSelect = document.getElementById('travelersSelect'); if (!travelersSelect) return; // Create dropdown for travelers const dropdown = document.createElement('div'); dropdown.className = 'yatra-travelers-dropdown'; dropdown.style.cssText = 'display: none; position: absolute; top: 100%; left: 0; right: 0; background: #fff; border: 1px solid #e5e7eb; border-radius: 8px; margin-top: 4px; padding: 12px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); z-index: 1000;'; dropdown.innerHTML = `
2
`; const parent = travelersSelect.parentElement; parent.style.position = 'relative'; parent.appendChild(dropdown); const input = travelersSelect.querySelector('input'); let adults = 2; travelersSelect.addEventListener('click', function(e) { e.stopPropagation(); dropdown.style.display = dropdown.style.display === 'none' ? 'block' : 'none'; }); dropdown.querySelectorAll('.yatra-quantity-btn').forEach(btn => { btn.addEventListener('click', function(e) { e.stopPropagation(); const action = this.getAttribute('data-action'); if (action === 'increase') { adults = Math.min(adults + 1, 20); } else { adults = Math.max(adults - 1, 1); } dropdown.querySelector('.yatra-quantity-value').textContent = adults; }); }); dropdown.querySelector('.yatra-apply-travelers').addEventListener('click', function(e) { e.stopPropagation(); input.value = adults + ' Adult' + (adults > 1 ? 's' : ''); dropdown.style.display = 'none'; }); document.addEventListener('click', function() { dropdown.style.display = 'none'; }); dropdown.addEventListener('click', function(e) { e.stopPropagation(); }); } // Filter section toggles function initFilterToggles() { const filterTitles = document.querySelectorAll('.yatra-filter-title'); filterTitles.forEach(title => { title.addEventListener('click', function() { const section = this.closest('.yatra-filter-section'); section.classList.toggle('open'); }); }); // Open all filter sections by default document.querySelectorAll('.yatra-filter-section').forEach(section => { section.classList.add('open'); }); } // View toggle (grid/list): one grid per page; localStorage key is per grid id (not global). function initViewToggle() { const grids = [ document.getElementById('trip-grid'), document.getElementById('category-grid'), document.getElementById('destination-grid'), document.getElementById('activity-grid') ].filter(function (el) { return el !== null; }); if (grids.length === 0) { return; } const grid = grids[0]; const storageKey = 'yatra_listing_view_' + (grid.id || 'listing'); const viewButtons = document.querySelectorAll('.yatra-view-btn[data-view]'); if (viewButtons.length === 0) { return; } const listingRoot = grid.closest('.yatra-listing-page') || document.body; function applyView(view) { if (view !== 'list') { view = 'grid'; } listingRoot.querySelectorAll('.yatra-results-controls .yatra-view-btn[data-view]').forEach(function (btn) { const btnView = btn.getAttribute('data-view'); btn.classList.toggle('active', btnView === view); }); if (view === 'list') { grid.classList.add('list-view'); grid.classList.remove('yatra-list-view'); } else { grid.classList.remove('list-view'); grid.classList.remove('yatra-list-view'); } } let initialView = 'grid'; try { const saved = window.localStorage.getItem(storageKey); if (saved === 'list' || saved === 'grid') { initialView = saved; } } catch (e) { // ignore } applyView(initialView); viewButtons.forEach(function (button) { button.addEventListener('click', function () { const view = this.getAttribute('data-view') || 'grid'; applyView(view); try { window.localStorage.setItem(storageKey, view); } catch (e) { // ignore } }); }); } // Price range slider - use specific IDs to avoid conflict with duration slider function initPriceRange() { const minRange = document.getElementById('priceRangeMin'); const maxRange = document.getElementById('priceRangeMax'); const priceDisplay = document.querySelector('.yatra-price-display'); const minInput = document.getElementById('priceMin'); const maxInput = document.getElementById('priceMax'); if (!minRange || !maxRange || !priceDisplay) return; function updatePriceDisplay() { const min = parseInt(minRange.value) || 0; const max = parseInt(maxRange.value) || 10000; // Format with commas const minFormatted = min.toLocaleString(); const maxFormatted = max.toLocaleString(); priceDisplay.textContent = `$${minFormatted} - $${maxFormatted}`; if (minInput) minInput.value = min; if (maxInput) maxInput.value = max; } minRange.addEventListener('input', function() { if (parseInt(this.value) > parseInt(maxRange.value)) { this.value = maxRange.value; } updatePriceDisplay(); }); maxRange.addEventListener('input', function() { if (parseInt(this.value) < parseInt(minRange.value)) { this.value = minRange.value; } updatePriceDisplay(); }); if (minInput) { minInput.addEventListener('input', function() { minRange.value = this.value || 0; updatePriceDisplay(); }); } if (maxInput) { maxInput.addEventListener('input', function() { maxRange.value = this.value || 10000; updatePriceDisplay(); }); } // Initial display updatePriceDisplay(); } // Clear filters functionality is handled by listing-filters.js // Removed conflicting event listener to prevent interference // Horizontal Search Dropdowns function initHorizontalSearchDropdowns() { const dropdowns = document.querySelectorAll('.yatra-search-dropdown'); if (dropdowns.length === 0) return; // Close all dropdowns when clicking outside document.addEventListener('click', function(e) { if (!e.target.closest('.yatra-search-dropdown')) { dropdowns.forEach(dropdown => { dropdown.classList.remove('open'); }); } }); dropdowns.forEach(dropdown => { const trigger = dropdown.querySelector('.yatra-dropdown-trigger'); const menu = dropdown.querySelector('.yatra-dropdown-menu'); const options = dropdown.querySelectorAll('.yatra-dropdown-option'); const valueSpan = dropdown.querySelector('.yatra-dropdown-value'); if (trigger) { trigger.addEventListener('click', function(e) { e.stopPropagation(); // Close other dropdowns dropdowns.forEach(d => { if (d !== dropdown) { d.classList.remove('open'); } }); // Toggle current dropdown dropdown.classList.toggle('open'); }); } // Handle option selection options.forEach(option => { option.addEventListener('click', function(e) { e.stopPropagation(); // Remove selected from siblings options.forEach(opt => opt.classList.remove('selected')); // Add selected to clicked option this.classList.add('selected'); // Update the display value if (valueSpan) { valueSpan.textContent = this.textContent; valueSpan.classList.add('selected'); } // Close dropdown dropdown.classList.remove('open'); }); }); // Keep dropdown open when clicking inside (for duration slider) if (menu) { menu.addEventListener('click', function(e) { e.stopPropagation(); }); } }); } // Duration Slider function initDurationSlider() { const durationDropdown = document.querySelector('[data-dropdown="duration"]'); if (!durationDropdown) return; const minSlider = durationDropdown.querySelector('#durationMin'); const maxSlider = durationDropdown.querySelector('#durationMax'); const minBadge = durationDropdown.querySelector('.yatra-duration-min-badge'); const maxBadge = durationDropdown.querySelector('.yatra-duration-max-badge'); const sliderRange = durationDropdown.querySelector('.yatra-slider-range'); const valueSpan = durationDropdown.querySelector('.yatra-dropdown-value'); if (!minSlider || !maxSlider) return; function durationBounds() { const lo = parseInt(durationDropdown.getAttribute('data-duration-min') || minSlider.min, 10); const hi = parseInt(durationDropdown.getAttribute('data-duration-max') || maxSlider.max, 10); const safeLo = isNaN(lo) ? 1 : lo; const safeHi = isNaN(hi) || hi < safeLo ? safeLo : hi; return { lo: safeLo, hi: safeHi, span: Math.max(1, safeHi - safeLo) }; } function updateDurationDisplay() { let min = parseInt(minSlider.value, 10); let max = parseInt(maxSlider.value, 10); // Ensure min doesn't exceed max if (min > max) { [min, max] = [max, min]; minSlider.value = min; maxSlider.value = max; } // Update badges if (minBadge) minBadge.textContent = min + ' Days'; if (maxBadge) maxBadge.textContent = max + ' Days'; // Update the dropdown value display if (valueSpan) { valueSpan.textContent = min + ' - ' + max + ' Days'; valueSpan.classList.add('selected'); } // Update the slider range track if (sliderRange) { const b = durationBounds(); const minPercent = ((min - b.lo) / b.span) * 100; const maxPercent = ((max - b.lo) / b.span) * 100; sliderRange.style.left = minPercent + '%'; sliderRange.style.width = Math.max(0, maxPercent - minPercent) + '%'; } } minSlider.addEventListener('input', updateDurationDisplay); maxSlider.addEventListener('input', updateDurationDisplay); // Initial display updateDurationDisplay(); } })();