PageSourceSearch

https://www.33bd33.com/mc/v.1.0.1/manifest/numberSeparator.6a0b613a.js

js 33bd33.com collected 2026-09-26 01:23:13 UTC 9,180 bytes, 252 lines download raw bytes

1(function (window, document, $, tcg) {
2  function resolveAllowDecimal(cfg) {
3    if (cfg.allowDecimal === undefined || cfg.allowDecimal === null) {
4      return cfg.decimal !== false;
5    }
6    return cfg.allowDecimal === "Y";
7  }
8
9  tcg.mc.easyNumberSeparator = (config) => {
10    // Currency Separator
11    const allowDecimal = resolveAllowDecimal(config);
12    const obj = {
13      selector: config.selector || ".number-separator",
14      separator: config.separator || ",",
15      decimalSeparator: config.decimalSeparator || ".",
16      resultInput: config.resultInput,
17      allowDecimal,
18      decimal: allowDecimal,
19      forceDecimal: tcg.mc.currency === "IDRK" || config.forceDecimal || false,
20      maxIntegerDigits: tcg.mc.currency === "IDRK" ? 15 : null, // 限制整數位數
21      listenPointer: config.listenPointer ?? true,
22    };
23    if (!obj.allowDecimal) {
24      obj.forceDecimal = false;
25    }
26    function clampCaretToInteger(input, dotChar) {
27      const v = input.value || "";
28      const dot = v.indexOf(dotChar);
29      if (dot === -1) return;
30      const start = input.selectionStart ?? 0;
31      const end = input.selectionEnd ?? 0;
32      if (start > dot || end > dot) input.setSelectionRange(dot, dot);
33    }
34
35    function listenSelectionClamp() {
36      const sel = obj.selector;
37
38      $(document)
39        .off("focusin.decimalClamp focusout.decimalClamp", sel)
40        .on("focusin.decimalClamp", sel, function () {
41          const el = this;
42          const handler = function () {
43            if (!obj.forceDecimal) return;
44            if (document.activeElement !== el) return;
45            clampCaretToInteger(el, tcg.mc.getDecimalSeparator());
46          };
47          $(el).data("decimalClampHandler", handler);
48          document.addEventListener("selectionchange", handler, { passive: true });
49        })
50        .on("focusout.decimalClamp", sel, function () {
51          const el = this;
52          const handler = $(el).data("decimalClampHandler");
53          if (handler) {
54            document.removeEventListener("selectionchange", handler);
55            $(el).removeData("decimalClampHandler");
56          }
57        });
58    }
59
60    function listenKeydownHard() {
61      $(obj.selector)
62        .off("keydown.decimalClamp")
63        .on("keydown.decimalClamp", function (e) {
64          if (!obj.forceDecimal) return;
65
66          const el = this;
67          const val = el.value || "";
68          const dotChar = tcg.mc.getDecimalSeparator();
69          const dot = val.indexOf(dotChar);
70          if (dot === -1) return;
71
72          const s = el.selectionStart ?? 0;
73          const epos = el.selectionEnd ?? 0;
74          const crosses = s < dot && epos > dot;
75          const atOrAfterDot = s >= dot || crosses;
76
77          const isDigit = (e.key >= "0" && e.key <= "9") || (e.code && /Numpad[0-9]/.test(e.code));
78          const isDotKey = e.key === "." || e.key === ",";
79
80          if (isDigit || isDotKey) {
81            const atAfterDotStrict = s > dot || crosses;
82            if (atAfterDotStrict) {
83              e.preventDefault();
84              el.setSelectionRange(dot, dot);
85              return;
86            }
87          }
88
89          if (e.key === "ArrowRight" || e.key === "End") {
90            if (atOrAfterDot) {
91              e.preventDefault();
92              el.setSelectionRange(dot, dot);
93            }
94          }
95        });
96    }
97
98    function listenKeydown() {
99      $(obj.selector)
100        .off("keydown.numberSeparator")
101        .on("keydown.numberSeparator", function (e) {
102          if (!obj.forceDecimal) return;
103          const dotChar = tcg.mc.getDecimalSeparator();
104          const val = this.value;
105          const dotPos = val.indexOf(dotChar);
106          const intPart = dotPos === -1 ? val : val.slice(0, dotPos);
107          const intDigits = intPart.replace(/\D/g, "").length;
108          const maxInt = obj.maxIntegerDigits;
109
110          if (/^\d$/.test(e.key)) {
111            if (dotPos === -1 || this.selectionStart <= dotPos) {
112              if (maxInt && intDigits >= maxInt) {
113                e.preventDefault();
114                return;
115              }
116            }
117          }
118          if (dotPos === -1) return;
119          const selectionStart = this.selectionStart;
120          const selectionEnd = this.selectionEnd;
121          if (e.key === "ArrowRight" || e.key === "End") {
122            if (selectionStart > dotPos || (selectionStart < dotPos && selectionEnd > dotPos)) {
123              e.preventDefault();
124              this.setSelectionRange(dotPos, dotPos);
125            }
126          }
127        });
128    }
129
130    function listenPointer() {
131      $(obj.selector)
132        .off("mouseup.numberSeparator click.numberSeparator select.numberSeparator touchend.numberSeparator")
133        .on(
134          "mouseup.numberSeparator click.numberSeparator select.numberSeparator touchend.numberSeparator",
135          function () {
136            if (!obj.forceDecimal) return;
137            const el = this;
138            const dotChar = tcg.mc.getDecimalSeparator();
139            setTimeout(function () {
140              clampCaretToInteger(el, dotChar);
141            }, 0);
142          }
143        );
144    }
145
146    function numberSeparator(val, maxLength) {
147      if (tcg.mc.currency === "IDRK") {
148        obj.decimal = 3;
149        obj.forceDecimal = true;
150      }
151      if (!val) {
152        return "";
153      }
154      let num = val;
155      const el = $(obj.selector).get(0);
156      const dot = tcg.mc.getDecimalSeparator();
157      const caret = el ? el.selectionStart : null;
158      const dotIndex = val.indexOf(dot);
159      const editingFraction = dotIndex !== -1 && caret !== null && caret > dotIndex;
160
161      const endWithDecimal = num && num.endsWith(dot);
162      const parseNum = tcg.mc.parseFormatNumber(num);
163      const currentFracLen = dotIndex !== -1 ? (val.split(dot)[1] || "").length : 0;
164      const decimalLength = obj.forceDecimal && !editingFraction ? 3 : Math.min(3, currentFracLen);
165
166      if (String(parseNum).length > maxLength) {
167        const truncated = String(parseNum).slice(0, maxLength);
168        return tcg.mc.currencyFormat(truncated, decimalLength);
169      }
170
171      const decimal = obj.decimal ? decimalLength : 0;
172      const value = tcg.mc.currencyFormat(parseNum, decimal);
173      const regex = /^([^,]*,){2}[^,]*$/;
174      const singleComma = !regex.test(val);
175      if (endWithDecimal && tcg.mc.currency === "IDRK") return value;
176      num = val === "-" ? null : value + (endWithDecimal && singleComma ? dot : "");
177
178      if (tcg.mc.currency === "IDRK" && obj.forceDecimal && num && !editingFraction) {
179        setTimeout(function () {
180          const inputValue = $(obj.selector).val();
181          const dotChar = tcg.mc.getDecimalSeparator();
182          const dotIndexs = inputValue.indexOf(dotChar);
183          let focusPos;
184          if (dotIndexs !== -1) {
185            focusPos = dotIndexs;
186          } else {
187            const commas = (inputValue.match(/,/g) || []).length;
188            const intLen = String(parseNum).split(".")[0].length;
189            focusPos = intLen + commas;
190          }
191          $(obj.selector).focus().get(0).setSelectionRange(focusPos, focusPos);
192        }, 0);
193      }
194
195      return num;
196    }
197    function listenKeydownIntegerOnly() {
198      $(obj.selector)
199        .off("keydown.integerOnly")
200        .on("keydown.integerOnly", function (e) {
201          if (obj.allowDecimal) return;
202          const dotChar = tcg.mc.getDecimalSeparator();
203          if (e.key === dotChar || e.code === "NumpadDecimal") {
204            e.preventDefault();
205          }
206        });
207    }
208
209    function numberSeparatorNormal(val) {
210      if (!val) {
211        return "";
212      }
213      let num = val;
214      const dot = tcg.mc.getDecimalSeparator();
215      const endWithDecimal = obj.allowDecimal && num && num.endsWith(dot);
216      let parseNum = tcg.mc.parseFormatNumber(num);
217      if (!obj.allowDecimal && Number.isFinite(parseNum)) {
218        parseNum = Math.trunc(parseNum);
219      }
220      const decimalLength = obj.decimal ? Math.min(2, `${num}`.split(dot)[1]?.length || 0) : 0;
221      const decimal = obj.decimal ? decimalLength : 0;
222      const value = tcg.mc.currencyFormat(parseNum, decimal);
223      const regex = /^([^,]*,){2}[^,]*$/;
224      const singleComma = !regex.test(val);
225      num = val === "-" ? null : value + (endWithDecimal && singleComma ? dot : "");
226
227      return num;
228    }
229
230    function listenFields() {
231      $(obj.selector)
232        .off("input.numberSeparator")
233        .on("input.numberSeparator", function (e) {
234          const max = $(e.target).data("maxLength");
235          this.value = obj.listenPointer ? numberSeparator(this.value, max) : numberSeparatorNormal(this.value);
236          const parsedNum = tcg.mc.parseFormatNumber(this.value);
237          const attrStr = typeof parsedNum === "number" && Number.isFinite(parsedNum) ? String(parsedNum) : "";
238          this.setAttribute("formatamount", attrStr);
239        });
240    }
241
242    listenFields();
243    if (obj.listenPointer) {
244      listenKeydown();
245      listenPointer();
246      listenKeydownHard();
247      listenSelectionClamp();
248    } else if (!obj.allowDecimal) {
249      listenKeydownIntegerOnly();
250    }
251  };
252})(window, document, jQuery, window.tcg || {});

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.