/**
* 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 = `
`;
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();
}
})();