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
← All changes | assets/js/single-trip.js +48 -19 3.0.8 → 3.0.16 View file →
@@ -12,20 +12,43 @@
12 12
13 13 // Translation helpers — idempotent shim matching booking.js / trip.js so
14 14 // `__()` resolves through wp.i18n when wp-i18n is enqueued, otherwise it
15 15 // falls back to the source string.
16 +// Parse a numeric min/max attribute while preserving a legitimate 0.
17 +// `parseInt(el.getAttribute('max')) || 99` treated max="0" — what a sold-out
18 +// departure renders — as "unset" and fell back to the placeholder ceiling, so
19 +// the guest selector stayed usable and ignored the departure's real capacity.
20 +// Only an absent or non-numeric value may fall back. Installed once and shared
21 +// by every frontend script, so load order does not matter.
22 +if (typeof window.yatraNumOr !== 'function') {
23 + window.yatraNumOr = function (raw, fallback) {
24 + var parsed = parseInt(raw, 10);
25 + return isNaN(parsed) ? fallback : parsed;
26 + };
27 +}
28 +
16 29 (function () {
17 - if (typeof window.__ === 'function') return;
18 - if (window.wp && window.wp.i18n && typeof window.wp.i18n.__ === 'function') {
19 - window.__ = function (text, domain) { return window.wp.i18n.__(text, domain || 'yatra'); };
20 - window._n = function (s, p, n, domain) { return window.wp.i18n._n(s, p, n, domain || 'yatra'); };
21 - window._x = function (text, ctx, domain) { return window.wp.i18n._x(text, ctx, domain || 'yatra'); };
22 - window.sprintf = window.sprintf || (window.wp.i18n.sprintf || function (fmt) { return fmt; });
30 + var i18n = (window.wp && window.wp.i18n) ? window.wp.i18n : null;
31 + if (i18n && typeof i18n.__ === 'function') {
32 + window.__ = function (text, domain) { return i18n.__(text, domain || 'yatra'); };
33 + window._n = function (s, p, n, domain) { return i18n._n(s, p, n, domain || 'yatra'); };
34 + window._x = function (text, ctx, domain) { return i18n._x(text, ctx, domain || 'yatra'); };
35 + // Always bind WordPress's own sprintf (it substitutes %d/%s/%1$s).
36 + // Do NOT defer to a pre-existing window.sprintf: a theme or other
37 + // plugin can define an incompatible global that leaves placeholders
38 + // unsubstituted (the cause of literal "%d"/"%s" in the UI).
39 + if (typeof i18n.sprintf === 'function') {
40 + window.sprintf = function () { return i18n.sprintf.apply(i18n, arguments); };
41 + } else if (typeof window.sprintf !== 'function') {
42 + window.sprintf = function (fmt) { return fmt; };
43 + }
23 44 } else {
24 - window.__ = function (text) { return text; };
25 - window._n = function (s, p, n) { return n === 1 ? s : p; };
26 - window._x = function (text) { return text; };
27 - window.sprintf = window.sprintf || function (fmt) { return fmt; };
45 + // wp.i18n not present — install passthroughs only if nothing usable
46 + // exists yet (don't clobber a real binding installed earlier).
47 + if (typeof window.__ !== 'function') window.__ = function (text) { return text; };
48 + if (typeof window._n !== 'function') window._n = function (s, p, n) { return n === 1 ? s : p; };
49 + if (typeof window._x !== 'function') window._x = function (text) { return text; };
50 + if (typeof window.sprintf !== 'function') window.sprintf = function (fmt) { return fmt; };
28 51 }
29 52 })();
30 53
31 54 document.addEventListener('DOMContentLoaded', function() {
@@ -351,10 +374,16 @@
351 374
352 375 updatePricing();
353 376 });
354 377
355 - // Set today's date by default if available, otherwise use trip fallback pricing
356 - const today = new Date().toISOString().split('T')[0];
378 + // Set today's date by default if available, otherwise use trip fallback pricing.
379 + // Build LOCAL YYYY-MM-DD, not toISOString() (which is UTC and can land on
380 + // the wrong calendar day — mis-matching the availability's departure_date
381 + // and pre-selecting the wrong date near midnight).
382 + const _now = new Date();
383 + const today = _now.getFullYear() + '-'
384 + + String(_now.getMonth() + 1).padStart(2, '0') + '-'
385 + + String(_now.getDate()).padStart(2, '0');
357 386 if (!dateInput.value) {
358 387 const availabilities = getSidebarAvailabilities();
359 388 if (availabilities.length > 0) {
360 389 const todayAvailability = availabilities.find(a => a.departure_date === today);
@@ -441,9 +470,9 @@
441 470 <div class="yatra-group-discount-badge">
442 471 <svg width="14" height="14" fill="currentColor" viewBox="0 0 20 20">
443 472 <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
444 473 </svg>
445 - Group discount applied: -${window.yatraTripData?.currencySymbol || '$'}${discountAmount.toFixed(2)}
474 + Group discount applied: -${typeof window.yatra_format_price_js === 'function' ? window.yatra_format_price_js(discountAmount) : (window.yatraTripData?.currencySymbol || '$') + discountAmount.toFixed(2)}
446 475 </div>
447 476 `;
448 477 } else if (indicator) {
449 478 indicator.remove();
@@ -543,10 +572,10 @@
543 572 }
544 573
545 574 if (!input) return;
546 575
547 - const min = parseInt(input.getAttribute('min')) || 0;
548 - const max = parseInt(input.getAttribute('max')) || 99;
576 + const min = window.yatraNumOr(input.getAttribute('min'), 0);
577 + const max = window.yatraNumOr(input.getAttribute('max'), 99);
549 578 let value = parseInt(input.value) || 0;
550 579
551 580 // Update value based on button type
552 581 if (btn.classList.contains('yatra-quantity-plus')) {
@@ -602,9 +631,9 @@
602 631 // Regular pricing - sync all num_travelers and enquiry_adults inputs
603 632 const regularInputs = document.querySelectorAll('#num_travelers, #enquiry_adults');
604 633 regularInputs.forEach(input => {
605 634 if (input !== sourceInput) {
606 - const max = parseInt(input.getAttribute('max')) || 99;
635 + const max = window.yatraNumOr(input.getAttribute('max'), 99);
607 636 input.value = Math.min(sourceValue, max);
608 637 }
609 638 });
610 639
@@ -611,9 +640,9 @@
611 640 // Also sync to availability section inputs
612 641 const availabilityInputs = document.querySelectorAll('input[id^="num-travelers-"]');
613 642 availabilityInputs.forEach(input => {
614 643 if (input !== sourceInput) {
615 - const max = parseInt(input.getAttribute('max')) || 99;
644 + const max = window.yatraNumOr(input.getAttribute('max'), 99);
616 645 input.value = Math.min(sourceValue, max);
617 646 }
618 647 });
619 648
@@ -638,15 +667,15 @@
638 667 );
639 668
640 669 categoryInputs.forEach(input => {
641 670 if (input !== sourceInput) {
642 - const max = parseInt(input.getAttribute('max')) || 99;
671 + const max = window.yatraNumOr(input.getAttribute('max'), 99);
643 672 input.value = Math.min(sourceValue, max);
644 673
645 674 // Update button states for this input
646 675 const row = input.closest('.yatra-quantity-row');
647 676 if (row) {
648 - const min = parseInt(input.getAttribute('min')) || 0;
677 + const min = window.yatraNumOr(input.getAttribute('min'), 0);
649 678 const minusBtn = row.querySelector('.yatra-quantity-minus');
650 679 const plusBtn = row.querySelector('.yatra-quantity-plus');
651 680 if (minusBtn) minusBtn.disabled = input.value <= min;
652 681 if (plusBtn) plusBtn.disabled = input.value >= max;