jsuites 6.5.1 → 6.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/jsuites.js +80 -47
  2. package/package.json +5 -5
package/dist/jsuites.js CHANGED
@@ -991,6 +991,8 @@ var jSuites;
991
991
  const methodCache = {};
992
992
  // Cache for getTokens results
993
993
  const tokensCache = {};
994
+ // Cache for the parsed layout of each mask
995
+ const layoutCache = {};
994
996
  // Cache for autoCasting results
995
997
  const autoCastingCache = {};
996
998
 
@@ -1752,32 +1754,33 @@ var jSuites;
1752
1754
  '#(.{1})##0?(.{1}[0#]+)?( ?;(.*)?)?': function(v) {
1753
1755
  // Process first the number
1754
1756
  parseMethods['[0#]+([.,]{1}0*#*)?'].call(this, v, true);
1755
- // Create the separators
1756
- let separator = this.tokens[this.index].substring(1,2);
1757
-
1758
1757
 
1759
1758
  let currentValue = this.values[this.index];
1760
- // Remove existing separators and negative sign
1759
+ // The value is already grouped: only a new digit in the integer part changes it
1760
+ if (! (v >= '0' && v <= '9') || currentValue.indexOf(this.decimal) !== -1) {
1761
+ return;
1762
+ }
1763
+ // Create the separators
1764
+ let separator = this.tokens[this.index].substring(1,2);
1765
+ // Remove existing separators
1761
1766
  currentValue = currentValue.replaceAll(separator, '');
1762
1767
  // Process separators
1763
- let val = currentValue.split(this.decimal);
1764
- if (val[0].length > 3) {
1765
- let number = [];
1768
+ if (currentValue.length > 3) {
1769
+ let number = '';
1766
1770
  let count = 0;
1767
- for (var j = val[0].length - 1; j >= 0 ; j--) {
1768
- let c = val[0][j];
1769
- if (c >= 0 && c <= 9) {
1771
+ for (let j = currentValue.length - 1; j >= 0 ; j--) {
1772
+ let c = currentValue[j];
1773
+ if (c >= '0' && c <= '9') {
1770
1774
  if (count && ! (count % 3)) {
1771
- number.unshift(separator);
1775
+ number = separator + number;
1772
1776
  }
1773
1777
  count++;
1774
1778
  }
1775
- number.unshift(c);
1779
+ number = c + number;
1776
1780
  }
1777
- val[0] = number.join('');
1781
+ currentValue = number;
1778
1782
  }
1779
- // Reconstruct the value
1780
- this.values[this.index] = val.join(this.decimal);
1783
+ this.values[this.index] = currentValue;
1781
1784
  },
1782
1785
  '[0#]+([.,]{1}0*#*)?E{1}\\+0+': function(v) {
1783
1786
  parseMethods['[0#]+([.,]{1}0*#*)?'].call(this, v);
@@ -2260,6 +2263,26 @@ var jSuites;
2260
2263
 
2261
2264
  // TODO, get negative mask automatically based on the input sign?
2262
2265
 
2266
+ /**
2267
+ * Parse the parts of a mask that do not depend on the value
2268
+ */
2269
+ const getLayout = function(mask) {
2270
+ const layout = {};
2271
+ // Transform Excel locale patterns (e.g., [$$-409]#,##0.00) - only if pattern exists
2272
+ if (mask.indexOf('[$') !== -1) {
2273
+ mask = transformExcelLocaleMask(mask);
2274
+ }
2275
+ // Cleaning the mask
2276
+ layout.mask = cleanMask(mask, layout);
2277
+ // Get tokens which are the methods for parsing
2278
+ layout.tokens = getTokens(layout.mask);
2279
+ // Get methods from the tokens
2280
+ layout.methods = getMethodsFromTokens(layout.tokens);
2281
+ // Type
2282
+ layout.type = getType(layout);
2283
+ return layout;
2284
+ }
2285
+
2263
2286
  const getConfig = function(config, value) {
2264
2287
  // Internal default control of the mask system
2265
2288
  const control = {
@@ -2326,21 +2349,28 @@ var jSuites;
2326
2349
  control.section = mask;
2327
2350
  }
2328
2351
 
2329
- // Transform Excel locale patterns (e.g., [$$-409]#,##0.00) - only if pattern exists
2330
- if (mask.indexOf('[$') !== -1) {
2331
- mask = transformExcelLocaleMask(mask);
2352
+ // The layout depends only on the mask: parse it once
2353
+ let layout = layoutCache[mask];
2354
+ if (layout === undefined) {
2355
+ layout = layoutCache[mask] = getLayout(mask);
2356
+ }
2357
+ if (layout.parenthesisForNegativeNumbers) {
2358
+ control.parenthesisForNegativeNumbers = true;
2332
2359
  }
2333
-
2334
- // Cleaning the mask
2335
- mask = cleanMask(mask, control);
2336
2360
  // Get only the first mask for now and remove
2337
- control.mask = mask;
2338
- // Get tokens which are the methods for parsing
2339
- let tokens = control.tokens = getTokens(mask);
2340
- // Get methods from the tokens
2341
- control.methods = getMethodsFromTokens(tokens);
2342
- // Type
2343
- control.type = getType(control);
2361
+ control.mask = layout.mask;
2362
+ // Tokens and methods are shared and read-only
2363
+ control.tokens = layout.tokens;
2364
+ control.methods = layout.methods;
2365
+ control.type = layout.type;
2366
+
2367
+ // Decimal only for numbers. Without options, it comes from the mask
2368
+ if (isNumeric(control.type) && ! control.decimal && ! control.locale) {
2369
+ if (layout.decimal === undefined) {
2370
+ layout.decimal = getDecimal.call(control);
2371
+ }
2372
+ control.decimal = layout.decimal;
2373
+ }
2344
2374
  }
2345
2375
 
2346
2376
  // Decimal only for numbers
@@ -6094,6 +6124,18 @@ if (! Modal && "function" === 'function') {
6094
6124
  return s;
6095
6125
  }
6096
6126
 
6127
+ // Any scroll outside the menu closes it (matches the OS context menu:
6128
+ // the menu refers to the spot that was right-clicked, and scrolling
6129
+ // moves that content away). Capture phase: scroll does not bubble.
6130
+ // Scrolling INSIDE a long menu list keeps it open. Listening only
6131
+ // while the menu is open: a window listener kept for good would also
6132
+ // keep the menu, and what holds it, alive after it is gone
6133
+ const scroll = function(e) {
6134
+ if (! self.isClosed() && ! (e.target instanceof Node && self.el.contains(e.target))) {
6135
+ self.close(0);
6136
+ }
6137
+ }
6138
+
6097
6139
  self.isClosed = function() {
6098
6140
  return self.modals[0].modal.closed === true;
6099
6141
  }
@@ -6171,6 +6213,7 @@ if (! Modal && "function" === 'function') {
6171
6213
  }
6172
6214
  });
6173
6215
  }
6216
+ window.addEventListener("scroll", scroll, true);
6174
6217
  // Focus
6175
6218
  self.el.classList.add('lm-menu-focus');
6176
6219
  // Focus on the contextmenu. preventScroll stops the browser from
@@ -6195,6 +6238,7 @@ if (! Modal && "function" === 'function') {
6195
6238
 
6196
6239
  // Close event
6197
6240
  if (level === 0) {
6241
+ window.removeEventListener("scroll", scroll, true);
6198
6242
  self.el.classList.remove('lm-menu-focus');
6199
6243
 
6200
6244
  Dispatch.call(self, self.onclose, 'close', {
@@ -6214,16 +6258,6 @@ if (! Modal && "function" === 'function') {
6214
6258
  }
6215
6259
  });
6216
6260
 
6217
- // Any scroll outside the menu closes it (matches the OS context menu:
6218
- // the menu refers to the spot that was right-clicked, and scrolling
6219
- // moves that content away). Capture phase: scroll does not bubble.
6220
- // Scrolling INSIDE a long menu list keeps it open
6221
- window.addEventListener("scroll", function(e) {
6222
- if (! self.isClosed() && ! (e.target instanceof Node && self.el.contains(e.target))) {
6223
- self.close(0);
6224
- }
6225
- }, true);
6226
-
6227
6261
  // Keyboard event
6228
6262
  self.el.addEventListener("keydown", function(e) {
6229
6263
  // Menu object
@@ -7627,8 +7661,6 @@ if (!lemonade && "function" === 'function') {
7627
7661
  }
7628
7662
  }
7629
7663
 
7630
- // References
7631
- const modals = [];
7632
7664
  // State of the resize and move modal
7633
7665
  let state = {};
7634
7666
  // Internal controls of the action of resize and move
@@ -7646,8 +7678,11 @@ if (!lemonade && "function" === 'function') {
7646
7678
  */
7647
7679
  const sendToFront = function (container) {
7648
7680
  let highestXIndex = defaultZIndex;
7681
+ // The modals on the page. A registry of the instances would keep
7682
+ // every modal ever created alive, the ones of destroyed components too
7683
+ const modals = document.querySelectorAll('.lm-modal');
7649
7684
  for (let i = 0; i < modals.length; i++) {
7650
- const zIndex = parseInt(modals[i].el.style.zIndex);
7685
+ const zIndex = parseInt(modals[i].style.zIndex);
7651
7686
  if (zIndex > highestXIndex) {
7652
7687
  highestXIndex = zIndex;
7653
7688
  }
@@ -8032,9 +8067,6 @@ if (!lemonade && "function" === 'function') {
8032
8067
  // Make sure keep the state as boolean
8033
8068
  self.closed = !!self.closed;
8034
8069
 
8035
- // Keep all modals references
8036
- modals.push(self);
8037
-
8038
8070
  // External onload remove from the lifecycle
8039
8071
  let change = self.onchange;
8040
8072
  self.onchange = null;
@@ -12593,13 +12625,14 @@ function Path(pathString, value, remove) {
12593
12625
  return false;
12594
12626
  }
12595
12627
 
12628
+ // Own keys only: a write never walks into what the object inherits
12596
12629
  // If the key exists but is null/undefined or a non-object, replace it with an empty object
12597
12630
  if (
12598
- key in currentObject &&
12631
+ Object.hasOwn(currentObject, key) &&
12599
12632
  (currentObject[key] == null || ! isValidPathObj(currentObject[key]))
12600
12633
  ) {
12601
12634
  currentObject[key] = {};
12602
- } else if (!(key in currentObject)) {
12635
+ } else if (! Object.hasOwn(currentObject, key)) {
12603
12636
  // If the key doesn't exist, create an empty object
12604
12637
  currentObject[key] = {};
12605
12638
  }
@@ -23549,7 +23582,7 @@ var jSuites = {
23549
23582
  ...dictionary,
23550
23583
  ...helpers,
23551
23584
  /** Current version */
23552
- version: '6.5.1',
23585
+ version: '6.6.0',
23553
23586
  /** Bind new extensions to Jsuites */
23554
23587
  setExtensions: function(o) {
23555
23588
  if (typeof(o) == 'object') {
package/package.json CHANGED
@@ -26,22 +26,22 @@
26
26
  },
27
27
  "main": "dist/jsuites.js",
28
28
  "types": "dist/jsuites.d.ts",
29
- "version": "6.5.1",
29
+ "version": "6.6.0",
30
30
  "bugs": "https://github.com/jsuites/jsuites/issues",
31
31
  "homepage": "https://github.com/jsuites/jsuites",
32
32
  "docs": "https://jsuites.net",
33
33
  "download": "https://github.com/jsuites/jsuites/archive/master.zip",
34
34
  "dependencies": {
35
- "@jsuites/utils": "^6.1.0",
35
+ "@jsuites/utils": "^6.2.0",
36
36
  "@lemonadejs/calendar": "^5.9.3",
37
37
  "@lemonadejs/color": "^5.8.0",
38
- "@lemonadejs/contextmenu": "^5.8.4",
39
- "@lemonadejs/dropdown": "^5.8.3",
38
+ "@lemonadejs/contextmenu": "^5.8.6",
39
+ "@lemonadejs/dropdown": "^5.8.4",
40
40
  "@lemonadejs/modal": "^5.8.3",
41
41
  "@lemonadejs/rating": "^5.8.1",
42
42
  "@lemonadejs/switch": "^5.8.0",
43
43
  "@lemonadejs/tabs": "^5.8.0",
44
- "@lemonadejs/topmenu": "^5.8.0"
44
+ "@lemonadejs/topmenu": "^5.8.1"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@babel/preset-env": "^7.28.5",