@lowentry/utils 0.2.1 → 1.0.1
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.
- package/LeTypes.js +0 -13
- package/LeUtils.js +576 -43
- package/index.js +2 -2
- package/package.json +1 -1
package/LeTypes.js
CHANGED
|
@@ -1,16 +1,3 @@
|
|
|
1
|
-
import FastDeepEqual from 'fast-deep-equal';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* A deep equals implementation (npm package "fast-deep-equal").
|
|
6
|
-
*
|
|
7
|
-
* @param {*} value The value to compare.
|
|
8
|
-
* @param {*} other The other value to compare.
|
|
9
|
-
* @returns {boolean} Returns true if the values are equivalent.
|
|
10
|
-
*/
|
|
11
|
-
export const EQUAL = FastDeepEqual;
|
|
12
|
-
|
|
13
|
-
|
|
14
1
|
/**
|
|
15
2
|
* Returns true if the value is set (not undefined and not null).
|
|
16
3
|
*
|
package/LeUtils.js
CHANGED
|
@@ -1,7 +1,49 @@
|
|
|
1
|
+
import FastDeepEqual from 'fast-deep-equal';
|
|
1
2
|
import {ISSET, IS_OBJECT, STRING, INT_LAX, FLOAT_LAX, INT_LAX_ANY, FLOAT_LAX_ANY} from './LeTypes.js';
|
|
2
3
|
|
|
3
4
|
|
|
5
|
+
/**
|
|
6
|
+
* @param {LeUtils~TransactionalValue} transactionalValue
|
|
7
|
+
*/
|
|
8
|
+
const checkTransactionalValue = (transactionalValue) =>
|
|
9
|
+
{
|
|
10
|
+
if(!LeUtils.isTransactionalValueValid(transactionalValue))
|
|
11
|
+
{
|
|
12
|
+
console.error('The given value is not a valid TransactionalValue:');
|
|
13
|
+
console.error(transactionalValue);
|
|
14
|
+
throw new Error('The given value is not a valid TransactionalValue');
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {LeUtils~TransactionalValue} transactionalValue
|
|
20
|
+
* @param {string} changeId
|
|
21
|
+
* @returns {{index:number, value:*}|null}
|
|
22
|
+
*/
|
|
23
|
+
const findTransactionalValueChange = (transactionalValue, changeId) =>
|
|
24
|
+
{
|
|
25
|
+
for(let i = 0; i < transactionalValue.changes.length; i++)
|
|
26
|
+
{
|
|
27
|
+
const change = transactionalValue.changes[i];
|
|
28
|
+
if(change.id === changeId)
|
|
29
|
+
{
|
|
30
|
+
return {index:i, value:change.value};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
|
|
4
37
|
export const LeUtils = {
|
|
38
|
+
/**
|
|
39
|
+
* A deep equals implementation (npm package "fast-deep-equal").
|
|
40
|
+
*
|
|
41
|
+
* @param {*} value The value to compare.
|
|
42
|
+
* @param {*} other The other value to compare.
|
|
43
|
+
* @returns {boolean} Returns true if the values are equivalent.
|
|
44
|
+
*/
|
|
45
|
+
equals:FastDeepEqual,
|
|
46
|
+
|
|
5
47
|
/**
|
|
6
48
|
* Parses the given version string, and returns an object with the major, minor, and patch numbers, as well as some comparison functions.
|
|
7
49
|
*
|
|
@@ -738,18 +780,7 @@ export const LeUtils = {
|
|
|
738
780
|
* @returns {number}
|
|
739
781
|
*/
|
|
740
782
|
compare:
|
|
741
|
-
(a, b) =>
|
|
742
|
-
{
|
|
743
|
-
if(a < b)
|
|
744
|
-
{
|
|
745
|
-
return -1;
|
|
746
|
-
}
|
|
747
|
-
if(a > b)
|
|
748
|
-
{
|
|
749
|
-
return 1;
|
|
750
|
-
}
|
|
751
|
-
return 0;
|
|
752
|
-
},
|
|
783
|
+
(a, b) => (a < b) ? -1 : ((a > b) ? 1 : 0),
|
|
753
784
|
|
|
754
785
|
/**
|
|
755
786
|
* Compares two numbers. Primarily used for sorting.
|
|
@@ -1377,6 +1408,40 @@ export const LeUtils = {
|
|
|
1377
1408
|
return messageParts[messageParts.length - 1].trim();
|
|
1378
1409
|
},
|
|
1379
1410
|
|
|
1411
|
+
/**
|
|
1412
|
+
* Generates all permutations of the given names.
|
|
1413
|
+
*
|
|
1414
|
+
* For example, if you pass "foo" and "bar", it will return:
|
|
1415
|
+
* - foobar
|
|
1416
|
+
* - fooBar
|
|
1417
|
+
* - FooBar
|
|
1418
|
+
* - foo-bar
|
|
1419
|
+
* - foo_bar
|
|
1420
|
+
*
|
|
1421
|
+
* @param {string} names
|
|
1422
|
+
* @returns {string[]}
|
|
1423
|
+
*/
|
|
1424
|
+
generateNamePermutations:
|
|
1425
|
+
(...names) =>
|
|
1426
|
+
{
|
|
1427
|
+
names = LeUtils.flattenArray(names)
|
|
1428
|
+
.map(name => STRING(name).trim().toLowerCase())
|
|
1429
|
+
.filter(name => (name.length > 0));
|
|
1430
|
+
let results = [];
|
|
1431
|
+
if(names.length > 0)
|
|
1432
|
+
{
|
|
1433
|
+
results.push(names.join('')); //foobar
|
|
1434
|
+
results.push(names.map(LeUtils.capitalize).join('')); //FooBar
|
|
1435
|
+
}
|
|
1436
|
+
if(names.length > 1)
|
|
1437
|
+
{
|
|
1438
|
+
results.push([names[0]].concat(names.slice(1).map(LeUtils.capitalize)).join('')); //fooBar
|
|
1439
|
+
results.push(names.join('-')); //foo-bar
|
|
1440
|
+
results.push(names.join('_')); //foo_bar
|
|
1441
|
+
}
|
|
1442
|
+
return results;
|
|
1443
|
+
},
|
|
1444
|
+
|
|
1380
1445
|
/**
|
|
1381
1446
|
* Increases the given numeric string by 1, this allows you to increase a numeric string without a limit.
|
|
1382
1447
|
*
|
|
@@ -1608,27 +1673,27 @@ export const LeUtils = {
|
|
|
1608
1673
|
},
|
|
1609
1674
|
|
|
1610
1675
|
/**
|
|
1611
|
-
* Returns the
|
|
1676
|
+
* Returns the RGB(A) of the given hex color.
|
|
1612
1677
|
*
|
|
1613
|
-
* @param {
|
|
1678
|
+
* @param {string} hexstring
|
|
1614
1679
|
* @returns {number[]}
|
|
1615
1680
|
*/
|
|
1616
|
-
|
|
1617
|
-
(
|
|
1681
|
+
hexToRgb:
|
|
1682
|
+
(hexstring) =>
|
|
1618
1683
|
{
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1684
|
+
hexstring = hexstring.replace(/[^0-9A-F]/gi, '');
|
|
1685
|
+
const hasAlpha = ((hexstring.length === 4) || (hexstring.length === 8));
|
|
1686
|
+
while(hexstring.length < 6)
|
|
1687
|
+
{
|
|
1688
|
+
hexstring = hexstring.replace(/(.)/g, '$1$1');
|
|
1689
|
+
}
|
|
1690
|
+
const result = hexstring.match(/\w{2}/g).map((a) => parseInt(a, 16));
|
|
1691
|
+
return [
|
|
1692
|
+
result[0],
|
|
1693
|
+
result[1],
|
|
1694
|
+
result[2],
|
|
1695
|
+
...(hasAlpha ? [result[3]] : []),
|
|
1696
|
+
];
|
|
1632
1697
|
},
|
|
1633
1698
|
|
|
1634
1699
|
/**
|
|
@@ -1643,11 +1708,9 @@ export const LeUtils = {
|
|
|
1643
1708
|
const r = rgb[0] / 255;
|
|
1644
1709
|
const g = rgb[1] / 255;
|
|
1645
1710
|
const b = rgb[2] / 255;
|
|
1646
|
-
|
|
1647
1711
|
const max = Math.max(r, g, b);
|
|
1648
1712
|
const min = Math.min(r, g, b);
|
|
1649
1713
|
let h, s, l = (max + min) / 2;
|
|
1650
|
-
|
|
1651
1714
|
if(max === min)
|
|
1652
1715
|
{
|
|
1653
1716
|
h = s = 0;
|
|
@@ -1670,16 +1733,90 @@ export const LeUtils = {
|
|
|
1670
1733
|
}
|
|
1671
1734
|
h /= 6;
|
|
1672
1735
|
}
|
|
1673
|
-
|
|
1674
|
-
|
|
1736
|
+
return [h, s, l, ...((rgb.length >= 4) ? [rgb[3] / 255] : [])];
|
|
1737
|
+
},
|
|
1738
|
+
|
|
1739
|
+
/**
|
|
1740
|
+
* Returns the RGB(A) of the given HSL(A).
|
|
1741
|
+
*
|
|
1742
|
+
* @param {number[]} hsl
|
|
1743
|
+
* @returns {number[]}
|
|
1744
|
+
*/
|
|
1745
|
+
hslToRgb:
|
|
1746
|
+
(() =>
|
|
1747
|
+
{
|
|
1748
|
+
const hue2rgb = (p, q, t) =>
|
|
1675
1749
|
{
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1750
|
+
if(t < 0)
|
|
1751
|
+
{
|
|
1752
|
+
t += 1;
|
|
1753
|
+
}
|
|
1754
|
+
if(t > 1)
|
|
1755
|
+
{
|
|
1756
|
+
t -= 1;
|
|
1757
|
+
}
|
|
1758
|
+
if(t < 1 / 6)
|
|
1759
|
+
{
|
|
1760
|
+
return p + (q - p) * 6 * t;
|
|
1761
|
+
}
|
|
1762
|
+
if(t < 1 / 2)
|
|
1763
|
+
{
|
|
1764
|
+
return q;
|
|
1765
|
+
}
|
|
1766
|
+
if(t < 2 / 3)
|
|
1767
|
+
{
|
|
1768
|
+
return p + (q - p) * (2 / 3 - t) * 6;
|
|
1769
|
+
}
|
|
1770
|
+
return p;
|
|
1771
|
+
};
|
|
1772
|
+
return (hsl) =>
|
|
1773
|
+
{
|
|
1774
|
+
const h = hsl[0];
|
|
1775
|
+
const s = hsl[1];
|
|
1776
|
+
const l = hsl[2];
|
|
1777
|
+
let r, g, b;
|
|
1778
|
+
if(s === 0)
|
|
1779
|
+
{
|
|
1780
|
+
r = g = b = l;
|
|
1781
|
+
}
|
|
1782
|
+
else
|
|
1783
|
+
{
|
|
1784
|
+
const q = (l < 0.5) ? (l * (1 + s)) : (l + s - (l * s));
|
|
1785
|
+
const p = (2 * l) - q;
|
|
1786
|
+
r = hue2rgb(p, q, h + (1 / 3));
|
|
1787
|
+
g = hue2rgb(p, q, h);
|
|
1788
|
+
b = hue2rgb(p, q, h - (1 / 3));
|
|
1789
|
+
}
|
|
1790
|
+
return [r * 255, g * 255, b * 255, ...((hsl.length >= 4) ? [hsl[3] * 255] : [])].map((c) => Math.max(0, Math.min(255, Math.round(c))));
|
|
1791
|
+
};
|
|
1792
|
+
})(),
|
|
1793
|
+
|
|
1794
|
+
/**
|
|
1795
|
+
* Returns the LAB(A) of the given RGB(A).
|
|
1796
|
+
*
|
|
1797
|
+
* @param {number[]} rgb
|
|
1798
|
+
* @returns {number[]}
|
|
1799
|
+
*/
|
|
1800
|
+
rgbToLab:
|
|
1801
|
+
(rgb) =>
|
|
1802
|
+
{
|
|
1803
|
+
let r = rgb[0] / 255;
|
|
1804
|
+
let g = rgb[1] / 255;
|
|
1805
|
+
let b = rgb[2] / 255;
|
|
1806
|
+
r = (r > 0.04045) ? Math.pow((r + 0.055) / 1.055, 2.4) : (r / 12.92);
|
|
1807
|
+
g = (g > 0.04045) ? Math.pow((g + 0.055) / 1.055, 2.4) : (g / 12.92);
|
|
1808
|
+
b = (b > 0.04045) ? Math.pow((b + 0.055) / 1.055, 2.4) : (b / 12.92);
|
|
1809
|
+
let x = ((r * 0.4124) + (g * 0.3576) + (b * 0.1805)) / 0.95047;
|
|
1810
|
+
let y = ((r * 0.2126) + (g * 0.7152) + (b * 0.0722));
|
|
1811
|
+
let z = ((r * 0.0193) + (g * 0.1192) + (b * 0.9505)) / 1.08883;
|
|
1812
|
+
x = (x > 0.008856) ? Math.pow(x, 1 / 3) : (7.787 * x) + (16 / 116);
|
|
1813
|
+
y = (y > 0.008856) ? Math.pow(y, 1 / 3) : (7.787 * y) + (16 / 116);
|
|
1814
|
+
z = (z > 0.008856) ? Math.pow(z, 1 / 3) : (7.787 * z) + (16 / 116);
|
|
1815
|
+
return [(116 * y) - 16, 500 * (x - y), 200 * (y - z), ...((rgb.length >= 4) ? [rgb[3] / 255] : [])];
|
|
1679
1816
|
},
|
|
1680
1817
|
|
|
1681
1818
|
/**
|
|
1682
|
-
* Returns the difference (calculated with DeltaE) of the
|
|
1819
|
+
* Returns the difference (calculated with DeltaE) of the LAB values of the given RGB values.
|
|
1683
1820
|
*
|
|
1684
1821
|
* Returns a number:
|
|
1685
1822
|
*
|
|
@@ -1704,7 +1841,7 @@ export const LeUtils = {
|
|
|
1704
1841
|
},
|
|
1705
1842
|
|
|
1706
1843
|
/**
|
|
1707
|
-
* Returns the difference (calculated with DeltaE) of the given
|
|
1844
|
+
* Returns the difference (calculated with DeltaE) of the given LAB values. Ignores the Alpha channel.
|
|
1708
1845
|
*
|
|
1709
1846
|
* Returns a number:
|
|
1710
1847
|
*
|
|
@@ -1737,7 +1874,7 @@ export const LeUtils = {
|
|
|
1737
1874
|
const deltaCkcsc = deltaC / (sc);
|
|
1738
1875
|
const deltaHkhsh = deltaH / (sh);
|
|
1739
1876
|
const i = deltaLKlsl * deltaLKlsl + deltaCkcsc * deltaCkcsc + deltaHkhsh * deltaHkhsh;
|
|
1740
|
-
return i < 0 ? 0 : Math.sqrt(i);
|
|
1877
|
+
return (i < 0) ? 0 : Math.sqrt(i);
|
|
1741
1878
|
},
|
|
1742
1879
|
|
|
1743
1880
|
/**
|
|
@@ -1930,7 +2067,7 @@ export const LeUtils = {
|
|
|
1930
2067
|
base64ToUtf8:
|
|
1931
2068
|
(base64string) =>
|
|
1932
2069
|
{
|
|
1933
|
-
return decodeURIComponent(LeUtils.atob(base64string).split('').map((c) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)).join(''));
|
|
2070
|
+
return decodeURIComponent(LeUtils.atob(base64string.trim()).split('').map((c) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)).join(''));
|
|
1934
2071
|
},
|
|
1935
2072
|
|
|
1936
2073
|
/**
|
|
@@ -1942,7 +2079,7 @@ export const LeUtils = {
|
|
|
1942
2079
|
base64ToHex:
|
|
1943
2080
|
(base64string) =>
|
|
1944
2081
|
{
|
|
1945
|
-
return LeUtils.atob(base64string).split('').map((c) => ('0' + c.charCodeAt(0).toString(16)).slice(-2)).join('');
|
|
2082
|
+
return LeUtils.atob(base64string.trim()).split('').map((c) => ('0' + c.charCodeAt(0).toString(16)).slice(-2)).join('');
|
|
1946
2083
|
},
|
|
1947
2084
|
|
|
1948
2085
|
/**
|
|
@@ -1954,7 +2091,7 @@ export const LeUtils = {
|
|
|
1954
2091
|
hexToBase64:
|
|
1955
2092
|
(hexstring) =>
|
|
1956
2093
|
{
|
|
1957
|
-
return LeUtils.btoa(hexstring.match(/\w{2}/g).map((a) => String.fromCharCode(parseInt(a, 16))).join(''));
|
|
2094
|
+
return LeUtils.btoa(hexstring.replace(/[^0-9A-F]/gi, '').match(/\w{2}/g).map((a) => String.fromCharCode(parseInt(a, 16))).join(''));
|
|
1958
2095
|
},
|
|
1959
2096
|
|
|
1960
2097
|
/**
|
|
@@ -1966,7 +2103,7 @@ export const LeUtils = {
|
|
|
1966
2103
|
base64ToBytes:
|
|
1967
2104
|
(base64string) =>
|
|
1968
2105
|
{
|
|
1969
|
-
const binary = LeUtils.atob(base64string);
|
|
2106
|
+
const binary = LeUtils.atob(base64string.trim());
|
|
1970
2107
|
const len = binary.length;
|
|
1971
2108
|
let data = new Uint8Array(len);
|
|
1972
2109
|
for(let i = 0; i < len; i++)
|
|
@@ -1995,6 +2132,23 @@ export const LeUtils = {
|
|
|
1995
2132
|
return LeUtils.btoa(binary);
|
|
1996
2133
|
},
|
|
1997
2134
|
|
|
2135
|
+
/**
|
|
2136
|
+
* Downloads the given base64 string as a file.
|
|
2137
|
+
*
|
|
2138
|
+
* @param {string} base64string
|
|
2139
|
+
* @param {string} [fileName]
|
|
2140
|
+
* @param {string} [mimeType]
|
|
2141
|
+
*/
|
|
2142
|
+
downloadFile:
|
|
2143
|
+
(base64string, fileName, mimeType) =>
|
|
2144
|
+
{
|
|
2145
|
+
const link = document.createElement('a');
|
|
2146
|
+
link.setAttribute('download', (typeof fileName === 'string') ? fileName : 'file');
|
|
2147
|
+
link.href = 'data:' + mimeType + ';base64,' + base64string;
|
|
2148
|
+
link.setAttribute('target', '_blank');
|
|
2149
|
+
link.click();
|
|
2150
|
+
},
|
|
2151
|
+
|
|
1998
2152
|
/**
|
|
1999
2153
|
* Loads the value from the browser, returns undefined if the value doesn't exist.
|
|
2000
2154
|
*
|
|
@@ -2061,4 +2215,383 @@ export const LeUtils = {
|
|
|
2061
2215
|
}
|
|
2062
2216
|
window.localStorage.removeItem('LeUtils_' + id);
|
|
2063
2217
|
},
|
|
2218
|
+
|
|
2219
|
+
/**
|
|
2220
|
+
* Creates and returns a new TreeSet.
|
|
2221
|
+
* A TreeSet is a set of elements, sorted by a comparator.
|
|
2222
|
+
* Binary search is used to find elements, which makes it very fast to find elements.
|
|
2223
|
+
*
|
|
2224
|
+
* The comparator is also used to determine if two values are equal to each other.
|
|
2225
|
+
* This way, you can have values that aren't the same be treated as if they are. This can be used to deal with issues such as floating point errors for example.
|
|
2226
|
+
*
|
|
2227
|
+
* @param {*[]} elements
|
|
2228
|
+
* @param {Function} comparator
|
|
2229
|
+
* @returns {{getElements: (function(): *[]), getComparator: (function(): Function), size: (function(): number), isEmpty: (function(): boolean), contains: (function(*): boolean), first: (function(): *|undefined), last: (function(): *|undefined), pollFirst: (function(): *|undefined), pollLast: (function(): *|undefined), add: function(*), addAll: function(*[]|object), getEqualValue: (function(*): (*)), getEqualValueOrAdd: (function(*): (*))}}
|
|
2230
|
+
*/
|
|
2231
|
+
createTreeSet:
|
|
2232
|
+
(elements, comparator) =>
|
|
2233
|
+
{
|
|
2234
|
+
comparator = comparator || LeUtils.compare;
|
|
2235
|
+
elements = elements || [];
|
|
2236
|
+
elements.sort(comparator);
|
|
2237
|
+
|
|
2238
|
+
/**
|
|
2239
|
+
* Performs a binary search on the elements, and returns the result.
|
|
2240
|
+
*
|
|
2241
|
+
* @param {*} value
|
|
2242
|
+
* @returns {{found: boolean, index: number, value: *|undefined}}
|
|
2243
|
+
*/
|
|
2244
|
+
const binarySearch = (value) =>
|
|
2245
|
+
{
|
|
2246
|
+
let low = 0;
|
|
2247
|
+
let high = elements.length - 1;
|
|
2248
|
+
while(low <= high)
|
|
2249
|
+
{
|
|
2250
|
+
const mid = Math.floor((low + high) / 2);
|
|
2251
|
+
const midValue = elements[mid];
|
|
2252
|
+
const cmp = comparator(midValue, value);
|
|
2253
|
+
if(cmp < 0)
|
|
2254
|
+
{
|
|
2255
|
+
low = mid + 1;
|
|
2256
|
+
}
|
|
2257
|
+
else if(cmp > 0)
|
|
2258
|
+
{
|
|
2259
|
+
high = mid - 1;
|
|
2260
|
+
}
|
|
2261
|
+
else
|
|
2262
|
+
{
|
|
2263
|
+
return {found:true, index:mid, value:midValue};
|
|
2264
|
+
}
|
|
2265
|
+
}
|
|
2266
|
+
return {found:false, index:low, value:undefined};
|
|
2267
|
+
};
|
|
2268
|
+
|
|
2269
|
+
const treeSet = {
|
|
2270
|
+
/**
|
|
2271
|
+
* Returns the elements of the set.
|
|
2272
|
+
*
|
|
2273
|
+
* @returns {*[]}
|
|
2274
|
+
*/
|
|
2275
|
+
getElements:
|
|
2276
|
+
() => elements,
|
|
2277
|
+
|
|
2278
|
+
/**
|
|
2279
|
+
* Returns the comparator of the set.
|
|
2280
|
+
*
|
|
2281
|
+
* @returns {Function}
|
|
2282
|
+
*/
|
|
2283
|
+
getComparator:
|
|
2284
|
+
() => comparator,
|
|
2285
|
+
|
|
2286
|
+
/**
|
|
2287
|
+
* Returns the size of the set.
|
|
2288
|
+
*
|
|
2289
|
+
* @returns {number}
|
|
2290
|
+
*/
|
|
2291
|
+
size:
|
|
2292
|
+
() => elements.length,
|
|
2293
|
+
|
|
2294
|
+
/**
|
|
2295
|
+
* Returns true if the set is empty, false otherwise.
|
|
2296
|
+
*
|
|
2297
|
+
* @returns {boolean}
|
|
2298
|
+
*/
|
|
2299
|
+
isEmpty:
|
|
2300
|
+
() => (elements.length <= 0),
|
|
2301
|
+
|
|
2302
|
+
/**
|
|
2303
|
+
* Returns true if the set contains a value that is equal to the given value, returns false otherwise.
|
|
2304
|
+
*
|
|
2305
|
+
* @param {*} value
|
|
2306
|
+
* @returns {boolean}
|
|
2307
|
+
*/
|
|
2308
|
+
contains:
|
|
2309
|
+
(value) => binarySearch(value).found,
|
|
2310
|
+
|
|
2311
|
+
/**
|
|
2312
|
+
* Returns the first element of the set, or undefined if it is empty.
|
|
2313
|
+
*
|
|
2314
|
+
* @returns {*|undefined}
|
|
2315
|
+
*/
|
|
2316
|
+
first:
|
|
2317
|
+
() => (elements.length > 0) ? elements[0] : undefined,
|
|
2318
|
+
|
|
2319
|
+
/**
|
|
2320
|
+
* Returns the last element of the set, or undefined if it is empty.
|
|
2321
|
+
*
|
|
2322
|
+
* @returns {*|undefined}
|
|
2323
|
+
*/
|
|
2324
|
+
last:
|
|
2325
|
+
() => (elements.length > 0) ? elements[elements.length - 1] : undefined,
|
|
2326
|
+
|
|
2327
|
+
/**
|
|
2328
|
+
* Removes and returns the first element of the set, or undefined if it is empty.
|
|
2329
|
+
*
|
|
2330
|
+
* @returns {*|undefined}
|
|
2331
|
+
*/
|
|
2332
|
+
pollFirst:
|
|
2333
|
+
() => (elements.length > 0) ? elements.splice(0, 1)[0] : undefined,
|
|
2334
|
+
|
|
2335
|
+
/**
|
|
2336
|
+
* Removes and returns the last element of the set, or undefined if it is empty.
|
|
2337
|
+
*
|
|
2338
|
+
* @returns {*|undefined}
|
|
2339
|
+
*/
|
|
2340
|
+
pollLast:
|
|
2341
|
+
() => (elements.length > 0) ? elements.splice(elements.length - 1, 1)[0] : undefined,
|
|
2342
|
+
|
|
2343
|
+
/**
|
|
2344
|
+
* Adds the given value to the set. Will only do so if no equal value already exists.
|
|
2345
|
+
*
|
|
2346
|
+
* @param {*} value
|
|
2347
|
+
*/
|
|
2348
|
+
add:
|
|
2349
|
+
(value) =>
|
|
2350
|
+
{
|
|
2351
|
+
const result = binarySearch(value);
|
|
2352
|
+
if(result.found)
|
|
2353
|
+
{
|
|
2354
|
+
return;
|
|
2355
|
+
}
|
|
2356
|
+
elements.splice(result.index, 0, value);
|
|
2357
|
+
},
|
|
2358
|
+
|
|
2359
|
+
/**
|
|
2360
|
+
* Adds all the given values to the set. Will only do so if no equal value already exists.
|
|
2361
|
+
*
|
|
2362
|
+
* @param {*[]|object} values
|
|
2363
|
+
*/
|
|
2364
|
+
addAll:
|
|
2365
|
+
(values) =>
|
|
2366
|
+
{
|
|
2367
|
+
LeUtils.each(values, treeSet.add);
|
|
2368
|
+
},
|
|
2369
|
+
|
|
2370
|
+
/**
|
|
2371
|
+
* Returns an equal value that's already in the tree set, or undefined if no equal values in it exist.
|
|
2372
|
+
*
|
|
2373
|
+
* @param {*} value
|
|
2374
|
+
* @returns {*|undefined}
|
|
2375
|
+
*/
|
|
2376
|
+
getEqualValue:
|
|
2377
|
+
(value) =>
|
|
2378
|
+
{
|
|
2379
|
+
const result = binarySearch(value);
|
|
2380
|
+
if(result.found)
|
|
2381
|
+
{
|
|
2382
|
+
return result.value;
|
|
2383
|
+
}
|
|
2384
|
+
return undefined;
|
|
2385
|
+
},
|
|
2386
|
+
|
|
2387
|
+
/**
|
|
2388
|
+
* Returns an equal value that's already in the tree set. If no equal values in it exist, the given value will be added and returned.
|
|
2389
|
+
*
|
|
2390
|
+
* @param {*} value
|
|
2391
|
+
* @returns {*}
|
|
2392
|
+
*/
|
|
2393
|
+
getEqualValueOrAdd:
|
|
2394
|
+
(value) =>
|
|
2395
|
+
{
|
|
2396
|
+
const result = binarySearch(value);
|
|
2397
|
+
if(result.found)
|
|
2398
|
+
{
|
|
2399
|
+
return result.value;
|
|
2400
|
+
}
|
|
2401
|
+
elements.splice(result.index, 0, value);
|
|
2402
|
+
return value;
|
|
2403
|
+
},
|
|
2404
|
+
};
|
|
2405
|
+
return treeSet;
|
|
2406
|
+
},
|
|
2407
|
+
|
|
2408
|
+
/**
|
|
2409
|
+
* @typedef {Object} LeUtils~TransactionalValue
|
|
2410
|
+
* @property {*} value
|
|
2411
|
+
* @property {{id:string, value:*}[]} changes
|
|
2412
|
+
*/
|
|
2413
|
+
/**
|
|
2414
|
+
* Creates and returns a new TransactionalValue object.
|
|
2415
|
+
* With a TransactionalValue, you can keep track of changes to a value, and commit or cancel them.
|
|
2416
|
+
*
|
|
2417
|
+
* Multiple uncommitted changes can be made at the same time, the last change will be the one that overwrites older changes.
|
|
2418
|
+
* If that change is cancelled, the previous change will be the one that overwrites older changes.
|
|
2419
|
+
* This allows you to make multiple unconfirmed changes, and confirm or cancel each of them individually at any time.
|
|
2420
|
+
*
|
|
2421
|
+
* @param {*} [value]
|
|
2422
|
+
* @returns {LeUtils~TransactionalValue}
|
|
2423
|
+
*/
|
|
2424
|
+
createTransactionalValue:
|
|
2425
|
+
(value) =>
|
|
2426
|
+
{
|
|
2427
|
+
if(typeof value === 'undefined')
|
|
2428
|
+
{
|
|
2429
|
+
value = null;
|
|
2430
|
+
}
|
|
2431
|
+
return {value:value, changes:[]};
|
|
2432
|
+
},
|
|
2433
|
+
|
|
2434
|
+
/**
|
|
2435
|
+
* Returns true if the given value is a valid TransactionalValue, returns false if it isn't.
|
|
2436
|
+
*
|
|
2437
|
+
* @param {LeUtils~TransactionalValue} transactionalValue
|
|
2438
|
+
* @returns {boolean}
|
|
2439
|
+
*/
|
|
2440
|
+
isTransactionalValueValid:
|
|
2441
|
+
(transactionalValue) =>
|
|
2442
|
+
{
|
|
2443
|
+
return ((typeof transactionalValue === 'object') && ('value' in transactionalValue) && ('changes' in transactionalValue) && Array.isArray(transactionalValue.changes));
|
|
2444
|
+
},
|
|
2445
|
+
|
|
2446
|
+
/**
|
|
2447
|
+
* Returns true if the given value is a TransactionalValue, false otherwise.
|
|
2448
|
+
*
|
|
2449
|
+
* @param {LeUtils~TransactionalValue} transactionalValue
|
|
2450
|
+
* @returns {string}
|
|
2451
|
+
*/
|
|
2452
|
+
transactionalValueToString:
|
|
2453
|
+
(transactionalValue) =>
|
|
2454
|
+
{
|
|
2455
|
+
if(!LeUtils.isTransactionalValueValid(transactionalValue))
|
|
2456
|
+
{
|
|
2457
|
+
return transactionalValue + '';
|
|
2458
|
+
}
|
|
2459
|
+
if(transactionalValue.changes.length <= 0)
|
|
2460
|
+
{
|
|
2461
|
+
return '' + transactionalValue.value;
|
|
2462
|
+
}
|
|
2463
|
+
let valuesString = '' + transactionalValue.value;
|
|
2464
|
+
for(let i = 0; i < transactionalValue.changes.length; i++)
|
|
2465
|
+
{
|
|
2466
|
+
valuesString += ' -> ' + transactionalValue.changes[i].value;
|
|
2467
|
+
}
|
|
2468
|
+
return transactionalValue.changes[transactionalValue.changes.length - 1].value + ' (' + valuesString + ')';
|
|
2469
|
+
},
|
|
2470
|
+
|
|
2471
|
+
/**
|
|
2472
|
+
* Sets the committed value of the given TransactionalValue to the given value. Clears out the previously uncommitted changes.
|
|
2473
|
+
*
|
|
2474
|
+
* @param {LeUtils~TransactionalValue} transactionalValue
|
|
2475
|
+
* @param {*} value
|
|
2476
|
+
*/
|
|
2477
|
+
transactionSetAndCommit:
|
|
2478
|
+
(transactionalValue, value) =>
|
|
2479
|
+
{
|
|
2480
|
+
checkTransactionalValue(transactionalValue);
|
|
2481
|
+
if(typeof value === 'undefined')
|
|
2482
|
+
{
|
|
2483
|
+
value = null;
|
|
2484
|
+
}
|
|
2485
|
+
transactionalValue.value = value;
|
|
2486
|
+
transactionalValue.changes = [];
|
|
2487
|
+
},
|
|
2488
|
+
|
|
2489
|
+
/**
|
|
2490
|
+
* Sets the value of the given TransactionalValue to the given value, without yet committing it, meaning it can be committed or cancelled later.
|
|
2491
|
+
* It returns the ID of the change, which can be used to commit or cancel the change later.
|
|
2492
|
+
*
|
|
2493
|
+
* @param {LeUtils~TransactionalValue} transactionalValue
|
|
2494
|
+
* @param {*} value
|
|
2495
|
+
* @returns {string}
|
|
2496
|
+
*/
|
|
2497
|
+
transactionSetWithoutCommitting:
|
|
2498
|
+
(transactionalValue, value) =>
|
|
2499
|
+
{
|
|
2500
|
+
checkTransactionalValue(transactionalValue);
|
|
2501
|
+
if(typeof value === 'undefined')
|
|
2502
|
+
{
|
|
2503
|
+
value = null;
|
|
2504
|
+
}
|
|
2505
|
+
const id = LeUtils.uniqueId();
|
|
2506
|
+
transactionalValue.changes.push({id:id, value:value});
|
|
2507
|
+
return id;
|
|
2508
|
+
},
|
|
2509
|
+
|
|
2510
|
+
/**
|
|
2511
|
+
* Commits the change with the given ID, making it the new committed value.
|
|
2512
|
+
* Returns true if the change was found and committed, returns false if it was already overwritten by a newer committed change.
|
|
2513
|
+
*
|
|
2514
|
+
* @param {LeUtils~TransactionalValue} transactionalValue
|
|
2515
|
+
* @param {string} changeId
|
|
2516
|
+
* @returns {boolean}
|
|
2517
|
+
*/
|
|
2518
|
+
transactionCommitChange:
|
|
2519
|
+
(transactionalValue, changeId) =>
|
|
2520
|
+
{
|
|
2521
|
+
checkTransactionalValue(transactionalValue);
|
|
2522
|
+
const change = findTransactionalValueChange(transactionalValue, changeId);
|
|
2523
|
+
if(change === null)
|
|
2524
|
+
{
|
|
2525
|
+
return false;
|
|
2526
|
+
}
|
|
2527
|
+
transactionalValue.value = change.value;
|
|
2528
|
+
transactionalValue.changes.splice(0, change.index + 1);
|
|
2529
|
+
return true;
|
|
2530
|
+
},
|
|
2531
|
+
|
|
2532
|
+
/**
|
|
2533
|
+
* Cancels the change with the given ID, removing it from the uncommitted changes.
|
|
2534
|
+
* Returns true if the change was found and removed, returns false if it was already overwritten by a newer committed change.
|
|
2535
|
+
*
|
|
2536
|
+
* @param {LeUtils~TransactionalValue} transactionalValue
|
|
2537
|
+
* @param {string} changeId
|
|
2538
|
+
* @returns {boolean}
|
|
2539
|
+
*/
|
|
2540
|
+
transactionCancelChange:
|
|
2541
|
+
(transactionalValue, changeId) =>
|
|
2542
|
+
{
|
|
2543
|
+
checkTransactionalValue(transactionalValue);
|
|
2544
|
+
const change = findTransactionalValueChange(transactionalValue, changeId);
|
|
2545
|
+
if(change === null)
|
|
2546
|
+
{
|
|
2547
|
+
return false;
|
|
2548
|
+
}
|
|
2549
|
+
transactionalValue.changes.splice(change.index, 1);
|
|
2550
|
+
return true;
|
|
2551
|
+
},
|
|
2552
|
+
|
|
2553
|
+
/**
|
|
2554
|
+
* Returns true if the change was found, meaning it can still make a difference to the final committed value of this TransactionalValue.
|
|
2555
|
+
* Returns false if it was already overwritten by a newer committed change, meaning that this change can no longer make a difference to the final committed value of this TransactionalValue.
|
|
2556
|
+
*
|
|
2557
|
+
* @param {LeUtils~TransactionalValue} transactionalValue
|
|
2558
|
+
* @param {string} changeId
|
|
2559
|
+
* @returns {boolean}
|
|
2560
|
+
*/
|
|
2561
|
+
transactionIsChangeRelevant:
|
|
2562
|
+
(transactionalValue, changeId) =>
|
|
2563
|
+
{
|
|
2564
|
+
checkTransactionalValue(transactionalValue);
|
|
2565
|
+
return (findTransactionalValueChange(transactionalValue, changeId) !== null);
|
|
2566
|
+
},
|
|
2567
|
+
|
|
2568
|
+
/**
|
|
2569
|
+
* Returns the committed value of the given TransactionalValue.
|
|
2570
|
+
*
|
|
2571
|
+
* @param {LeUtils~TransactionalValue} transactionalValue
|
|
2572
|
+
* @returns {*}
|
|
2573
|
+
*/
|
|
2574
|
+
transactionGetCommittedValue:
|
|
2575
|
+
(transactionalValue) =>
|
|
2576
|
+
{
|
|
2577
|
+
checkTransactionalValue(transactionalValue);
|
|
2578
|
+
return transactionalValue.value;
|
|
2579
|
+
},
|
|
2580
|
+
|
|
2581
|
+
/**
|
|
2582
|
+
* Returns the value (including any uncommitted changes made to it) of the given TransactionalValue.
|
|
2583
|
+
*
|
|
2584
|
+
* @param {LeUtils~TransactionalValue} transactionalValue
|
|
2585
|
+
* @returns {*}
|
|
2586
|
+
*/
|
|
2587
|
+
transactionGetValue:
|
|
2588
|
+
(transactionalValue) =>
|
|
2589
|
+
{
|
|
2590
|
+
checkTransactionalValue(transactionalValue);
|
|
2591
|
+
if(transactionalValue.changes.length <= 0)
|
|
2592
|
+
{
|
|
2593
|
+
return transactionalValue.value;
|
|
2594
|
+
}
|
|
2595
|
+
return transactionalValue.changes[transactionalValue.changes.length - 1].value;
|
|
2596
|
+
},
|
|
2064
2597
|
};
|
package/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import {LeUtils} from './LeUtils.js';
|
|
2
|
-
import {
|
|
2
|
+
import {ISSET, IS_ARRAY, ARRAY, IS_OBJECT, OBJECT, STRING, STRING_ANY, INT, INT_ANY, FLOAT, FLOAT_ANY, INT_LAX, INT_LAX_ANY, FLOAT_LAX, FLOAT_LAX_ANY} from './LeTypes.js';
|
|
3
3
|
|
|
4
|
-
export {LeUtils,
|
|
4
|
+
export {LeUtils, ISSET, IS_ARRAY, ARRAY, IS_OBJECT, OBJECT, STRING, STRING_ANY, INT, INT_ANY, FLOAT, FLOAT_ANY, INT_LAX, INT_LAX_ANY, FLOAT_LAX, FLOAT_LAX_ANY};
|