| @@ -15,18 +15,75 @@ | ||
| 15 | 15 | init(); |
| 16 | 16 | } |
| 17 | 17 | |
| 18 | 18 | function init() { |
| 19 | - initFilterToggles(); | |
| 19 | + // Filter sidebar toggles (.yatra-filter-title click → toggle .open | |
| 20 | + // on the section) live in listing-filters.js. Keeping a second | |
| 21 | + // copy here meant TWO toggles fired per click, leaving the | |
| 22 | + // section in its original state — i.e. the arrow appeared dead. | |
| 20 | 23 | initViewToggle(); |
| 21 | 24 | initPriceRange(); |
| 22 | 25 | initAdvancedSearch(); |
| 23 | 26 | initTravelersSelect(); |
| 27 | + initStretchedCardClicks(); | |
| 24 | 28 | // Search functionality moved to shortcode-specific JS |
| 25 | 29 | // initHorizontalSearchDropdowns(); |
| 26 | 30 | // initDurationSlider(); |
| 27 | 31 | } |
| 28 | 32 | |
| 33 | + // Whole-card click target for the destination / activity / trip-category | |
| 34 | + // shortcode-as-block "category" cards. Trip listing cards intentionally | |
| 35 | + // opt out — those have multiple visible CTAs (View Details button, image | |
| 36 | + // link, title link, favorite, category/activity chips) and shouldn't | |
| 37 | + // hijack ambient clicks; the user navigates via the explicit controls. | |
| 38 | + // | |
| 39 | + // CSS-only "stretched link" (title link ::after with inset:0) is the | |
| 40 | + // canonical implementation and remains in place for screen-reader and | |
| 41 | + // crawler semantics — but in some layouts an intermediate ancestor with | |
| 42 | + // `position: relative` traps the absolute overlay, leaving the upper | |
| 43 | + // portion of the card non-clickable. This delegated click handler is the | |
| 44 | + // belt-and-braces fallback: it catches any click that didn't already land | |
| 45 | + // on a real interactive element and forwards it to the card's primary | |
| 46 | + // link. Modifier keys (ctrl/cmd/middle-click) open in a new tab to match | |
| 47 | + // the browser's normal `<a>` behavior. | |
| 48 | + function initStretchedCardClicks() { | |
| 49 | + const cardSelector = '.yatra-category-card'; | |
| 50 | + const linkSelector = 'a.yatra-category-card-title-link'; | |
| 51 | + // Click targets that should be allowed to handle their own event. | |
| 52 | + const interactive = 'a, button, input, select, textarea, label, [role="button"], [data-no-card-click]'; | |
| 53 | + | |
| 54 | + document.addEventListener('click', function (event) { | |
| 55 | + // Allow native links/buttons to do their thing. | |
| 56 | + if (event.target.closest(interactive)) { | |
| 57 | + return; | |
| 58 | + } | |
| 59 | + const card = event.target.closest(cardSelector); | |
| 60 | + if (!card) return; | |
| 61 | + | |
| 62 | + const link = card.querySelector(linkSelector); | |
| 63 | + if (!link || !link.href) return; | |
| 64 | + | |
| 65 | + // Cmd/Ctrl/middle-click → new tab. Plain click → same tab. | |
| 66 | + if (event.metaKey || event.ctrlKey || event.shiftKey || event.button === 1) { | |
| 67 | + window.open(link.href, '_blank', 'noopener'); | |
| 68 | + } else { | |
| 69 | + window.location.href = link.href; | |
| 70 | + } | |
| 71 | + }); | |
| 72 | + | |
| 73 | + // Keyboard parity: Enter on a focused card root navigates to the link. | |
| 74 | + document.addEventListener('keydown', function (event) { | |
| 75 | + if (event.key !== 'Enter') return; | |
| 76 | + if (event.target.closest(interactive)) return; | |
| 77 | + const card = event.target.closest(cardSelector); | |
| 78 | + if (!card) return; | |
| 79 | + const link = card.querySelector(linkSelector); | |
| 80 | + if (link && link.href) { | |
| 81 | + window.location.href = link.href; | |
| 82 | + } | |
| 83 | + }); | |
| 84 | + } | |
| 85 | + | |
| 29 | 86 | // Advanced search toggle |
| 30 | 87 | function initAdvancedSearch() { |
| 31 | 88 | const toggleBtn = document.getElementById('advancedToggle'); |
| 32 | 89 | const advancedOptions = document.getElementById('advancedOptions'); |
| @@ -98,25 +155,8 @@ | ||
| 98 | 155 | }); |
| 99 | 156 | |
| 100 | 157 | dropdown.addEventListener('click', function(e) { |
| 101 | 158 | e.stopPropagation(); |
| 102 | - }); | |
| 103 | - } | |
| 104 | - | |
| 105 | - // Filter section toggles | |
| 106 | - function initFilterToggles() { | |
| 107 | - const filterTitles = document.querySelectorAll('.yatra-filter-title'); | |
| 108 | - | |
| 109 | - filterTitles.forEach(title => { | |
| 110 | - title.addEventListener('click', function() { | |
| 111 | - const section = this.closest('.yatra-filter-section'); | |
| 112 | - section.classList.toggle('open'); | |
| 113 | - }); | |
| 114 | - }); | |
| 115 | - | |
| 116 | - // Open all filter sections by default | |
| 117 | - document.querySelectorAll('.yatra-filter-section').forEach(section => { | |
| 118 | - section.classList.add('open'); | |
| 119 | 159 | }); |
| 120 | 160 | } |
| 121 | 161 | |
| 122 | 162 | // View toggle (grid/list): one grid per page; localStorage key is per grid id (not global). |