PageSourceSearch

https://www.tradingsmart.ai/currency-pref.js?v=20260622d

js tradingsmart.ai collected 2026-10-01 14:25:07 UTC 3,928 bytes, 111 lines download raw bytes

1// =====================================================================
2// CURRENCY PREFERENCE — INR for India, USD for everyone else
3// =====================================================================
4// Centralizes the currency-detection + override logic so the landing
5// pricing section, the checkout page, and any future Stripe-touching
6// code all read from the same source of truth.
7//
8// Detection ladder (first match wins):
9//   1. URL ?currency=inr  (one-shot override, also persists)
10//   2. localStorage 'tsai-currency-pref' (sticky user choice)
11//   3. Browser timezone === 'Asia/Kolkata' → INR
12//   4. Default → USD
13//
14// Public API:
15//   window.TSAI_CURRENCY.get()           → 'inr' | 'usd'
16//   window.TSAI_CURRENCY.set('inr')      → persists + dispatches event
17//   window.TSAI_CURRENCY.format(val)     → "₹1,499" or "$19"
18//   window.TSAI_CURRENCY.symbol()        → "₹" or "$"
19//   window.TSAI_CURRENCY.code()          → "INR" or "USD"
20//   window.TSAI_CURRENCY.detected()      → 'inr' | 'usd' (without override)
21//   addEventListener('tsai-currency-change', e => ...) on window
22// =====================================================================
23(function () {
24  const STORAGE_KEY = 'tsai-currency-pref';
25  const VALID = ['usd', 'inr'];
26
27  // INR (and the Razorpay/GST path) is India-only. Used to gate both the
28  // detected currency and whether the on-page INR toggle is shown at all.
29  function isIndia() {
30    try {
31      const tz = Intl.DateTimeFormat().resolvedOptions().timeZone || '';
32      return tz === 'Asia/Kolkata' || tz === 'Asia/Calcutta';
33    } catch (_) { return false; }
34  }
35
36  function detected() {
37    return isIndia() ? 'inr' : 'usd';
38  }
39
40  // ONE-SHOT URL override at script init: if ?currency= is present
41  // and valid, persist it to localStorage immediately. Subsequent
42  // get() calls only read localStorage / detected timezone, so the
43  // toggle's set() call wins (URL doesn't keep "voting" forever).
44  (function consumeUrlOverride() {
45    try {
46      const u = new URL(location.href);
47      const c = (u.searchParams.get('currency') || '').toLowerCase();
48      if (VALID.includes(c)) {
49        localStorage.setItem(STORAGE_KEY, c);
50      }
51    } catch (_) {}
52  })();
53
54  function get() {
55    if (!isIndia()) return 'usd';            // INR is India-only — ignore any sticky pref elsewhere
56    try {
57      const v = (localStorage.getItem(STORAGE_KEY) || '').toLowerCase();
58      if (VALID.includes(v)) return v;
59    } catch (_) {}
60    return detected();
61  }
62
63  function set(c) {
64    let next = String(c || '').toLowerCase();
65    if (!VALID.includes(next)) return;
66    if (next === 'inr' && !isIndia()) next = 'usd';  // never allow INR outside India
67
68    const prev = get();
69    try { localStorage.setItem(STORAGE_KEY, next); } catch (_) {}
70    if (prev !== next) {
71      try {
72        window.dispatchEvent(new CustomEvent('tsai-currency-change', {
73          detail: { from: prev, to: next },
74        }));
75      } catch (_) {}
76    }
77  }
78
79  function symbol(c) {
80    return (c || get()) === 'inr' ? '₹' : '$';
81  }
82  function code(c) {
83    return (c || get()) === 'inr' ? 'INR' : 'USD';
84  }
85
86  // format(amount, currency?) — returns symbol + thousands-separated value
87  // Whole-rupee/whole-dollar amounts elide ".00" (matches the fmt$ rule
88  // in app.js — keeps the headline price scannable on small screens).
89  function format(amount, c) {
90    const cur = c || get();
91    const sym = cur === 'inr' ? '₹' : '$';
92    const abs = Math.abs(+amount || 0);
93    const isWhole = abs % 1 === 0;
94    const formatted = abs.toLocaleString(cur === 'inr' ? 'en-IN' : 'en-US', {
95      minimumFractionDigits: isWhole ? 0 : 2,
96      maximumFractionDigits: 2,
97    });
98    return (amount < 0 ? '-' : '') + sym + formatted;
99  }
100
101  window.TSAI_CURRENCY = {
102    get,
103    set,
104    symbol,
105    code,
106    format,
107    detected,
108    isIndia,
109    VALID,
110  };
111})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.