PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.16
Yatra – Travel Booking & Tour Operator Software v3.0.16
3.0.16 3.0.15 3.0.14 3.0.14.1 3.0.14.2 3.0.12 3.0.13 3.0.11 3.0.10 3.0.9 3.0.8 3.0.7 3.0.6 3.0.5 3.0.5.1 3.0.4 3.0.3 3.0.2.9 3.0.2.7 3.0.2.8 3.0.2.6 trunk 1.0.0 2.0.0 2.0.1 All 84 releases
yatra / assets / js / trip-search-shortcode.js

trip-search-shortcode.js in Yatra – Travel Booking & Tour Operator Software 3.0.16, at assets/js/trip-search-shortcode.js

344 lines 13.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 jQuery(document).ready(function() {
2 'use strict';
3
4 function getListingUrl() {
5 var root = document.querySelector('.yatra-trip-search-shortcode');
6 var configured = root && root.getAttribute('data-listing-url');
7 if (!configured && window.yatraTripSearchConfig && window.yatraTripSearchConfig.listingUrl) {
8 configured = window.yatraTripSearchConfig.listingUrl;
9 }
10 if (!configured && window.yatraListing && window.yatraListing.tripListingUrl) {
11 configured = window.yatraListing.tripListingUrl;
12 }
13 if (configured) {
14 try {
15 var cur = new URL(window.location.href);
16 var cfg = new URL(configured, window.location.href);
17 var cpath = cur.pathname.replace(/\/$/, '') || '/';
18 var bpath = cfg.pathname.replace(/\/$/, '') || '/';
19 var escaped = bpath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
20 if (cpath === bpath || new RegExp('^' + escaped + '/page/\\d+$').test(cpath)) {
21 return cfg.origin + bpath + '/';
22 }
23 } catch (e) {}
24 return configured;
25 }
26 return window.location.href.split('?')[0].replace(/\/page\/\d+\/?$/, '').replace(/\/$/, '') + '/';
27 }
28
29 function closeDropdownMenu(dropdown) {
30 if (!dropdown) {
31 return;
32 }
33 dropdown.classList.remove('open');
34 var m = dropdown.querySelector('.yatra-dropdown-menu');
35 if (m) {
36 m.classList.remove('show');
37 }
38 }
39
40 function initHorizontalSearchDropdowns() {
41 var dropdowns = document.querySelectorAll('.yatra-search-dropdown');
42
43 if (dropdowns.length === 0) {
44 return;
45 }
46
47 document.addEventListener('click', function(e) {
48 if (!e.target.closest('.yatra-search-dropdown')) {
49 dropdowns.forEach(function(dropdown) {
50 closeDropdownMenu(dropdown);
51 });
52 }
53 });
54
55 dropdowns.forEach(function(dropdown) {
56 dropdown.classList.remove('open');
57
58 var trigger = dropdown.querySelector('.yatra-dropdown-trigger');
59 var menu = dropdown.querySelector('.yatra-dropdown-menu');
60 var valueSpan = dropdown.querySelector('.yatra-dropdown-value');
61 var options = dropdown.querySelectorAll('.yatra-dropdown-option');
62
63 var filterableMenu = dropdown.querySelector('.yatra-dropdown-menu--filterable');
64 var filterInput = filterableMenu ? filterableMenu.querySelector('.yatra-dropdown-filter-input') : null;
65 var optionsContainer = filterableMenu ? filterableMenu.querySelector('.yatra-dropdown-options') : null;
66
67 if (filterInput && optionsContainer) {
68 filterInput.addEventListener('click', function(e) {
69 e.stopPropagation();
70 });
71 filterInput.addEventListener('keydown', function(e) {
72 e.stopPropagation();
73 });
74 filterInput.addEventListener('input', function() {
75 var q = (filterInput.value || '').trim().toLowerCase();
76 optionsContainer.querySelectorAll('.yatra-dropdown-option').forEach(function(opt) {
77 var hay = (opt.getAttribute('data-search-text') || opt.textContent || '').trim().toLowerCase();
78 var hide = q !== '' && hay.indexOf(q) === -1;
79 opt.classList.toggle('yatra-dropdown-option--hidden', hide);
80 });
81 });
82 }
83
84 if (trigger) {
85 trigger.addEventListener('click', function(e) {
86 e.preventDefault();
87 e.stopPropagation();
88 e.stopImmediatePropagation();
89
90 dropdowns.forEach(function(d) {
91 if (d !== dropdown) {
92 closeDropdownMenu(d);
93 }
94 });
95
96 if (dropdown.classList.contains('open')) {
97 closeDropdownMenu(dropdown);
98 } else {
99 dropdown.classList.add('open');
100 var m = dropdown.querySelector('.yatra-dropdown-menu');
101 if (m) {
102 m.removeAttribute('style');
103 m.classList.add('show');
104 }
105 if (filterInput && optionsContainer) {
106 filterInput.value = '';
107 optionsContainer.querySelectorAll('.yatra-dropdown-option').forEach(function(opt) {
108 opt.classList.remove('yatra-dropdown-option--hidden');
109 });
110 window.requestAnimationFrame(function() {
111 filterInput.focus();
112 });
113 }
114 }
115 }, true);
116 }
117
118 options.forEach(function(option) {
119 option.addEventListener('click', function(e) {
120 e.stopPropagation();
121
122 var scope = optionsContainer || dropdown;
123 var siblings = scope.querySelectorAll('.yatra-dropdown-option');
124 siblings.forEach(function(opt) {
125 opt.classList.remove('selected');
126 });
127
128 this.classList.add('selected');
129
130 if (valueSpan) {
131 valueSpan.textContent = (this.textContent || '').trim();
132 valueSpan.classList.add('selected');
133 }
134
135 closeDropdownMenu(dropdown);
136 });
137 });
138
139 if (menu) {
140 menu.addEventListener('click', function(e) {
141 e.stopPropagation();
142 });
143 }
144 });
145 }
146
147 function initDurationSlider() {
148 var durationDropdown = document.querySelector('[data-dropdown="duration"]');
149 if (!durationDropdown) {
150 return;
151 }
152
153 var minSlider = durationDropdown.querySelector('#durationMin');
154 var maxSlider = durationDropdown.querySelector('#durationMax');
155 var minBadge = durationDropdown.querySelector('.yatra-duration-min-badge');
156 var maxBadge = durationDropdown.querySelector('.yatra-duration-max-badge');
157 var sliderRange = durationDropdown.querySelector('.yatra-slider-range');
158 var valueSpan = durationDropdown.querySelector('.yatra-dropdown-value');
159
160 if (!minSlider || !maxSlider) {
161 return;
162 }
163
164 function bounds() {
165 var lo = parseInt(durationDropdown.getAttribute('data-duration-min') || minSlider.min, 10);
166 var hi = parseInt(durationDropdown.getAttribute('data-duration-max') || maxSlider.max, 10);
167 if (isNaN(lo)) {
168 lo = 1;
169 }
170 if (isNaN(hi) || hi < lo) {
171 hi = lo;
172 }
173 return { lo: lo, hi: hi, span: Math.max(1, hi - lo) };
174 }
175
176 function updateDurationDisplay() {
177 var b = bounds();
178 var min = parseInt(minSlider.value, 10);
179 var max = parseInt(maxSlider.value, 10);
180
181 if (min > max) {
182 var t = min;
183 min = max;
184 max = t;
185 minSlider.value = min;
186 maxSlider.value = max;
187 }
188
189 if (minBadge) {
190 minBadge.textContent = min + ' Days';
191 }
192 if (maxBadge) {
193 maxBadge.textContent = max + ' Days';
194 }
195
196 if (valueSpan) {
197 valueSpan.textContent = min + ' - ' + max + ' Days';
198 valueSpan.classList.add('selected');
199 }
200
201 if (sliderRange) {
202 var minPercent = ((min - b.lo) / b.span) * 100;
203 var maxPercent = ((max - b.lo) / b.span) * 100;
204 sliderRange.style.left = minPercent + '%';
205 sliderRange.style.width = Math.max(0, maxPercent - minPercent) + '%';
206 }
207 }
208
209 minSlider.addEventListener('input', updateDurationDisplay);
210 maxSlider.addEventListener('input', updateDurationDisplay);
211
212 updateDurationDisplay();
213 }
214
215 function runTripSearch() {
216 var filters = {};
217
218 var kw = document.querySelector('.yatra-search-keyword-input');
219 if (kw && kw.value.trim()) {
220 filters.s = kw.value.trim();
221 }
222
223 var destDropdown = document.querySelector('[data-dropdown="destination"]');
224 if (destDropdown) {
225 var selectedDest = destDropdown.querySelector('.yatra-dropdown-option.selected');
226 if (selectedDest) {
227 var dv = selectedDest.getAttribute('data-value');
228 if (dv) {
229 filters.destination = dv;
230 }
231 }
232 }
233
234 var actDropdown = document.querySelector('[data-dropdown="activities"]');
235 if (actDropdown) {
236 var selectedAct = actDropdown.querySelector('.yatra-dropdown-option.selected');
237 if (selectedAct) {
238 var av = selectedAct.getAttribute('data-value');
239 if (av) {
240 filters.activity = av;
241 }
242 }
243 }
244
245 var durationDropdown = document.querySelector('[data-dropdown="duration"]');
246 if (durationDropdown) {
247 var minInput = durationDropdown.querySelector('#durationMin');
248 var maxInput = durationDropdown.querySelector('#durationMax');
249 if (minInput && maxInput) {
250 var min = parseInt(minInput.value, 10);
251 var max = parseInt(maxInput.value, 10);
252 var lo = parseInt(durationDropdown.getAttribute('data-duration-min') || minInput.min, 10);
253 var hi = parseInt(durationDropdown.getAttribute('data-duration-max') || maxInput.max, 10);
254 if (!isNaN(min) && !isNaN(max) && (min !== lo || max !== hi)) {
255 filters.duration = min + '-' + max;
256 }
257 }
258 }
259
260 var budgetDropdown = document.querySelector('[data-dropdown="budget"]');
261 if (budgetDropdown) {
262 var selectedBudget = budgetDropdown.querySelector('.yatra-dropdown-option.selected');
263 if (selectedBudget) {
264 var bv = selectedBudget.getAttribute('data-value');
265 if (bv) {
266 filters.budget = bv;
267 }
268 }
269 }
270
271 var dateInput = document.querySelector('.yatra-search-date-input');
272 if (dateInput && dateInput.value && /^\d{4}-\d{2}-\d{2}$/.test(dateInput.value)) {
273 filters.available_date = dateInput.value;
274 }
275
276 var listing = getListingUrl();
277 var url;
278 try {
279 url = new URL(listing);
280 } catch (e) {
281 url = new URL(listing, window.location.href);
282 }
283
284 Object.keys(filters).forEach(function(key) {
285 if (filters[key]) {
286 url.searchParams.set(key, filters[key]);
287 }
288 });
289
290 window.location.href = url.toString();
291 }
292
293 function initSearchFunctionality() {
294 var searchBtn = document.querySelector('.yatra-search-main-btn');
295 var kwInput = document.querySelector('.yatra-search-keyword-input');
296
297 if (searchBtn) {
298 searchBtn.addEventListener('click', function(e) {
299 e.preventDefault();
300 runTripSearch();
301 });
302 }
303
304 if (kwInput) {
305 kwInput.addEventListener('keydown', function(e) {
306 if (e.key === 'Enter') {
307 e.preventDefault();
308 runTripSearch();
309 }
310 });
311 }
312 }
313
314 // Upgrade the native date field to the same flatpickr picker used on the
315 // checkout/booking page, for a consistent, styled calendar. Fully guarded:
316 // with no flatpickr (or on mobile, where the native picker is already good)
317 // the native <input type="date"> is left working untouched. The submitted
318 // value stays ISO (Y-m-d) so the search URL and back-end are unchanged.
319 function initTripSearchDatePicker() {
320 var input = document.querySelector('.yatra-search-date-input');
321 if (!input || input.dataset.yatraFp === '1') return;
322 if (typeof window.flatpickr === 'undefined') return;
323 var isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent || '');
324 if (isMobile) return; // native mobile date UI is already good; leave it
325 input.dataset.yatraFp = '1';
326 // Switch off the native date UI so flatpickr is the only picker; the
327 // value stays ISO (Y-m-d) via dateFormat, so runTripSearch() and the
328 // back-end see the same format as before.
329 try { input.type = 'text'; } catch (e) {}
330 window.flatpickr(input, {
331 dateFormat: 'Y-m-d',
332 minDate: input.getAttribute('min') || 'today',
333 defaultDate: input.value || null,
334 allowInput: false,
335 disableMobile: true
336 });
337 }
338
339 initHorizontalSearchDropdowns();
340 initDurationSlider();
341 initSearchFunctionality();
342 initTripSearchDatePicker();
343 });
344