mirror of
https://github.com/koalyptus/TableFilter.git
synced 2024-06-27 09:50:24 +02:00
Compare commits
781 commits
Author | SHA1 | Date | |
---|---|---|---|
|
7afe45f1e6 | ||
|
6e01e45dfb | ||
|
12c30629af | ||
|
3e763efac9 | ||
|
825b915ae8 | ||
|
8e48bf2943 | ||
|
be7a5e585f | ||
|
c44bef22a2 | ||
|
6dcebbf67e | ||
|
44cb6f9124 | ||
|
571c31e8da | ||
|
8633891fdb | ||
|
8eddc6f35c | ||
|
577fb0b90a | ||
|
88a5bfe425 | ||
|
cac2900444 | ||
|
5dad4dae8e | ||
|
134851525c | ||
|
9a66748bb8 | ||
|
c52004421f | ||
|
f53b392c59 | ||
|
c496b0916d | ||
|
25b89b19e7 | ||
|
8b4a05be02 | ||
|
1c4961a25b | ||
|
40daf54768 | ||
|
c43debc7ac | ||
|
3ac2603e47 | ||
|
185c119342 | ||
|
80c9b3d734 | ||
|
e8605e5e19 | ||
|
bd95afb3eb | ||
|
c16f885951 | ||
|
6be9ad491f | ||
|
447a3119aa | ||
|
2025aa4010 | ||
|
bdc03755e8 | ||
|
2dceed888e | ||
|
982769a020 | ||
|
4318826ead | ||
|
66b8fa9d94 | ||
|
79cea3e27f | ||
|
7af493da27 | ||
|
90c3b7f937 | ||
|
85dce5847a | ||
|
65863b635a | ||
|
3c001f52e2 | ||
|
e3957977b6 | ||
|
8923c4db94 | ||
|
c7d1a25467 | ||
|
ebdd817199 | ||
|
27365e25d4 | ||
|
2e960867ab | ||
|
3d35d53005 | ||
|
02bc5e3ae1 | ||
|
09c1f8ff52 | ||
|
6b339f7bd7 | ||
|
a1efe26a85 | ||
|
64e6c6597f | ||
|
9363a7a661 | ||
|
41e220efa9 | ||
|
64d3808a2b | ||
|
eb15788965 | ||
|
fede2f6e86 | ||
|
9738c8ed91 | ||
|
b285d01b54 | ||
|
37eed72f2c | ||
|
71103cd04b | ||
|
42a347550b | ||
|
bed04b5b9b | ||
|
43fc68df31 | ||
|
d116525f73 | ||
|
d7ff36514d | ||
|
0d0abf3206 | ||
|
4cd004e423 | ||
|
459829a214 | ||
|
b8c0c1bc3f | ||
|
5686e8a470 | ||
|
b04d4f55ed | ||
|
3004963058 | ||
|
3454187be6 | ||
|
1dac7736b1 | ||
|
2c7ad88346 | ||
|
6e41c4a8c6 | ||
|
859f6b1eeb | ||
|
7204c4b546 | ||
|
f29b59fdbd | ||
|
6cc887e806 | ||
|
f7ad9741ca | ||
|
323a80d1d7 | ||
|
fc46f0b4ae | ||
|
0471570985 | ||
|
20243b641f | ||
|
99722cbdb0 | ||
|
64cc6825c5 | ||
|
bcb541fcad | ||
|
1c3c1bbb0a | ||
|
bba009c505 | ||
|
48659ec1d5 | ||
|
1d32dcea7d | ||
|
0e1c617b06 | ||
|
5c705fe591 | ||
|
3c501e3aef | ||
|
78ae09c861 | ||
|
2e1af5efb3 | ||
|
da270df5d6 | ||
|
8a8419bf02 | ||
|
a6c24c7885 | ||
|
ed2fef999a | ||
|
47c66d71bb | ||
|
f99f850c4d | ||
|
10c06b5100 | ||
|
1cc810c341 | ||
|
c707978e19 | ||
|
32b541239e | ||
|
2963962250 | ||
|
bbec44cc15 | ||
|
352a700fb2 | ||
|
fae4ec9e07 | ||
|
226f18a6f6 | ||
|
1d58191127 | ||
|
1559c74fd9 | ||
|
2cd30b1bfb | ||
|
cd5e5589a4 | ||
|
5499093810 | ||
|
df54ddda33 | ||
|
80ebc0aa8c | ||
|
a5fa336a08 | ||
|
36d4f85f6c | ||
|
e886a6f1a8 | ||
|
7204746e5f | ||
|
ecd33d0631 | ||
|
f97394fc32 | ||
|
eef0ab3bbd | ||
|
c48b48f924 | ||
|
d699d02914 | ||
|
09b3f7875d | ||
|
9c54974338 | ||
|
b89a52fb77 | ||
|
ef46fd4295 | ||
|
8d8c8ae74c | ||
|
fafa983dac | ||
|
a19c5a106f | ||
|
1e391233dc | ||
|
aade342976 | ||
|
0443442916 | ||
|
ed4979331c | ||
|
0e1a1ff3d1 | ||
|
e71b3a5c93 | ||
|
a22b009c57 | ||
|
f6a9a058c9 | ||
|
f7c231b99f | ||
|
6f4e5a91ab | ||
|
f405a45d79 | ||
|
fbe43b1db4 | ||
|
e13201733d | ||
|
002c46297e | ||
|
017337b2e2 | ||
|
51679ad61b | ||
|
bc34e8b187 | ||
|
58e90cb766 | ||
|
3243fad4da | ||
|
ea2a8be8b6 | ||
|
5e1fe901b7 | ||
|
c001e90617 | ||
|
a446c0afc0 | ||
|
ff88f6c7d7 | ||
|
d46265eb57 | ||
|
3057b1949c | ||
|
bca2cee175 | ||
|
077eb3fe87 | ||
|
90e4367951 | ||
|
589b356bc6 | ||
|
7664e054e5 | ||
|
2dcad20d0c | ||
|
86369ff116 | ||
|
f1bdd8997f | ||
|
eefbf3fe41 | ||
|
0b455e2ec4 | ||
|
de6745821f | ||
|
f79234ea7e | ||
|
8bcf731d3c | ||
|
5247493035 | ||
|
69a1fd3ee9 | ||
|
9c80252935 | ||
|
c22f9981e6 | ||
|
04012e5a97 | ||
|
02997076d4 | ||
|
9117097750 | ||
|
e3f9851848 | ||
|
f1febe1688 | ||
|
cf9a566e92 | ||
|
34e8b4099b | ||
|
495b64ecf0 | ||
|
0a69a99dc5 | ||
|
2d9671e10d | ||
|
0f380c03da | ||
|
df85babf34 | ||
|
131280c1a3 | ||
|
372473227c | ||
|
cb7fc0d4fa | ||
|
c3b5ef529c | ||
|
89b1814c2d | ||
|
9a1202c0b5 | ||
|
95475b022d | ||
|
8b1d3a6e23 | ||
|
6b2fbd1eef | ||
|
8d1dc88f6a | ||
|
34c56e5765 | ||
|
87ee312fc5 | ||
|
df0221d5e7 | ||
|
528d587a80 | ||
|
b8bdff83aa | ||
|
d40244b7e5 | ||
|
ec7799b57b | ||
|
fa28abbee8 | ||
|
e06dfbdc35 | ||
|
64f56c22a4 | ||
|
ecfa6c64ad | ||
|
37f6db7025 | ||
|
bfa440b265 | ||
|
bf9cbd0a69 | ||
|
967ae801b4 | ||
|
066c5fee56 | ||
|
807c191a01 | ||
|
9382a07c7b | ||
|
8b09b6feab | ||
|
d733766621 | ||
|
ceba24d727 | ||
|
c25cae1679 | ||
|
04342ac316 | ||
|
0ad57767f8 | ||
|
fd56dabea8 | ||
|
0b11de4f90 | ||
|
bbd0ce06ce | ||
|
500344c64a | ||
|
5845f8c52d | ||
|
d232f64fa5 | ||
|
53a77d1b97 | ||
|
44ce01be4b | ||
|
1f17364a00 | ||
|
a437dad841 | ||
|
99b34c07b4 | ||
|
ff977281c7 | ||
|
bf667cdd6f | ||
|
94d6d59593 | ||
|
1fc5fa5f8a | ||
|
34d35a3495 | ||
|
9750b07e06 | ||
|
bfe6b6dc2c | ||
|
67b1d4b65e | ||
|
c7482bec2d | ||
|
b38bc836ee | ||
|
79d06ff09e | ||
|
bd6afe484c | ||
|
6560392771 | ||
|
599717ae14 | ||
|
e96273e95f | ||
|
dcc0a43258 | ||
|
31ece0ff81 | ||
|
db0c95e197 | ||
|
2945c27ae9 | ||
|
786bb519b0 | ||
|
db1ecaec42 | ||
|
3f74756d58 | ||
|
dca79c8391 | ||
|
dd6de7f219 | ||
|
4e222fd98c | ||
|
e45c7ce863 | ||
|
b45815cfc7 | ||
|
481c7c3970 | ||
|
6b47928c92 | ||
|
259a88d0c5 | ||
|
91ec79d226 | ||
|
6630a87263 | ||
|
4d4d1f4212 | ||
|
7631b51f3d | ||
|
5bde707a0c | ||
|
2cea817247 | ||
|
68acd1fcb7 | ||
|
4d424d1d7e | ||
|
50fda2a900 | ||
|
335f97a9de | ||
|
a7e0f235a3 | ||
|
d6a79e14fc | ||
|
7e780f3463 | ||
|
439f183d95 | ||
|
10b80612fe | ||
|
72327b84cc | ||
|
ba5323ab3b | ||
|
a9c0fd9c2f | ||
|
e6049975ee | ||
|
62a55c8d95 | ||
|
5d4def11fc | ||
|
13eb677b8e | ||
|
d48bbeaab5 | ||
|
6fec4947c4 | ||
|
d3634bce5f | ||
|
6813debb6e | ||
|
b14667a345 | ||
|
2f825a25b4 | ||
|
cca223c4d4 | ||
|
09243a9bdb | ||
|
24e0f3d184 | ||
|
d70cf23624 | ||
|
2d963e782f | ||
|
c100f0f63f | ||
|
875fdc2603 | ||
|
4bdf873ec8 | ||
|
d1875f19f2 | ||
|
5254983778 | ||
|
7e13d59d0f | ||
|
a66402e139 | ||
|
8cb8f74fa3 | ||
|
c5775ae8aa | ||
|
a10d3a2830 | ||
|
2e089a1823 | ||
|
3231da9760 | ||
|
7533499c40 | ||
|
80cf351eab | ||
|
d790156373 | ||
|
70d791f41c | ||
|
f1f28b51cb | ||
|
8a94f2ffd2 | ||
|
a0f9f28397 | ||
|
71292db999 | ||
|
42a40a295b | ||
|
7a90cb5b13 | ||
|
7eecd95122 | ||
|
a45217bc9f | ||
|
d14a0a359a | ||
|
e09bab000b | ||
|
efffa40248 | ||
|
50afb94340 | ||
|
d35ea7cb26 | ||
|
52705e56f7 | ||
|
b34e5696f3 | ||
|
606cc00393 | ||
|
c728209c92 | ||
|
2e3bdda8bc | ||
|
7bc7b16cfc | ||
|
c5bc7cbb33 | ||
|
ec6d0779a1 | ||
|
bcbfe5251f | ||
|
453ff1c59c | ||
|
948055da09 | ||
|
f534a8b23f | ||
|
6c23ae883f | ||
|
55e4d6b511 | ||
|
2d5f7401f9 | ||
|
00143a686b | ||
|
46f7028580 | ||
|
313336ab5f | ||
|
89851eae3b | ||
|
e49538c442 | ||
|
cb0aa73a6d | ||
|
9b89b78f38 | ||
|
1a32ef216b | ||
|
bcf7189bbc | ||
|
9a55c86e5f | ||
|
c710fa3585 | ||
|
a5164f4ba5 | ||
|
0babe0249e | ||
|
ca4f0f2afa | ||
|
00150bc9e1 | ||
|
46b21b4a20 | ||
|
89b0cf843a | ||
|
946f600260 | ||
|
0cd8fb2aa3 | ||
|
ad8c86c599 | ||
|
bf1bdc5a0e | ||
|
ed01c6e201 | ||
|
b4905f7703 | ||
|
2cc28e8072 | ||
|
521d02c374 | ||
|
fe51fdecb8 | ||
|
bfa23c3b6e | ||
|
2abd81906b | ||
|
f1e046e331 | ||
|
ea8ca2a125 | ||
|
6bc6c8a8eb | ||
|
c0520dd4bb | ||
|
3d7945b09c | ||
|
84c964bf13 | ||
|
c7d6de72f7 | ||
|
81f31a3106 | ||
|
3995dee394 | ||
|
7540169fcd | ||
|
4bff89b70c | ||
|
c8df8992b3 | ||
|
4889b29cda | ||
|
b3101a8871 | ||
|
bf2f2bd747 | ||
|
b08b517fa7 | ||
|
f2c5edbfb8 | ||
|
ca6ced712a | ||
|
0d95699fa6 | ||
|
4378141d7d | ||
|
0631fd2ef7 | ||
|
7cbb38d9ba | ||
|
edd2494899 | ||
|
49eb4b7bd6 | ||
|
5d4627277a | ||
|
907ccd5e4a | ||
|
c26e6d3c4b | ||
|
e1106f23a8 | ||
|
7909cde78b | ||
|
bc416e0e39 | ||
|
934ba4add0 | ||
|
73fc78e9e3 | ||
|
c1000b7684 | ||
|
a34009f1e9 | ||
|
51e27c4a2f | ||
|
2fee4d95f2 | ||
|
5b6919ba39 | ||
|
974bb3cc77 | ||
|
1a1560d636 | ||
|
2d3f67d504 | ||
|
81c593382a | ||
|
62cab3ac2c | ||
|
4ac92a3e73 | ||
|
da8977433d | ||
|
cde2e8a326 | ||
|
7b03e23f3c | ||
|
dc3d40b12c | ||
|
48674c3b31 | ||
|
a92acfa615 | ||
|
be1bdf72cd | ||
|
b6d9bddc6f | ||
|
025717f61c | ||
|
e09d30c2cd | ||
|
39bbe6a19a | ||
|
2f7b650f5b | ||
|
85092bbd1c | ||
|
3bed943a42 | ||
|
2452a0bd9e | ||
|
98aca44cb9 | ||
|
33ed3cc194 | ||
|
2da8a56659 | ||
|
71d5cd7a49 | ||
|
05c2d6b666 | ||
|
50f4a0014b | ||
|
07eebbd528 | ||
|
9ccc4dbfd4 | ||
|
9d184df49a | ||
|
d664ebb780 | ||
|
0226300af8 | ||
|
1e8e4a6467 | ||
|
0ec96ed520 | ||
|
11d01b1661 | ||
|
2d0219b54d | ||
|
317d795974 | ||
|
f2f853c517 | ||
|
9468602f3d | ||
|
cc0932f5f7 | ||
|
f97ff3a52d | ||
|
8575d0ea68 | ||
|
d274876976 | ||
|
a9737da2f6 | ||
|
62964c2478 | ||
|
71e7012ba0 | ||
|
4a3fbbb736 | ||
|
ee128f9d80 | ||
|
9b29d1632e | ||
|
1946d75125 | ||
|
83ff0aab79 | ||
|
8dbc307a39 | ||
|
c7eefc8ddc | ||
|
0e2d17714d | ||
|
650959237b | ||
|
4a10876a96 | ||
|
d5ef7afa1e | ||
|
4cf9a4081d | ||
|
c1e26349ef | ||
|
16b2997a71 | ||
|
ab273644e5 | ||
|
731909a267 | ||
|
7f75e23b1b | ||
|
55eadd72eb | ||
|
4855c9064b | ||
|
032bdd53b0 | ||
|
f73aa02733 | ||
|
029f2c35e8 | ||
|
52a514088b | ||
|
c7756d8d58 | ||
|
054423f10d | ||
|
cccc4b71cf | ||
|
db2bb7de18 | ||
|
740cce0551 | ||
|
f6a93f7f00 | ||
|
b6db436bca | ||
|
158c8835f9 | ||
|
7a2bc50a56 | ||
|
74cea36219 | ||
|
2deeb5d57a | ||
|
619c272469 | ||
|
7862bc68d0 | ||
|
e2e8331a08 | ||
|
3134ee804b | ||
|
1c930a0184 | ||
|
51f188e63f | ||
|
2ca11374a0 | ||
|
79367df924 | ||
|
fe384896d5 | ||
|
f8c5d081d4 | ||
|
3ff774d78f | ||
|
33ae62cab7 | ||
|
8be5990a02 | ||
|
88d31090b4 | ||
|
fbfa2fdf96 | ||
|
f447199905 | ||
|
be67034e02 | ||
|
a01c914f0a | ||
|
c288fe44ce | ||
|
dc05239d57 | ||
|
42fb561866 | ||
|
95c8206eb7 | ||
|
26beced5c7 | ||
|
cf7a53354d | ||
|
653b1ce006 | ||
|
d69f60aced | ||
|
949f21f446 | ||
|
722c420dc6 | ||
|
590dd8316c | ||
|
376102c801 | ||
|
a243c96dd3 | ||
|
631f6bdb5c | ||
|
fc089f1b73 | ||
|
dfa93b378b | ||
|
0affe2c187 | ||
|
8231252f34 | ||
|
75faca6e8d | ||
|
4a6ae393a5 | ||
|
0e669bcc45 | ||
|
08fb37b982 | ||
|
bde954e570 | ||
|
78f6df704b | ||
|
7cf9be1342 | ||
|
86a650ff6d | ||
|
13adb6fb3a | ||
|
f2d54839c3 | ||
|
9abc9802bd | ||
|
82a03d428c | ||
|
0b5160b45d | ||
|
fca1fcf23c | ||
|
e311aa36f1 | ||
|
9b54c10bc6 | ||
|
eb62703e50 | ||
|
81062452e2 | ||
|
6e72912c90 | ||
|
52999f000e | ||
|
6999b0c7f9 | ||
|
e205a6b15a | ||
|
fbeb52bda2 | ||
|
465b216e01 | ||
|
ff622ea585 | ||
|
6a0179681b | ||
|
68adc86cbc | ||
|
e661005ff8 | ||
|
a861cff760 | ||
|
12e4052a9f | ||
|
e9441fe1d5 | ||
|
175a23934f | ||
|
a757bd02fa | ||
|
b03ec21a28 | ||
|
5f66df7e6a | ||
|
5a10841f84 | ||
|
2ef37ed58d | ||
|
828a42f938 | ||
|
4428f7b48b | ||
|
e855fc5bbd | ||
|
a7f0f442d8 | ||
|
2a424e7f6f | ||
|
50f537fbfc | ||
|
7ba78c94ae | ||
|
763fbcc86e | ||
|
3abca0ef22 | ||
|
7888a8ee24 | ||
|
abec798b27 | ||
|
eb9ac51b5a | ||
|
d86601e1a1 | ||
|
fd48f8c3ec | ||
|
fa28d6ce17 | ||
|
4250fda098 | ||
|
4f9e3dee01 | ||
|
e05f0b2c73 | ||
|
7c7a5fc1b7 | ||
|
a54abc6ea1 | ||
|
e4ed4d5567 | ||
|
29c4c107bc | ||
|
0b242aadc7 | ||
|
44a39e7e1f | ||
|
e82640c7da | ||
|
f89bf8859b | ||
|
6b5c432ce7 | ||
|
409a3bc6eb | ||
|
d406a09a9e | ||
|
36b045c6d2 | ||
|
59902adcf5 | ||
|
41842eede4 | ||
|
62c7cb1918 | ||
|
d23f6f4cc8 | ||
|
80f1fc3371 | ||
|
ea87137a82 | ||
|
aa8df36e28 | ||
|
0947a87d6c | ||
|
72c47a9b0d | ||
|
f0c9a800a5 | ||
|
ad5405e699 | ||
|
cc5c8b9ed5 | ||
|
04d8fd3d14 | ||
|
fb0a6a0a01 | ||
|
78059d1bf8 | ||
|
3352765fed | ||
|
f96166be48 | ||
|
3a878c9e90 | ||
|
7b8c3c7412 | ||
|
9f6751533e | ||
|
82e9b27598 | ||
|
237fff1351 | ||
|
e00c560c80 | ||
|
407e772fdb | ||
|
645437b5e3 | ||
|
7f6221cd8e | ||
|
d9c770855a | ||
|
70a7d6540c | ||
|
acf6678619 | ||
|
f2242c4e57 | ||
|
8fb7c76e2d | ||
|
72e78fd4bc | ||
|
2f1e065571 | ||
|
761c3730ed | ||
|
cdf7b926ba | ||
|
d3addb09c4 | ||
|
471203b0a6 | ||
|
7cac5b105e | ||
|
e8c3f27d93 | ||
|
97d2ed0d64 | ||
|
7278aab649 | ||
|
e33e634d0d | ||
|
92af5d8842 | ||
|
140f949190 | ||
|
c5d043f85b | ||
|
06cea02484 | ||
|
287b7413e3 | ||
|
3c330ac4f0 | ||
|
51bc126c8d | ||
|
edcd166cd8 | ||
|
aaead0e5ca | ||
|
990ef45e45 | ||
|
9ae607d802 | ||
|
3c07d8dcc4 | ||
|
bb8b8a9d50 | ||
|
08303e93ca | ||
|
01bdad6368 | ||
|
8145ef116f | ||
|
ab9ff96684 | ||
|
9858ac84c1 | ||
|
c6b876d7f9 | ||
|
05f1c62ad0 | ||
|
bf631efd24 | ||
|
f86e73b374 | ||
|
7cd85bbd34 | ||
|
38424bfdca | ||
|
9dde61e7a0 | ||
|
5fc1c78d1b | ||
|
2cbfc0b1ec | ||
|
5043378c2c | ||
|
92e743a67e | ||
|
9262e7fd13 | ||
|
5adfa8a1be | ||
|
0d64d5aa00 | ||
|
11e15f0482 | ||
|
07355d7442 | ||
|
e8392b8fa5 | ||
|
bfcf221a91 | ||
|
c29cbda581 | ||
|
5294a31e30 | ||
|
ed7ead95d5 | ||
|
aee6063410 | ||
|
45e78777e9 | ||
|
1de6a6288c | ||
|
4b7af32eb1 | ||
|
955c49a2c1 | ||
|
eeb5afe97b | ||
|
f5d818c91a | ||
|
0a38e422b8 | ||
|
f059faecbc | ||
|
195918f088 | ||
|
022e52e31c | ||
|
b249399b1d | ||
|
132d46fed5 | ||
|
49e16a3631 | ||
|
06c3b3f025 | ||
|
39e4340dee | ||
|
cb3a633807 | ||
|
b0bc11007f | ||
|
7781bcfe4b | ||
|
308ea2ce25 | ||
|
d66c7906c0 | ||
|
a0bf340378 | ||
|
1b8bb8a9ea | ||
|
25101b278a | ||
|
5c4c8c0fe9 | ||
|
7a861eabee | ||
|
b8f549a432 | ||
|
5a82498d60 | ||
|
890d004c3c | ||
|
c7c20cdacf | ||
|
3f2bc41176 | ||
|
70779f192c | ||
|
6fc121a314 | ||
|
29960cada8 | ||
|
6dc1c9e53b | ||
|
5b7b1527d5 | ||
|
6bfccca291 | ||
|
39c8933a3f | ||
|
5411843f9f | ||
|
88b0dc5215 | ||
|
2a8571d940 | ||
|
9882a99417 | ||
|
2f8fb874d8 | ||
|
5f229311f0 | ||
|
4a88f6cc56 | ||
|
151ec256fa | ||
|
37c90ed12b | ||
|
c21863c71a | ||
|
508fc8fd1c | ||
|
9f6b3160fc | ||
|
650de1d7e3 | ||
|
68ebfcd537 | ||
|
4cc870b1bb | ||
|
a15fb5719e | ||
|
6926ef3b9a | ||
|
76a61d5a01 | ||
|
f24c5da431 | ||
|
b9ab9582a8 | ||
|
f9426c9ed0 | ||
|
067cce1d7b | ||
|
b03445ea46 | ||
|
9d7f49dda9 | ||
|
dfd78be5b3 | ||
|
f0e2ec6a8a | ||
|
06ed30de3b | ||
|
5cfc6c573b | ||
|
ec940d428a | ||
|
4f593cb2d3 | ||
|
611fc1ba24 | ||
|
4f7249bfa4 | ||
|
8f8e468278 | ||
|
23916b753a | ||
|
e8ba629217 | ||
|
ef2c2917db | ||
|
6daed0f4a8 | ||
|
8624920e2c | ||
|
e303cccd2a | ||
|
88c4f2d8d0 | ||
|
41feee7a22 | ||
|
c0101f45b5 | ||
|
c49eb2e50f | ||
|
238af84a97 | ||
|
87d166c4a4 | ||
|
d05a3c4dc0 | ||
|
a2ccc2668a | ||
|
e93df29cc0 | ||
|
aafe5da783 | ||
|
35174fb849 | ||
|
1905d89a75 | ||
|
d566d6a315 | ||
|
08529d0d59 | ||
|
ce946b9aed | ||
|
f7aa5cd65c | ||
|
d9c0fd6d0b | ||
|
41db8d67df | ||
|
7a5985ba8f | ||
|
574e2c3761 | ||
|
90b5e3cdca | ||
|
b062d44b87 | ||
|
ca1c801d64 | ||
|
c3a6c61739 | ||
|
5a496f228a |
14
.esdoc.json
Normal file
14
.esdoc.json
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"source": "src",
|
||||||
|
"destination": "docs/docs",
|
||||||
|
"plugins": [{
|
||||||
|
"name": "esdoc-standard-plugin",
|
||||||
|
"option": {
|
||||||
|
"lint": {"enable": false},
|
||||||
|
"accessor": {
|
||||||
|
"access": ["public", "protected"],
|
||||||
|
"autoPrivate": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
11
.eslintrc
11
.eslintrc
|
@ -1,18 +1,20 @@
|
||||||
{
|
{
|
||||||
"parser": "babel-eslint",
|
"parser": "babel-eslint",
|
||||||
"parserOptions": {
|
"parserOptions": {
|
||||||
"sourceType": "module"
|
"sourceType": "module",
|
||||||
|
"ecmaFeatures": { "modules": true }
|
||||||
},
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
"max-len": [2, 80, 2, {"ignoreUrls": true}],
|
"max-len": [2, 80, 2, {"ignoreUrls": true}],
|
||||||
"indent": [2, 4, {"SwitchCase": 1}],
|
"indent": [2, 4, {"SwitchCase": 1}],
|
||||||
|
"semi": ["error", "always"],
|
||||||
"no-trailing-spaces": 2,
|
"no-trailing-spaces": 2,
|
||||||
"no-multi-spaces": 2,
|
"no-multi-spaces": 2,
|
||||||
"array-bracket-spacing": 2,
|
"array-bracket-spacing": 2,
|
||||||
"keyword-spacing": ["error", { "after": true, "before": true }],
|
"keyword-spacing": ["error", { "after": true, "before": true }],
|
||||||
"max-depth": [2, 7],
|
"max-depth": [2, 7],
|
||||||
"max-statements": [2, 144],
|
"max-statements": [2, 133],
|
||||||
"complexity": [2, 78],
|
"complexity": [2, 45],
|
||||||
"no-unused-vars": 2,
|
"no-unused-vars": 2,
|
||||||
"no-eval": 2,
|
"no-eval": 2,
|
||||||
"no-underscore-dangle": 0,
|
"no-underscore-dangle": 0,
|
||||||
|
@ -24,9 +26,6 @@
|
||||||
"new-cap": 2,
|
"new-cap": 2,
|
||||||
"radix": [2, "always"]
|
"radix": [2, "always"]
|
||||||
},
|
},
|
||||||
"ecmaFeatures": {
|
|
||||||
"modules": true
|
|
||||||
},
|
|
||||||
"env": {
|
"env": {
|
||||||
"es6": true,
|
"es6": true,
|
||||||
"browser": true,
|
"browser": true,
|
||||||
|
|
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: bug
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**Reproduction steps:**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. [First Step]
|
||||||
|
2. [Second Step]
|
||||||
|
3. [Other Steps...]
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Observed behavior:**
|
||||||
|
A clear and concise description of observed behavior.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
![Screenshots and GIFs which follow reproduction steps to demonstrate the problem](url)
|
||||||
|
|
||||||
|
**TableFilter version:** [Enter TableFilter version here]
|
||||||
|
**Browser and version:** [Enter Browser name and version here]
|
||||||
|
**OS and version:** [Enter OS name and version here]
|
||||||
|
**Device:** [e.g. iPhone6]
|
||||||
|
|
||||||
|
**Additional information/context:**
|
||||||
|
Add any other context about the problem here.
|
||||||
|
|
||||||
|
* Problem started happening recently, didn't happen in an older version of TableFilter: [Yes/No] if yes [version here]
|
||||||
|
* Problem can be reliably reproduced, doesn't happen randomly: [Yes/No]
|
36
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
36
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Enhancement/feature description**
|
||||||
|
[A clear and concise description of what the problem is. Ex. I'm always frustrated when ...]
|
||||||
|
|
||||||
|
**Steps which explain the enhancement/feature**
|
||||||
|
1. [First Step]
|
||||||
|
2. [Second Step]
|
||||||
|
3. [Other Steps...]
|
||||||
|
|
||||||
|
**Current and suggested behavior**
|
||||||
|
[Describe current and suggested behavior here]
|
||||||
|
|
||||||
|
**Why would the enhancement be useful to most users**
|
||||||
|
[Explain why the enhancement would be useful to most users]
|
||||||
|
|
||||||
|
**Screenshots and GIFs**
|
||||||
|
![Screenshots and GIFs which demonstrate the steps or part of TableFilter the enhancement suggestion is related to](url)
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
[Add any other context or screenshots about the feature request here.]
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**TableFilter Version:** [Enter TableFilter version here]
|
||||||
|
**Browser and version:** [Enter Browser name and version here]
|
||||||
|
**OS and version:** [Enter OS name and version here]
|
||||||
|
**Device:** [e.g. iPhone6]
|
17
.github/ISSUE_TEMPLATE/support.md
vendored
Normal file
17
.github/ISSUE_TEMPLATE/support.md
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
---
|
||||||
|
name: Support
|
||||||
|
about: I need support with TableFilter
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
For usage and support questions, please check out resources below, you might find an answer:
|
||||||
|
|
||||||
|
- https://www.tablefilter.com/
|
||||||
|
- https://www.tablefilter.com/docs/
|
||||||
|
- https://www.tablefilter.com/examples.html
|
||||||
|
- https://github.com/koalyptus/TableFilter/wiki/
|
||||||
|
- https://github.com/koalyptus/TableFilter/issues?q=is%3Aissue+is%3Aclosed
|
||||||
|
- https://codepen.io/koalyptus/pens/public/
|
49
.travis.yml
49
.travis.yml
|
@ -1,16 +1,53 @@
|
||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
node_js:
|
||||||
- '6.3.0'
|
- '8.9.4'
|
||||||
before_script:
|
before_script:
|
||||||
- npm install grunt-cli -g
|
- npm install grunt-cli -g
|
||||||
- npm install codecov -g
|
- npm install codecov -g
|
||||||
script:
|
script:
|
||||||
- npm test
|
- npm test
|
||||||
- npm run codecov
|
- npm run codecov
|
||||||
- npm run deploy
|
- npm run build:all
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
|
- /^greenkeeper/.*$/
|
||||||
|
before_deploy:
|
||||||
|
- git config --global user.email "maxgug@hotmail.com"
|
||||||
|
- git config --global user.name "koalyptus"
|
||||||
|
- export GIT_TAG=$(git describe --tags --abbrev=0)
|
||||||
|
- echo -n $GIT_TAG
|
||||||
|
- export NEW_GIT_TAG=$(node -p -e "require('./package.json').version")
|
||||||
|
- echo -n $NEW_GIT_TAG
|
||||||
|
- |
|
||||||
|
if [ $GIT_TAG != $NEW_GIT_TAG ]; then
|
||||||
|
git tag $NEW_GIT_TAG -am "Generated tag from TravisCI build $TRAVIS_BUILD_NUMBER"
|
||||||
|
fi
|
||||||
|
deploy:
|
||||||
|
- provider: releases
|
||||||
|
on:
|
||||||
|
branch: master
|
||||||
|
api_key: $GITHUB_OAUTH_ACCESS_TOKEN
|
||||||
|
skip_cleanup: true
|
||||||
|
name: $NEW_GIT_TAG
|
||||||
|
- provider: s3
|
||||||
|
on:
|
||||||
|
branch: master
|
||||||
|
access_key_id: $AWS_ACCESS_KEY_ID
|
||||||
|
secret_access_key: $AWS_SECRET_ACCESS_KEY
|
||||||
|
region: $AWS_DEFAULT_REGION
|
||||||
|
bucket: www.tablefilter.com
|
||||||
|
skip_cleanup: true
|
||||||
|
local_dir: dist
|
||||||
|
- provider: s3
|
||||||
|
on:
|
||||||
|
branch: master
|
||||||
|
access_key_id: $AWS_ACCESS_KEY_ID
|
||||||
|
secret_access_key: $AWS_SECRET_ACCESS_KEY
|
||||||
|
region: $AWS_DEFAULT_REGION
|
||||||
|
bucket: www.tablefilter.com
|
||||||
|
skip_cleanup: true
|
||||||
|
local_dir: docs
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
- secure: A1G8GvJkV0rjy7XCTVdOpTHy3xaoSZZAbMWhI+ikrqBqd8mRz+sB71FhRusouTcYdsT5VfF9Io2doS8LKAeP0TNC34Pp0uvjtsvarzn8a/oNEOuqR3Ub0ws2bmbZIZc+wOpgErKOj1H1QSJAUpd6ZjIuEAbOVXlhGBJz3zUCmcpRDh32CpFKC62oFWeGlvttxPciLLzBfKgkVKEGhPtdGP/xCHL1MCQptYVHZiXwWsaIQ5wHFO6KCVlRrPgdfOL+Yce3mT02iXH6ZjW6U6zA6vYQVQZVD873AkU5RmirYblW+jW1wdvu4UXI71lSH6Z3uXRVnrw1b0TsLVTjP9ZUbCtkTHtLbxYzeDjEukxKoCjpAppIhOtaNIxrdA8oKJAabQYp5X+QK6lkosy0zdT5u2B1+g8unZhsf0y//7lgLUe04iQ7sc1Q6AHiiEGtByaXg4BHNW53bUfKgNnbV4+IbXf8rz5wWOxL2/yWAU/GoiszjqRQfajAXCpSf6SyMjXjhhvQdeFn+Cz6FwdtaxH+tOIY0Hq9Gqy1xrLIkv/httd3O+AbhLrU1c/M0MwlFQue7GeJb7ZyF3KsK7bXvoz2dEqvzHd98NZXiQEqFXCIs77uVh4eZMoYrbEyrkOAgkUZNQYhHh9fuvfynJ/zgUvyA0v3GUvBebq3ybYKD/vqX7s=
|
- secure: A1G8GvJkV0rjy7XCTVdOpTHy3xaoSZZAbMWhI+ikrqBqd8mRz+sB71FhRusouTcYdsT5VfF9Io2doS8LKAeP0TNC34Pp0uvjtsvarzn8a/oNEOuqR3Ub0ws2bmbZIZc+wOpgErKOj1H1QSJAUpd6ZjIuEAbOVXlhGBJz3zUCmcpRDh32CpFKC62oFWeGlvttxPciLLzBfKgkVKEGhPtdGP/xCHL1MCQptYVHZiXwWsaIQ5wHFO6KCVlRrPgdfOL+Yce3mT02iXH6ZjW6U6zA6vYQVQZVD873AkU5RmirYblW+jW1wdvu4UXI71lSH6Z3uXRVnrw1b0TsLVTjP9ZUbCtkTHtLbxYzeDjEukxKoCjpAppIhOtaNIxrdA8oKJAabQYp5X+QK6lkosy0zdT5u2B1+g8unZhsf0y//7lgLUe04iQ7sc1Q6AHiiEGtByaXg4BHNW53bUfKgNnbV4+IbXf8rz5wWOxL2/yWAU/GoiszjqRQfajAXCpSf6SyMjXjhhvQdeFn+Cz6FwdtaxH+tOIY0Hq9Gqy1xrLIkv/httd3O+AbhLrU1c/M0MwlFQue7GeJb7ZyF3KsK7bXvoz2dEqvzHd98NZXiQEqFXCIs77uVh4eZMoYrbEyrkOAgkUZNQYhHh9fuvfynJ/zgUvyA0v3GUvBebq3ybYKD/vqX7s=
|
||||||
|
|
|
@ -116,15 +116,13 @@ In general, we follow the "fork-and-pull" Git workflow.
|
||||||
3. **Commit** changes to your own branch
|
3. **Commit** changes to your own branch
|
||||||
- 3.1. **Add** unit tests covering your change in the `test` folder
|
- 3.1. **Add** unit tests covering your change in the `test` folder
|
||||||
- 3.2. **Run** the tests with the `npm run eslint test` command
|
- 3.2. **Run** the tests with the `npm run eslint test` command
|
||||||
- 3.3. **Ensure** build is working with `npm run build-all` command
|
- 3.3. **Ensure** build is working with `npm run dist` command
|
||||||
4. **Push** your work back up to your fork
|
4. **Push** your work back up to your fork
|
||||||
5. Submit a **Pull request** so that we can review your changes
|
5. Submit a **Pull request** so that we can review your changes
|
||||||
|
|
||||||
NOTE: Be sure to merge the latest from "upstream" before making a pull request!
|
NOTE: Be sure to merge the latest from "upstream" before making a pull request!
|
||||||
|
|
||||||
## Donations
|
## Donations
|
||||||
To support this project simply locate the `Donate` button in the [project's
|
Support this project by donating [here](http://www.tablefilter.com/donate.html).
|
||||||
website](http://koalyptus.github.io/TableFilter/)
|
Thanks to all those who supported this project in the past and those who will
|
||||||
which points to PayPal.
|
|
||||||
Thanks to all those who supported this project in the past and to those who will
|
|
||||||
in the future!
|
in the future!
|
||||||
|
|
260
Gruntfile.js
260
Gruntfile.js
|
@ -1,38 +1,19 @@
|
||||||
module.exports = function (grunt) {
|
module.exports = function (grunt) {
|
||||||
var webpackConfig = require('./webpack.config.js');
|
|
||||||
var webpackDevConfig = require('./webpack.dev.config.js');
|
|
||||||
var webpackTestConfig = require('./webpack.test.config.js');
|
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var testDir = 'test';
|
var testDir = 'test';
|
||||||
var testHost = 'http://localhost:8000/';
|
var testHost = 'http://localhost:8000/';
|
||||||
var pkg = grunt.file.readJSON('package.json');
|
var pkg = grunt.file.readJSON('package.json');
|
||||||
var repo = 'github.com/koalyptus/TableFilter';
|
|
||||||
var styleDirDist = 'dist/tablefilter/style/';
|
|
||||||
|
|
||||||
grunt.initConfig({
|
grunt.initConfig({
|
||||||
|
|
||||||
eslint: {
|
|
||||||
options: {
|
|
||||||
configFile: '.eslintrc'
|
|
||||||
},
|
|
||||||
target: [
|
|
||||||
'Gruntfile.js',
|
|
||||||
'webpack.config.js',
|
|
||||||
'webpack.dev.config.js',
|
|
||||||
'webpack.test.config.js',
|
|
||||||
'src/**/*.js',
|
|
||||||
'test/*.js'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
qunit: {
|
qunit: {
|
||||||
options: {
|
options: {
|
||||||
'--web-security': 'no',
|
'--web-security': 'no',
|
||||||
coverage: {
|
coverage: {
|
||||||
disposeCollector: true,
|
disposeCollector: true,
|
||||||
src: ['dist/tablefilter/*.js'],
|
src: ['dist/tablefilter/*.js'],
|
||||||
instrumentedFiles: 'temp/',
|
instrumentedFiles: 'report/temp/',
|
||||||
htmlReport: 'report/coverage',
|
htmlReport: 'report/coverage',
|
||||||
coberturaReport: 'report/',
|
coberturaReport: 'report/',
|
||||||
lcovReport: 'report/',
|
lcovReport: 'report/',
|
||||||
|
@ -126,24 +107,6 @@ module.exports = function (grunt) {
|
||||||
|
|
||||||
clean: ['demos/starter.html'],
|
clean: ['demos/starter.html'],
|
||||||
|
|
||||||
'webpack-dev-server': {
|
|
||||||
options: {
|
|
||||||
webpack: webpackDevConfig,
|
|
||||||
publicPath: '/dist/'
|
|
||||||
},
|
|
||||||
start: {
|
|
||||||
webpack: {
|
|
||||||
devtool: 'eval'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
webpack: {
|
|
||||||
build: webpackConfig,
|
|
||||||
dev: webpackDevConfig,
|
|
||||||
test: webpackTestConfig
|
|
||||||
},
|
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
app: {
|
app: {
|
||||||
files: ['src/**/*', 'static/style/**/*'],
|
files: ['src/**/*', 'static/style/**/*'],
|
||||||
|
@ -161,168 +124,49 @@ module.exports = function (grunt) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
babel: {
|
// temporary shell commands while decommissioning grunt
|
||||||
options: {
|
shell: {
|
||||||
sourceMap: true,
|
eslint: {
|
||||||
modules: 'amd',
|
command: 'npm run lint'
|
||||||
compact: false,
|
|
||||||
presets: ['es2015']
|
|
||||||
},
|
},
|
||||||
dist: {
|
|
||||||
files: [{
|
|
||||||
expand: true,
|
|
||||||
cwd: 'src',
|
|
||||||
src: ['**/*.js'],
|
|
||||||
dest: 'dist/tablefilter'
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
esdoc: {
|
esdoc: {
|
||||||
dist: {
|
command: 'npm run esdoc'
|
||||||
options: {
|
},
|
||||||
source: 'src',
|
build: {
|
||||||
destination: 'docs/docs',
|
command: 'npm run build'
|
||||||
title: pkg.name + ' v' + pkg.version
|
},
|
||||||
|
dev: {
|
||||||
|
command: 'npm run dev'
|
||||||
|
},
|
||||||
|
test: {
|
||||||
|
command: 'npm run build:test'
|
||||||
|
},
|
||||||
|
'build-css': {
|
||||||
|
command: 'npm run build:css'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
stylus: {
|
|
||||||
compile: {
|
|
||||||
options: {
|
|
||||||
banner: '/** \n' +
|
|
||||||
' *\t ' + pkg.name + ' v' + pkg.version +
|
|
||||||
' by ' + pkg.author.name + ' \n' +
|
|
||||||
' *\t build date: ' + new Date().toISOString() + ' \n' +
|
|
||||||
' *\t MIT License \n' +
|
|
||||||
' */ \n'
|
|
||||||
},
|
|
||||||
files: [
|
|
||||||
{
|
|
||||||
src: ['static/style/*.styl'],
|
|
||||||
dest: styleDirDist + 'tablefilter.css'
|
|
||||||
}, {
|
|
||||||
src: ['static/style/extensions/colsVisibility.styl'],
|
|
||||||
dest: styleDirDist + 'colsVisibility.css'
|
|
||||||
}, {
|
|
||||||
src: ['static/style/extensions/filtersVisibility.styl'],
|
|
||||||
dest: styleDirDist + 'filtersVisibility.css'
|
|
||||||
}, {
|
|
||||||
src: ['static/style/themes/default/*.styl'],
|
|
||||||
dest: styleDirDist + 'themes/default/default.css'
|
|
||||||
}, {
|
|
||||||
src: ['static/style/themes/mytheme/*.styl'],
|
|
||||||
dest: styleDirDist + 'themes/mytheme/mytheme.css'
|
|
||||||
}, {
|
|
||||||
src: ['static/style/themes/skyblue/*.styl'],
|
|
||||||
dest: styleDirDist + 'themes/skyblue/skyblue.css'
|
|
||||||
}, {
|
|
||||||
src: ['static/style/themes/transparent/*.styl'],
|
|
||||||
dest:
|
|
||||||
styleDirDist + 'themes/transparent/transparent.css'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
'gh-pages': {
|
|
||||||
options: {
|
|
||||||
branch: 'gh-pages',
|
|
||||||
add: true
|
|
||||||
},
|
|
||||||
'publish-lib': {
|
|
||||||
options: {
|
|
||||||
base: 'dist',
|
|
||||||
repo: 'https://' + repo,
|
|
||||||
message: 'publish TableFilter lib to gh-pages (cli)'
|
|
||||||
},
|
|
||||||
src: ['**/*']
|
|
||||||
},
|
|
||||||
'publish-readme': {
|
|
||||||
options: {
|
|
||||||
base: './',
|
|
||||||
repo: 'https://' + repo,
|
|
||||||
message: 'publish README and LICENSE to gh-pages (cli)'
|
|
||||||
},
|
|
||||||
src: ['README.md', 'LICENSE']
|
|
||||||
},
|
|
||||||
'publish-docs': {
|
|
||||||
options: {
|
|
||||||
base: 'docs',
|
|
||||||
repo: 'https://' + repo,
|
|
||||||
message: 'publish Docs to gh-pages (cli)'
|
|
||||||
},
|
|
||||||
src: ['**/*']
|
|
||||||
},
|
|
||||||
'deploy-lib': {
|
|
||||||
options: {
|
|
||||||
user: {
|
|
||||||
name: 'koalyptus'
|
|
||||||
},
|
|
||||||
base: 'dist',
|
|
||||||
repo: 'https://' + process.env.GH_TOKEN + '@' + repo,
|
|
||||||
message: 'publish TableFilter to gh-pages (auto)' +
|
|
||||||
getDeployMessage(),
|
|
||||||
silent: true
|
|
||||||
},
|
|
||||||
src: ['**/*']
|
|
||||||
},
|
|
||||||
'deploy-readme': {
|
|
||||||
options: {
|
|
||||||
user: {
|
|
||||||
name: 'koalyptus'
|
|
||||||
},
|
|
||||||
base: './',
|
|
||||||
repo: 'https://' + process.env.GH_TOKEN + '@' + repo,
|
|
||||||
message: 'publish README to gh-pages (auto)' +
|
|
||||||
getDeployMessage(),
|
|
||||||
silent: true
|
|
||||||
},
|
|
||||||
src: ['README.md', 'LICENSE']
|
|
||||||
},
|
|
||||||
'deploy-docs': {
|
|
||||||
options: {
|
|
||||||
user: {
|
|
||||||
name: 'koalyptus'
|
|
||||||
},
|
|
||||||
base: 'docs',
|
|
||||||
repo: 'https://' + process.env.GH_TOKEN + '@' + repo,
|
|
||||||
message: 'publish Docs to gh-pages (auto)' +
|
|
||||||
getDeployMessage(),
|
|
||||||
silent: true
|
|
||||||
},
|
|
||||||
src: ['**/*']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
grunt.loadNpmTasks('grunt-eslint');
|
|
||||||
grunt.loadNpmTasks('grunt-contrib-copy');
|
grunt.loadNpmTasks('grunt-contrib-copy');
|
||||||
grunt.loadNpmTasks('grunt-contrib-clean');
|
grunt.loadNpmTasks('grunt-contrib-clean');
|
||||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||||
grunt.loadNpmTasks('grunt-string-replace');
|
grunt.loadNpmTasks('grunt-string-replace');
|
||||||
grunt.loadNpmTasks('grunt-contrib-connect');
|
grunt.loadNpmTasks('grunt-contrib-connect');
|
||||||
grunt.loadNpmTasks('grunt-webpack');
|
grunt.loadNpmTasks('grunt-shell');
|
||||||
grunt.loadNpmTasks('grunt-babel');
|
|
||||||
grunt.loadNpmTasks('grunt-esdoc');
|
|
||||||
grunt.loadNpmTasks('grunt-qunit-istanbul');
|
grunt.loadNpmTasks('grunt-qunit-istanbul');
|
||||||
grunt.loadNpmTasks('grunt-contrib-stylus');
|
|
||||||
grunt.loadNpmTasks('grunt-gh-pages');
|
grunt.registerTask('eslint', ['shell:eslint']);
|
||||||
|
grunt.registerTask('esdoc', ['shell:esdoc']);
|
||||||
|
|
||||||
grunt.registerTask('default', ['test', 'build', 'build-demos']);
|
grunt.registerTask('default', ['test', 'build', 'build-demos']);
|
||||||
|
|
||||||
// Development server
|
|
||||||
grunt.registerTask('server', ['webpack-dev-server:start']);
|
|
||||||
|
|
||||||
// Dev dev/build/watch cycle
|
// Dev dev/build/watch cycle
|
||||||
grunt.registerTask('dev',
|
grunt.registerTask('dev',
|
||||||
['eslint', 'webpack:dev', 'copy:dist', 'stylus:compile', 'watch:app']);
|
['eslint', 'shell:dev', 'copy:dist', 'shell:build-css', 'watch:app']);
|
||||||
|
|
||||||
// Production build
|
// Production build
|
||||||
grunt.registerTask('build',
|
grunt.registerTask('build',
|
||||||
['eslint', 'webpack:build', 'copy:dist', 'stylus:compile']);
|
['eslint', 'shell:build', 'copy:dist', 'shell:build-css']);
|
||||||
|
|
||||||
// Build demos
|
// Build demos
|
||||||
grunt.registerTask('dev-demos', ['build-demos', 'watch:templates']);
|
grunt.registerTask('dev-demos', ['build-demos', 'watch:templates']);
|
||||||
|
@ -331,23 +175,14 @@ module.exports = function (grunt) {
|
||||||
|
|
||||||
// Build tests
|
// Build tests
|
||||||
grunt.registerTask('build-test',
|
grunt.registerTask('build-test',
|
||||||
['eslint', 'webpack:test', 'copy:dist', 'stylus:compile']);
|
['eslint', 'shell:test', 'copy:dist', 'shell:build-css']);
|
||||||
|
|
||||||
// Transpile with Babel
|
|
||||||
grunt.registerTask('dev-modules', ['babel', 'copy:dist']);
|
|
||||||
|
|
||||||
// Tests with coverage
|
// Tests with coverage
|
||||||
grunt.registerTask('test', ['build-test', 'connect', 'qunit:all']);
|
grunt.registerTask('test', ['build-test', 'connect', 'qunit:all']);
|
||||||
|
|
||||||
// Publish to gh-pages
|
// Build all for deployment from travis
|
||||||
grunt.registerTask('publish', 'Publish from CLI', [
|
grunt.registerTask('build-all', 'Prepare for deployment', [
|
||||||
'build', 'build-demos', 'esdoc', 'gh-pages:publish-lib',
|
'build', 'build-demos', 'esdoc'
|
||||||
'gh-pages:publish-readme', 'gh-pages:publish-docs'
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Deploy to gh-pages
|
|
||||||
grunt.registerTask('deploy', 'Publish from Travis', [
|
|
||||||
'build', 'esdoc', 'check-deploy'
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Custom task running QUnit tests for specified files.
|
// Custom task running QUnit tests for specified files.
|
||||||
|
@ -414,43 +249,4 @@ module.exports = function (grunt) {
|
||||||
|
|
||||||
return getFiles(testDir, host);
|
return getFiles(testDir, host);
|
||||||
}
|
}
|
||||||
|
|
||||||
grunt.registerTask('check-deploy', function () {
|
|
||||||
var env = process.env;
|
|
||||||
// need this
|
|
||||||
this.requires(['build', 'esdoc']);
|
|
||||||
|
|
||||||
// only deploy under these conditions
|
|
||||||
if (env.TRAVIS === 'true' &&
|
|
||||||
env.TRAVIS_SECURE_ENV_VARS === 'true' &&
|
|
||||||
env.TRAVIS_PULL_REQUEST === 'false') {
|
|
||||||
grunt.log.writeln('executing deployment');
|
|
||||||
// queue deploy
|
|
||||||
grunt.task.run([
|
|
||||||
'gh-pages:deploy-lib',
|
|
||||||
'gh-pages:deploy-readme',
|
|
||||||
'gh-pages:deploy-docs'
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
grunt.log.writeln('skipped deployment');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get a formatted commit message to review changes from the commit log
|
|
||||||
// github will turn some of these into clickable links
|
|
||||||
function getDeployMessage() {
|
|
||||||
var ret = '\n\n';
|
|
||||||
var env = process.env;
|
|
||||||
if (env.TRAVIS !== 'true') {
|
|
||||||
ret += 'missing env vars for travis-ci';
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
ret += 'branch: ' + env.TRAVIS_BRANCH + '\n';
|
|
||||||
ret += 'SHA: ' + env.TRAVIS_COMMIT + '\n';
|
|
||||||
ret += 'range SHA: ' + env.TRAVIS_COMMIT_RANGE + '\n';
|
|
||||||
ret += 'build id: ' + env.TRAVIS_BUILD_ID + '\n';
|
|
||||||
ret += 'build number: ' + env.TRAVIS_BUILD_NUMBER + '\n';
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
24
PULL_REQUEST_TEMPLATE.md
Normal file
24
PULL_REQUEST_TEMPLATE.md
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# Description
|
||||||
|
|
||||||
|
Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context.
|
||||||
|
Fixes # (issue)
|
||||||
|
|
||||||
|
## Type of change
|
||||||
|
|
||||||
|
Please delete options that are not relevant.
|
||||||
|
|
||||||
|
- [ ] Bug fix (non-breaking change which fixes an issue)
|
||||||
|
- [ ] New feature (non-breaking change which adds functionality)
|
||||||
|
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
||||||
|
- [ ] This change requires a documentation update
|
||||||
|
- [ ] Development tool configuration change
|
||||||
|
|
||||||
|
# Checklist:
|
||||||
|
|
||||||
|
- [ ] My code follows the style guidelines of this project
|
||||||
|
- [ ] I have performed a self-review of my own code
|
||||||
|
- [ ] I have commented my code, particularly in hard-to-understand areas
|
||||||
|
- [ ] I have made corresponding changes to the documentation
|
||||||
|
- [ ] My changes do not lower current test coverage
|
||||||
|
- [ ] I have added tests that prove my fix is effective or that my feature works
|
||||||
|
- [ ] New and existing unit tests pass locally with my changes
|
39
README.md
39
README.md
|
@ -1,6 +1,8 @@
|
||||||
[![Build Status](https://api.travis-ci.org/koalyptus/TableFilter.svg?branch=master)](https://travis-ci.org/koalyptus/TableFilter)
|
[![Build Status](https://api.travis-ci.org/koalyptus/TableFilter.svg?branch=master)](https://travis-ci.org/koalyptus/TableFilter)
|
||||||
[![Document](http://koalyptus.github.io/TableFilter/docs/badge.svg)](https://koalyptus.github.io/TableFilter/docs/source)
|
[![Document](https://www.tablefilter.com/docs/badge.svg)](https://www.tablefilter.com/docs/source.html)
|
||||||
[![codecov](https://codecov.io/gh/koalyptus/TableFilter/branch/master/graph/badge.svg)](https://codecov.io/gh/koalyptus/TableFilter)
|
[![codecov](https://codecov.io/gh/koalyptus/TableFilter/branch/master/graph/badge.svg)](https://codecov.io/gh/koalyptus/TableFilter)
|
||||||
|
[![Greenkeeper badge](https://badges.greenkeeper.io/koalyptus/TableFilter.svg)](https://greenkeeper.io/)
|
||||||
|
[![Donate](https://img.shields.io/badge/donate-%24-green.svg)](https://www.tablefilter.com/donate.html)
|
||||||
|
|
||||||
# TableFilter
|
# TableFilter
|
||||||
|
|
||||||
|
@ -22,7 +24,7 @@ users to filter and limit the data displayed within a long table. By default, th
|
||||||
* Attach to an existing HTML table
|
* Attach to an existing HTML table
|
||||||
* Integration with any server-side technology as this is a pure client-side
|
* Integration with any server-side technology as this is a pure client-side
|
||||||
solution
|
solution
|
||||||
* Exhaustive documentation and poweful API
|
* Exhaustive documentation and powerful API
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
* Clone the repo using Git:
|
* Clone the repo using Git:
|
||||||
|
@ -32,7 +34,7 @@ git clone https://github.com/koalyptus/TableFilter.git
|
||||||
|
|
||||||
* You can [download](https://github.com/koalyptus/TableFilter/archive/master.zip) this repository.
|
* You can [download](https://github.com/koalyptus/TableFilter/archive/master.zip) this repository.
|
||||||
|
|
||||||
* Alternatively, install TableFilter files in your npm enabled project using:
|
* TableFilter is available on [npm repository](https://www.npmjs.com/package/tablefilter), you can install it from the command line using the following command:
|
||||||
```shell
|
```shell
|
||||||
npm install tablefilter --save-dev
|
npm install tablefilter --save-dev
|
||||||
```
|
```
|
||||||
|
@ -40,15 +42,32 @@ npm install tablefilter --save-dev
|
||||||
```shell
|
```shell
|
||||||
npm install tablefilter@next --save-dev
|
npm install tablefilter@next --save-dev
|
||||||
```
|
```
|
||||||
* If you don't use `npm`, you can also
|
* Alternatively you can also [access these files from unpkg CDN](https://unpkg.com/tablefilter/), download them or point your package manager to them.
|
||||||
[access these files on unpkg](https://unpkg.com/tablefilter/), download them
|
|
||||||
or point your package manager to them.
|
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
### Using modules
|
||||||
|
Require `TableFilter`:
|
||||||
|
```javascript
|
||||||
|
// ES2015 modules
|
||||||
|
import TableFilter from 'tablefilter';
|
||||||
|
|
||||||
|
// CommonJS or AMD modules
|
||||||
|
var TableFilter = require('tablefilter');
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using distribution scripts
|
||||||
|
If you are not using a module system, you can reference the distribution scripts directly in your html pages:
|
||||||
|
```html
|
||||||
|
<script src="path_to/node_modules/tablefilter/dist/tablefilter/tablefilter.js"></script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Placing manually the distribution scripts in your project
|
||||||
Copy the ``tablefilter`` directory under ``dist`` and place it at desired location in your project. Then include the main js file in your page:
|
Copy the ``tablefilter`` directory under ``dist`` and place it at desired location in your project. Then include the main js file in your page:
|
||||||
```shell
|
```shell
|
||||||
<script src="path/to/my/scripts/tablefilter/tablefilter.js"></script>
|
<script src="path/to/my/scripts/tablefilter/tablefilter.js"></script>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Usage
|
||||||
Place the following snippet just under the HTML table and always define a ``base_path`` property in the configuration object to reflect the path to the script
|
Place the following snippet just under the HTML table and always define a ``base_path`` property in the configuration object to reflect the path to the script
|
||||||
```shell
|
```shell
|
||||||
<script>
|
<script>
|
||||||
|
@ -66,7 +85,7 @@ your-page.html
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
This project requires node.js and Grunt to be installed:
|
This project requires node.js and Grunt to be installed:
|
||||||
- install [node.js](https://nodejs.org/)
|
- install [node.js](https://nodejs.org/) v8.9.4 or higher
|
||||||
- install [Grunt](http://gruntjs.com/getting-started) from the command line using npm (comes with node.js):
|
- install [Grunt](http://gruntjs.com/getting-started) from the command line using npm (comes with node.js):
|
||||||
```shell
|
```shell
|
||||||
npm install -g grunt-cli
|
npm install -g grunt-cli
|
||||||
|
@ -115,7 +134,7 @@ to view the coverage report(s), open the `index.html` under the
|
||||||
[online](https://codecov.io/gh/koalyptus/TableFilter).
|
[online](https://codecov.io/gh/koalyptus/TableFilter).
|
||||||
|
|
||||||
## Demos
|
## Demos
|
||||||
Check out the online [examples](http://koalyptus.github.io/TableFilter/examples)
|
Check out the online [examples](http://www.tablefilter.com/examples.html)
|
||||||
or generate the demos locally:
|
or generate the demos locally:
|
||||||
```shell
|
```shell
|
||||||
npm run build:demos
|
npm run build:demos
|
||||||
|
@ -132,7 +151,7 @@ http://localhost:8080/demos/
|
||||||
## Documentation
|
## Documentation
|
||||||
Find exhaustive documentation on the configuration options in the [WIKI](https://github.com/koalyptus/TableFilter/wiki) section.
|
Find exhaustive documentation on the configuration options in the [WIKI](https://github.com/koalyptus/TableFilter/wiki) section.
|
||||||
|
|
||||||
Autogenerated documentation of the ES6 modules is available on the website: [docs](http://koalyptus.github.io/TableFilter/docs)
|
Autogenerated documentation of the ES6 modules is available on the website: [docs](http://www.tablefilter.com/docs)
|
||||||
|
|
||||||
If you previously used the HTML Table Filter Generator plugin, verify the configuration
|
If you previously used the HTML Table Filter Generator plugin, verify the configuration
|
||||||
options you are using are still supported: [Obsolete](https://github.com/koalyptus/TableFilter/wiki/Obsolete)
|
options you are using are still supported: [Obsolete](https://github.com/koalyptus/TableFilter/wiki/Obsolete)
|
||||||
|
@ -143,7 +162,7 @@ npm run esdoc
|
||||||
```
|
```
|
||||||
|
|
||||||
## Support
|
## Support
|
||||||
* GitHub for reporting bugs and feature requests.
|
* GitHub for [reporting bugs](https://github.com/koalyptus/TableFilter/blob/master/CONTRIBUTING.md#reporting-bugs) and [feature requests](https://github.com/koalyptus/TableFilter/blob/master/CONTRIBUTING.md#suggesting-enhancements-and-features).
|
||||||
|
|
||||||
## License
|
## License
|
||||||
[MIT](LICENSE)
|
[MIT](LICENSE)
|
||||||
|
|
6
dist/starter.html
vendored
6
dist/starter.html
vendored
|
@ -1,10 +1,10 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<title>tablefilter v0.4.40 - Starter</title>
|
<title>tablefilter v0.7.3 - Starter</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>tablefilter v0.4.40</h1>
|
<h1>tablefilter v0.7.3</h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -479,7 +479,7 @@
|
||||||
},
|
},
|
||||||
col_widths: [
|
col_widths: [
|
||||||
'150px', '100px', '100px',
|
'150px', '100px', '100px',
|
||||||
'70px', '70px', '70px',
|
'100px', '100px', '100px',
|
||||||
'70px', '60px', '60px'
|
'70px', '60px', '60px'
|
||||||
],
|
],
|
||||||
extensions:[{ name: 'sort' }]
|
extensions:[{ name: 'sort' }]
|
||||||
|
|
7
dist/tablefilter/style/colsVisibility.css
vendored
7
dist/tablefilter/style/colsVisibility.css
vendored
|
@ -1,6 +1 @@
|
||||||
/**
|
span.colVisSpan{text-align:left;}span.colVisSpan a.colVis{display:inline-block;padding:7px 5px 0;font-size:inherit;font-weight:inherit;vertical-align:top}div.colVisCont{position:relative;background:#fff;-webkit-box-shadow:3px 3px 2px #888;-moz-box-shadow:3px 3px 2px #888;box-shadow:3px 3px 2px #888;position:absolute;display:none;border:1px solid #ccc;height:auto;width:250px;background-color:#fff;margin:35px 0 0 -100px;z-index:10000;padding:10px 10px 10px 10px;text-align:left;font-size:inherit;}div.colVisCont:after,div.colVisCont:before{bottom:100%;left:50%;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}div.colVisCont:after{border-color:rgba(255,255,255,0);border-bottom-color:#fff;border-width:10px;margin-left:-10px}div.colVisCont:before{border-color:rgba(255,255,255,0);border-bottom-color:#ccc;border-width:12px;margin-left:-12px}div.colVisCont p{margin:6px auto 6px auto}div.colVisCont a.colVis{display:initial;font-weight:inherit}ul.cols_checklist{padding:0;margin:0;list-style-type:none;}ul.cols_checklist label{display:block}ul.cols_checklist input{vertical-align:middle;margin:2px 5px 2px 1px}li.cols_checklist_item{padding:4px;margin:0;}li.cols_checklist_item:hover{background-color:#335ea8;color:#fff}.cols_checklist_slc_item{background-color:#335ea8;color:#fff}
|
||||||
* tablefilter v0.4.40 by Max Guglielmi
|
|
||||||
* build date: 2017-02-11T12:40:33.756Z
|
|
||||||
* MIT License
|
|
||||||
*/
|
|
||||||
span.colVisSpan{text-align:left;}span.colVisSpan a.colVis{display:inline-block;padding:7px 5px 0;font-size:inherit;font-weight:inherit;vertical-align:top}div.colVisCont{position:relative;background:#fff;-webkit-box-shadow:3px 3px 2px #888;-moz-box-shadow:3px 3px 2px #888;box-shadow:3px 3px 2px #888;position:absolute;display:none;border:1px solid #ccc;height:auto;width:250px;background-color:#fff;margin:35px 0 0 -100px;z-index:10000;padding:10px 10px 10px 10px;text-align:left;font-size:12px;}div.colVisCont:after,div.colVisCont:before{bottom:100%;left:50%;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}div.colVisCont:after{border-color:rgba(255,255,255,0);border-bottom-color:#fff;border-width:10px;margin-left:-10px}div.colVisCont:before{border-color:rgba(255,255,255,0);border-bottom-color:#ccc;border-width:12px;margin-left:-12px}div.colVisCont p{margin:6px auto 6px auto}div.colVisCont a.colVis{display:initial;font-weight:inherit}ul.cols_checklist{padding:0;margin:0;list-style:none;}ul.cols_checklist label{display:block}ul.cols_checklist input{vertical-align:middle;margin:2px 5px 2px 1px}li.cols_checklist_item{padding:4px;margin:0;}li.cols_checklist_item:hover{background-color:#335ea8;color:#fff}.cols_checklist_slc_item{background-color:#335ea8;color:#fff}
|
|
5
dist/tablefilter/style/filtersVisibility.css
vendored
5
dist/tablefilter/style/filtersVisibility.css
vendored
|
@ -1,6 +1 @@
|
||||||
/**
|
|
||||||
* tablefilter v0.4.40 by Max Guglielmi
|
|
||||||
* build date: 2017-02-11T12:40:33.756Z
|
|
||||||
* MIT License
|
|
||||||
*/
|
|
||||||
span.expClpFlt a.btnExpClpFlt{width:35px;height:35px;display:inline-block;}span.expClpFlt a.btnExpClpFlt:hover{background-color:#f4f4f4}span.expClpFlt img{padding:8px 11px 11px 11px}
|
span.expClpFlt a.btnExpClpFlt{width:35px;height:35px;display:inline-block;}span.expClpFlt a.btnExpClpFlt:hover{background-color:#f4f4f4}span.expClpFlt img{padding:8px 11px 11px 11px}
|
24
dist/tablefilter/style/tablefilter.css
vendored
24
dist/tablefilter/style/tablefilter.css
vendored
File diff suppressed because one or more lines are too long
|
@ -1,6 +1 @@
|
||||||
/**
|
|
||||||
* tablefilter v0.4.40 by Max Guglielmi
|
|
||||||
* build date: 2017-02-11T12:40:33.756Z
|
|
||||||
* MIT License
|
|
||||||
*/
|
|
||||||
table.TF{border-left:1px solid #ccc;border-top:none;border-right:none;border-bottom:none;}table.TF th{background:#ebecee url("images/bg_th.jpg") left top repeat-x;border-bottom:1px solid #d0d0d0;border-right:1px solid #d0d0d0;border-left:1px solid #fff;border-top:1px solid #fff;color:#333}table.TF td{border-bottom:1px dotted #999;padding:5px}.fltrow{background-color:#ebecee !important;}.fltrow th,.fltrow td{border-bottom:1px dotted #666 !important;padding:1px 3px 1px 3px !important}.flt,select.flt,select.flt_multi,.flt_s,.single_flt,.div_checklist{border:1px solid #999 !important}input.flt{width:99% !important}.inf{height:$min-height;background:#d7d7d7 url("images/bg_infDiv.jpg") 0 0 repeat-x !important}input.reset{background:transparent url("images/btn_eraser.gif") center center no-repeat !important}.helpBtn:hover{background-color:transparent}.nextPage{background:transparent url("images/btn_next_page.gif") center center no-repeat !important;}.nextPage:hover{background:transparent url("images/btn_over_next_page.gif") center center no-repeat !important}.previousPage{background:transparent url("images/btn_previous_page.gif") center center no-repeat !important;}.previousPage:hover{background:transparent url("images/btn_over_previous_page.gif") center center no-repeat !important}.firstPage{background:transparent url("images/btn_first_page.gif") center center no-repeat !important;}.firstPage:hover{background:transparent url("images/btn_over_first_page.gif") center center no-repeat !important}.lastPage{background:transparent url("images/btn_last_page.gif") center center no-repeat !important;}.lastPage:hover{background:transparent url("images/btn_over_last_page.gif") center center no-repeat !important}div.grd_Cont{background-color:#ebecee !important;border:1px solid #ccc !important;padding:0 !important;}div.grd_Cont .even{background-color:#fff}div.grd_Cont .odd{background-color:#d5d5d5}div.grd_headTblCont{background-color:#ebecee !important;border-bottom:none !important;}div.grd_headTblCont table{border-right:none !important}div.grd_tblCont table th,div.grd_headTblCont table th,div.grd_headTblCont table td{background:#ebecee url("images/bg_th.jpg") left top repeat-x !important;border-bottom:1px solid #d0d0d0 !important;border-right:1px solid #d0d0d0 !important;border-left:1px solid #fff !important;border-top:1px solid #fff !important}div.grd_tblCont table td{border-bottom:1px solid #999 !important}.grd_inf{background:#d7d7d7 url("images/bg_infDiv.jpg") 0 0 repeat-x !important;border-top:1px solid #d0d0d0 !important}.loader{border:1px solid #999}.defaultLoader{width:32px;height:32px;background:transparent url("images/img_loading.gif") 0 0 no-repeat !important}.even{background-color:#fff}.odd{background-color:#d5d5d5}span.expClpFlt a.btnExpClpFlt:hover{background-color:transparent !important}.activeHeader{background:#999 !important}
|
table.TF{border-left:1px solid #ccc;border-top:none;border-right:none;border-bottom:none;}table.TF th{background:#ebecee url("images/bg_th.jpg") left top repeat-x;border-bottom:1px solid #d0d0d0;border-right:1px solid #d0d0d0;border-left:1px solid #fff;border-top:1px solid #fff;color:#333}table.TF td{border-bottom:1px dotted #999;padding:5px}.fltrow{background-color:#ebecee !important;}.fltrow th,.fltrow td{border-bottom:1px dotted #666 !important;padding:1px 3px 1px 3px !important}.flt,select.flt,select.flt_multi,.flt_s,.single_flt,.div_checklist{border:1px solid #999 !important}input.flt{width:99% !important}.inf{height:$min-height;background:#d7d7d7 url("images/bg_infDiv.jpg") 0 0 repeat-x !important}input.reset{background:transparent url("images/btn_eraser.gif") center center no-repeat !important}.helpBtn:hover{background-color:transparent}.nextPage{background:transparent url("images/btn_next_page.gif") center center no-repeat !important;}.nextPage:hover{background:transparent url("images/btn_over_next_page.gif") center center no-repeat !important}.previousPage{background:transparent url("images/btn_previous_page.gif") center center no-repeat !important;}.previousPage:hover{background:transparent url("images/btn_over_previous_page.gif") center center no-repeat !important}.firstPage{background:transparent url("images/btn_first_page.gif") center center no-repeat !important;}.firstPage:hover{background:transparent url("images/btn_over_first_page.gif") center center no-repeat !important}.lastPage{background:transparent url("images/btn_last_page.gif") center center no-repeat !important;}.lastPage:hover{background:transparent url("images/btn_over_last_page.gif") center center no-repeat !important}div.grd_Cont{background-color:#ebecee !important;border:1px solid #ccc !important;padding:0 !important;}div.grd_Cont .even{background-color:#fff}div.grd_Cont .odd{background-color:#d5d5d5}div.grd_headTblCont{background-color:#ebecee !important;border-bottom:none !important;}div.grd_headTblCont table{border-right:none !important}div.grd_tblCont table th,div.grd_headTblCont table th,div.grd_headTblCont table td{background:#ebecee url("images/bg_th.jpg") left top repeat-x !important;border-bottom:1px solid #d0d0d0 !important;border-right:1px solid #d0d0d0 !important;border-left:1px solid #fff !important;border-top:1px solid #fff !important}div.grd_tblCont table td{border-bottom:1px solid #999 !important}.grd_inf{background:#d7d7d7 url("images/bg_infDiv.jpg") 0 0 repeat-x !important;border-top:1px solid #d0d0d0 !important}.loader{border:1px solid #999}.defaultLoader{width:32px;height:32px;background:transparent url("images/img_loading.gif") 0 0 no-repeat !important}.even{background-color:#fff}.odd{background-color:#d5d5d5}span.expClpFlt a.btnExpClpFlt:hover{background-color:transparent !important}.activeHeader{background:#999 !important}
|
|
@ -1,6 +1 @@
|
||||||
/**
|
|
||||||
* tablefilter v0.4.40 by Max Guglielmi
|
|
||||||
* build date: 2017-02-11T12:40:33.756Z
|
|
||||||
* MIT License
|
|
||||||
*/
|
|
||||||
table.TF{border-left:1px dotted #81963b;border-top:none;border-right:0;border-bottom:none;}table.TF th{background:#39424b url("images/bg_headers.jpg") left top repeat-x;border-bottom:0;border-right:1px dotted #d0d0d0;border-left:0;border-top:0;color:#fff}table.TF td{border-bottom:1px dotted #81963b;border-right:1px dotted #81963b;padding:5px}.fltrow{background-color:#81963b !important;}.fltrow th,.fltrow td{border-bottom:1px dotted #39424b !important;border-right:1px dotted #fff !important;border-left:0 !important;border-top:0 !important;padding:1px 3px 1px 3px !important}.flt,select.flt,select.flt_multi,.flt_s,.single_flt,.div_checklist{border:1px solid #687830 !important}input.flt{width:99% !important}.inf{background:#d8d8d8;height:$min-height}input.reset{width:53px;background:transparent url("images/btn_filter.png") center center no-repeat !important}.helpBtn:hover{background-color:transparent}.nextPage{background:transparent url("images/btn_next_page.gif") center center no-repeat !important}.previousPage{background:transparent url("images/btn_previous_page.gif") center center no-repeat !important}.firstPage{background:transparent url("images/btn_first_page.gif") center center no-repeat !important}.lastPage{background:transparent url("images/btn_last_page.gif") center center no-repeat !important}div.grd_Cont{background:#81963b url("images/bg_headers.jpg") left top repeat-x !important;border:1px solid #ccc !important;padding:0 1px 1px 1px !important;}div.grd_Cont .even{background-color:#bccd83}div.grd_Cont .odd{background-color:#fff}div.grd_headTblCont{background-color:#ebecee !important;border-bottom:none !important}div.grd_tblCont table{border-right:none !important;}div.grd_tblCont table td{border-bottom:1px dotted #81963b;border-right:1px dotted #81963b}div.grd_tblCont table th,div.grd_headTblCont table th{background:transparent url("images/bg_headers.jpg") 0 0 repeat-x !important;border-bottom:0 !important;border-right:1px dotted #d0d0d0 !important;border-left:0 !important;border-top:0 !important;padding:0 4px 0 4px !important;color:#fff !important;height:35px !important}div.grd_headTblCont table td{border-bottom:1px dotted #39424b !important;border-right:1px dotted #fff !important;border-left:0 !important;border-top:0 !important;background-color:#81963b !important;padding:1px 3px 1px 3px !important}.grd_inf{background-color:#d8d8d8;border-top:1px solid #d0d0d0 !important}.loader{border:0 !important;background:#81963b !important}.defaultLoader{width:32px;height:32px;background:transparent url("images/img_loading.gif") 0 0 no-repeat !important}.even{background-color:#bccd83}.odd{background-color:#fff}span.expClpFlt a.btnExpClpFlt:hover{background-color:transparent !important}.activeHeader{background:#81963b !important}
|
table.TF{border-left:1px dotted #81963b;border-top:none;border-right:0;border-bottom:none;}table.TF th{background:#39424b url("images/bg_headers.jpg") left top repeat-x;border-bottom:0;border-right:1px dotted #d0d0d0;border-left:0;border-top:0;color:#fff}table.TF td{border-bottom:1px dotted #81963b;border-right:1px dotted #81963b;padding:5px}.fltrow{background-color:#81963b !important;}.fltrow th,.fltrow td{border-bottom:1px dotted #39424b !important;border-right:1px dotted #fff !important;border-left:0 !important;border-top:0 !important;padding:1px 3px 1px 3px !important}.flt,select.flt,select.flt_multi,.flt_s,.single_flt,.div_checklist{border:1px solid #687830 !important}input.flt{width:99% !important}.inf{background:#d8d8d8;height:$min-height}input.reset{width:53px;background:transparent url("images/btn_filter.png") center center no-repeat !important}.helpBtn:hover{background-color:transparent}.nextPage{background:transparent url("images/btn_next_page.gif") center center no-repeat !important}.previousPage{background:transparent url("images/btn_previous_page.gif") center center no-repeat !important}.firstPage{background:transparent url("images/btn_first_page.gif") center center no-repeat !important}.lastPage{background:transparent url("images/btn_last_page.gif") center center no-repeat !important}div.grd_Cont{background:#81963b url("images/bg_headers.jpg") left top repeat-x !important;border:1px solid #ccc !important;padding:0 1px 1px 1px !important;}div.grd_Cont .even{background-color:#bccd83}div.grd_Cont .odd{background-color:#fff}div.grd_headTblCont{background-color:#ebecee !important;border-bottom:none !important}div.grd_tblCont table{border-right:none !important;}div.grd_tblCont table td{border-bottom:1px dotted #81963b;border-right:1px dotted #81963b}div.grd_tblCont table th,div.grd_headTblCont table th{background:transparent url("images/bg_headers.jpg") 0 0 repeat-x !important;border-bottom:0 !important;border-right:1px dotted #d0d0d0 !important;border-left:0 !important;border-top:0 !important;padding:0 4px 0 4px !important;color:#fff !important;height:35px !important}div.grd_headTblCont table td{border-bottom:1px dotted #39424b !important;border-right:1px dotted #fff !important;border-left:0 !important;border-top:0 !important;background-color:#81963b !important;padding:1px 3px 1px 3px !important}.grd_inf{background-color:#d8d8d8;border-top:1px solid #d0d0d0 !important}.loader{border:0 !important;background:#81963b !important}.defaultLoader{width:32px;height:32px;background:transparent url("images/img_loading.gif") 0 0 no-repeat !important}.even{background-color:#bccd83}.odd{background-color:#fff}span.expClpFlt a.btnExpClpFlt:hover{background-color:transparent !important}.activeHeader{background:#81963b !important}
|
|
@ -1,6 +1 @@
|
||||||
/**
|
|
||||||
* tablefilter v0.4.40 by Max Guglielmi
|
|
||||||
* build date: 2017-02-11T12:40:33.756Z
|
|
||||||
* MIT License
|
|
||||||
*/
|
|
||||||
table.TF{padding:0;color:#000;border-right:1px solid #a4bed4;border-top:1px solid #a4bed4;border-left:1px solid #a4bed4;border-bottom:0;}table.TF th{margin:0;color:inherit;background:#d1e5fe url("images/bg_skyblue.gif") 0 0 repeat-x;border-color:#fdfdfd #a4bed4 #a4bed4 #fdfdfd;border-width:1px;border-style:solid}table.TF td{margin:0;padding:5px;color:inherit;border-bottom:1px solid #a4bed4;border-left:0;border-top:0;border-right:0}.fltrow{background-color:#d1e5fe !important;}.fltrow th,.fltrow td{padding:1px 3px 1px 3px !important}.flt,select.flt,select.flt_multi,.flt_s,.single_flt,.div_checklist{border:1px solid #a4bed4 !important}input.flt{width:99% !important}.inf{background-color:#e3efff !important;border:1px solid #a4bed4;height:$min-height;color:#004a6f}div.tot,div.status{border-right:0 !important}.helpBtn:hover{background-color:transparent}input.reset{background:transparent url("images/icn_clear_filters.png") center center no-repeat !important}.nextPage{background:transparent url("images/btn_next_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.nextPage:hover{background:#ffe4ab url("images/btn_next_page.gif") center center no-repeat !important;border:1px solid #ffb552 !important}.previousPage{background:transparent url("images/btn_prev_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.previousPage:hover{background:#ffe4ab url("images/btn_prev_page.gif") center center no-repeat !important;border:1px solid #ffb552 !important}.firstPage{background:transparent url("images/btn_first_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.firstPage:hover{background:#ffe4ab url("images/btn_first_page.gif") center center no-repeat !important;border:1px solid #ffb552 !important}.lastPage{background:transparent url("images/btn_last_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.lastPage:hover{background:#ffe4ab url("images/btn_last_page.gif") center center no-repeat !important;border:1px solid #ffb552 !important}.activeHeader{background:#ffe4ab !important;border:1px solid #ffb552 !important;color:inherit !important}div.grd_Cont{background-color:#d9eaed !important;border:1px solid #9cc !important;padding:0 !important;}div.grd_Cont .even{background-color:#fff}div.grd_Cont .odd{background-color:#e3efff}div.grd_headTblCont{background-color:#d9eaed !important;border-bottom:none !important}div.grd_tblCont table{border-right:none !important}div.grd_tblCont table th,div.grd_headTblCont table th,div.grd_headTblCont table td{background:#d9eaed url("images/bg_skyblue.gif") left top repeat-x;border-bottom:1px solid #a4bed4;border-right:1px solid #a4bed4 !important;border-left:1px solid #fff !important;border-top:1px solid #fff !important}div.grd_tblCont table td{border-bottom:1px solid #a4bed4 !important;border-right:0 !important;border-left:0 !important;border-top:0 !important}.grd_inf{background-color:#cce2fe;color:#004a6f;border-top:1px solid #9cc !important;}.grd_inf a{text-decoration:none;font-weight:bold}.loader{background-color:#2d8eef;border:1px solid #cce2fe;border-radius:5px}.even{background-color:#fff}.odd{background-color:#e3efff}span.expClpFlt a.btnExpClpFlt:hover{background-color:transparent !important}.ezActiveRow{background-color:#ffdc61 !important;color:inherit}.ezSelectedRow{background-color:#ffe4ab !important;color:inherit}.ezActiveCell{background-color:#fff !important;color:#000 !important;font-weight:bold}.ezETSelectedCell{background-color:#fff !important;font-weight:bold;color:#000 !important}
|
table.TF{padding:0;color:#000;border-right:1px solid #a4bed4;border-top:1px solid #a4bed4;border-left:1px solid #a4bed4;border-bottom:0;}table.TF th{margin:0;color:inherit;background:#d1e5fe url("images/bg_skyblue.gif") 0 0 repeat-x;border-color:#fdfdfd #a4bed4 #a4bed4 #fdfdfd;border-width:1px;border-style:solid}table.TF td{margin:0;padding:5px;color:inherit;border-bottom:1px solid #a4bed4;border-left:0;border-top:0;border-right:0}.fltrow{background-color:#d1e5fe !important;}.fltrow th,.fltrow td{padding:1px 3px 1px 3px !important}.flt,select.flt,select.flt_multi,.flt_s,.single_flt,.div_checklist{border:1px solid #a4bed4 !important}input.flt{width:99% !important}.inf{background-color:#e3efff !important;border:1px solid #a4bed4;height:$min-height;color:#004a6f}div.tot,div.status{border-right:0 !important}.helpBtn:hover{background-color:transparent}input.reset{background:transparent url("images/icn_clear_filters.png") center center no-repeat !important}.nextPage{background:transparent url("images/btn_next_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.nextPage:hover{background:#ffe4ab url("images/btn_next_page.gif") center center no-repeat !important;border:1px solid #ffb552 !important}.previousPage{background:transparent url("images/btn_prev_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.previousPage:hover{background:#ffe4ab url("images/btn_prev_page.gif") center center no-repeat !important;border:1px solid #ffb552 !important}.firstPage{background:transparent url("images/btn_first_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.firstPage:hover{background:#ffe4ab url("images/btn_first_page.gif") center center no-repeat !important;border:1px solid #ffb552 !important}.lastPage{background:transparent url("images/btn_last_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.lastPage:hover{background:#ffe4ab url("images/btn_last_page.gif") center center no-repeat !important;border:1px solid #ffb552 !important}.activeHeader{background:#ffe4ab !important;border:1px solid #ffb552 !important;color:inherit !important}div.grd_Cont{background-color:#d9eaed !important;border:1px solid #9cc !important;padding:0 !important;}div.grd_Cont .even{background-color:#fff}div.grd_Cont .odd{background-color:#e3efff}div.grd_headTblCont{background-color:#d9eaed !important;border-bottom:none !important}div.grd_tblCont table{border-right:none !important}div.grd_tblCont table th,div.grd_headTblCont table th,div.grd_headTblCont table td{background:#d9eaed url("images/bg_skyblue.gif") left top repeat-x;border-bottom:1px solid #a4bed4;border-right:1px solid #a4bed4 !important;border-left:1px solid #fff !important;border-top:1px solid #fff !important}div.grd_tblCont table td{border-bottom:1px solid #a4bed4 !important;border-right:0 !important;border-left:0 !important;border-top:0 !important}.grd_inf{background-color:#cce2fe;color:#004a6f;border-top:1px solid #9cc !important;}.grd_inf a{text-decoration:none;font-weight:bold}.loader{background-color:#2d8eef;border:1px solid #cce2fe;border-radius:5px}.even{background-color:#fff}.odd{background-color:#e3efff}span.expClpFlt a.btnExpClpFlt:hover{background-color:transparent !important}.ezActiveRow{background-color:#ffdc61 !important;color:inherit}.ezSelectedRow{background-color:#ffe4ab !important;color:inherit}.ezActiveCell{background-color:#fff !important;color:#000 !important;font-weight:bold}.ezETSelectedCell{background-color:#fff !important;font-weight:bold;color:#000 !important}
|
|
@ -1,6 +1 @@
|
||||||
/**
|
|
||||||
* tablefilter v0.4.40 by Max Guglielmi
|
|
||||||
* build date: 2017-02-11T12:40:33.756Z
|
|
||||||
* MIT License
|
|
||||||
*/
|
|
||||||
table.TF{padding:0;color:inherit;border-right:1px solid transparent;border-top:1px solid transparent;border-left:1px solid transparent;border-bottom:0;}table.TF th{margin:0;color:inherit;background-color:transparent;border-color:transparent;border-width:1px;border-style:solid;}table.TF th:last-child{border-right:1px solid transparent}table.TF td{margin:0;padding:5px;color:inherit;border-bottom:1px solid transparent;border-left:0;border-top:0;border-right:0}.fltrow{background-color:transparent;}.fltrow th,.fltrow td{padding:1px 3px 1px 3px;border-bottom:1px solid transparent !important;}.fltrow th:last-child,.fltrow td:last-child{border-right:1px solid transparent}.flt,select.flt,select.flt_multi,.flt_s,.single_flt,.div_checklist{border:1px solid #a4bed4}input.flt{width:99% !important}.inf{background-color:transparent;border:1px solid transparent;height:$min-height;color:inherit}div.tot,div.status{border-right:0 !important}.helpBtn:hover{background-color:transparent}input.reset{background:transparent url("images/icn_clear_filters.png") center center no-repeat !important}.nextPage{background:transparent url("images/btn_next_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.nextPage:hover{background:#f7f7f7 url("images/btn_next_page.gif") center center no-repeat !important;border:1px solid #f7f7f7 !important}.previousPage{background:transparent url("images/btn_prev_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.previousPage:hover{background:#f7f7f7 url("images/btn_prev_page.gif") center center no-repeat !important;border:1px solid #f7f7f7 !important}.firstPage{background:transparent url("images/btn_first_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.firstPage:hover{background:#f7f7f7 url("images/btn_first_page.gif") center center no-repeat !important;border:1px solid #f7f7f7 !important}.lastPage{background:transparent url("images/btn_last_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.lastPage:hover{background:#f7f7f7 url("images/btn_last_page.gif") center center no-repeat !important;border:1px solid #f7f7f7 !important}.activeHeader{background:#f7f7f7 !important;border:1px solid transparent;color:inherit !important}div.grd_Cont{-webkit-box-shadow:0 0 0 0 rgba(50,50,50,0.75);-moz-box-shadow:0 0 0 0 rgba(50,50,50,0.75);box-shadow:0 0 0 0 rgba(50,50,50,0.75);background-color:transparent;border:1px solid transparent;padding:0 !important;}div.grd_Cont .even{background-color:transparent}div.grd_Cont .odd{background-color:#f7f7f7}div.grd_headTblCont{background-color:transparent;border-bottom:none !important}div.grd_tblCont table{border-right:none !important}div.grd_tblCont table th,div.grd_headTblCont table th,div.grd_headTblCont table td{background:transparent;border-bottom:1px solid transparent;border-right:1px solid transparent !important;border-left:1px solid transparent;border-top:1px solid transparent}div.grd_tblCont table td{border-bottom:1px solid transparent;border-right:0 !important;border-left:0 !important;border-top:0 !important}.grd_inf{background-color:transparent;color:inherit;border-top:1px solid transparent;}.grd_inf a{text-decoration:none;font-weight:bold}.loader{background-color:#f7f7f7;border:1px solid #f7f7f7;border-radius:5px;color:#000;text-shadow:none}.even{background-color:transparent}.odd{background-color:#f7f7f7}span.expClpFlt a.btnExpClpFlt:hover{background-color:transparent !important}.ezActiveRow{background-color:#ccc !important;color:inherit}.ezSelectedRow{background-color:#ccc !important;color:inherit}.ezActiveCell{background-color:transparent;color:inherit;font-weight:bold}.ezETSelectedCell{background-color:transparent;font-weight:bold;color:inherit}
|
table.TF{padding:0;color:inherit;border-right:1px solid transparent;border-top:1px solid transparent;border-left:1px solid transparent;border-bottom:0;}table.TF th{margin:0;color:inherit;background-color:transparent;border-color:transparent;border-width:1px;border-style:solid;}table.TF th:last-child{border-right:1px solid transparent}table.TF td{margin:0;padding:5px;color:inherit;border-bottom:1px solid transparent;border-left:0;border-top:0;border-right:0}.fltrow{background-color:transparent;}.fltrow th,.fltrow td{padding:1px 3px 1px 3px;border-bottom:1px solid transparent !important;}.fltrow th:last-child,.fltrow td:last-child{border-right:1px solid transparent}.flt,select.flt,select.flt_multi,.flt_s,.single_flt,.div_checklist{border:1px solid #a4bed4}input.flt{width:99% !important}.inf{background-color:transparent;border:1px solid transparent;height:$min-height;color:inherit}div.tot,div.status{border-right:0 !important}.helpBtn:hover{background-color:transparent}input.reset{background:transparent url("images/icn_clear_filters.png") center center no-repeat !important}.nextPage{background:transparent url("images/btn_next_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.nextPage:hover{background:#f7f7f7 url("images/btn_next_page.gif") center center no-repeat !important;border:1px solid #f7f7f7 !important}.previousPage{background:transparent url("images/btn_prev_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.previousPage:hover{background:#f7f7f7 url("images/btn_prev_page.gif") center center no-repeat !important;border:1px solid #f7f7f7 !important}.firstPage{background:transparent url("images/btn_first_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.firstPage:hover{background:#f7f7f7 url("images/btn_first_page.gif") center center no-repeat !important;border:1px solid #f7f7f7 !important}.lastPage{background:transparent url("images/btn_last_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.lastPage:hover{background:#f7f7f7 url("images/btn_last_page.gif") center center no-repeat !important;border:1px solid #f7f7f7 !important}.activeHeader{background:#f7f7f7 !important;border:1px solid transparent;color:inherit !important}div.grd_Cont{-webkit-box-shadow:0 0 0 0 rgba(50,50,50,0.75);-moz-box-shadow:0 0 0 0 rgba(50,50,50,0.75);box-shadow:0 0 0 0 rgba(50,50,50,0.75);background-color:transparent;border:1px solid transparent;padding:0 !important;}div.grd_Cont .even{background-color:transparent}div.grd_Cont .odd{background-color:#f7f7f7}div.grd_headTblCont{background-color:transparent;border-bottom:none !important}div.grd_tblCont table{border-right:none !important}div.grd_tblCont table th,div.grd_headTblCont table th,div.grd_headTblCont table td{background:transparent;border-bottom:1px solid transparent;border-right:1px solid transparent !important;border-left:1px solid transparent;border-top:1px solid transparent}div.grd_tblCont table td{border-bottom:1px solid transparent;border-right:0 !important;border-left:0 !important;border-top:0 !important}.grd_inf{background-color:transparent;color:inherit;border-top:1px solid transparent;}.grd_inf a{text-decoration:none;font-weight:bold}.loader{background-color:#f7f7f7;border:1px solid #f7f7f7;border-radius:5px;color:#000;text-shadow:none}.even{background-color:transparent}.odd{background-color:#f7f7f7}span.expClpFlt a.btnExpClpFlt:hover{background-color:transparent !important}.ezActiveRow{background-color:#ccc !important;color:inherit}.ezSelectedRow{background-color:#ccc !important;color:inherit}.ezActiveCell{background-color:transparent;color:inherit;font-weight:bold}.ezETSelectedCell{background-color:transparent;font-weight:bold;color:inherit}
|
15
dist/tablefilter/tablefilter.js
vendored
15
dist/tablefilter/tablefilter.js
vendored
File diff suppressed because one or more lines are too long
1
dist/tablefilter/tablefilter.js.map
vendored
1
dist/tablefilter/tablefilter.js.map
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
dist/tablefilter/tf-1-2aa33b10e0e549020c12.js
vendored
Normal file
1
dist/tablefilter/tf-1-2aa33b10e0e549020c12.js
vendored
Normal file
File diff suppressed because one or more lines are too long
12319
package-lock.json
generated
Normal file
12319
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
62
package.json
62
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "tablefilter",
|
"name": "tablefilter",
|
||||||
"version": "0.4.40",
|
"version": "0.7.3",
|
||||||
"description": "A Javascript library making HTML tables filterable and a bit more",
|
"description": "A Javascript library making HTML tables filterable and a bit more",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"author": {
|
"author": {
|
||||||
|
@ -22,54 +22,58 @@
|
||||||
"pagination"
|
"pagination"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "grunt dev",
|
"lint": "eslint src/**/*.js test/*.js *.js",
|
||||||
"build": "grunt build",
|
"dev": "webpack --colors --config webpack.dev.config.js",
|
||||||
|
"build": "webpack --colors --config webpack.config.js",
|
||||||
|
"build:css": "stylus -c static/style/tablefilter.styl -o dist/tablefilter/style && stylus -c static/style/extensions -o dist/tablefilter/style && stylus -c static/style/themes/default -o dist/tablefilter/style/themes/default && stylus -c static/style/themes/mytheme -o dist/tablefilter/style/themes/mytheme && stylus -c static/style/themes/skyblue -o dist/tablefilter/style/themes/skyblue && stylus -c static/style/themes/transparent -o dist/tablefilter/style/themes/transparent",
|
||||||
"build:demos": "grunt build-demos",
|
"build:demos": "grunt build-demos",
|
||||||
"server": "grunt server",
|
"build:test": "webpack --colors --config webpack.test.config.js",
|
||||||
"eslint": "grunt eslint",
|
"server": "webpack-dev-server --colors --hot --config ./webpack.dev.config.js",
|
||||||
"test": "grunt test",
|
"test": "grunt test",
|
||||||
"codecov": "./node_modules/.bin/codecov",
|
"codecov": "./node_modules/.bin/codecov",
|
||||||
"esdoc": "grunt esdoc",
|
"esdoc": "esdoc",
|
||||||
"dist": "grunt",
|
"dist": "grunt",
|
||||||
"deploy": "grunt deploy",
|
"build:all": "grunt build-all",
|
||||||
"start": "npm run server"
|
"start": "npm run server"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"tag": "next"
|
"tag": "next"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-core": "^6.22.1",
|
"@babel/core": "7.10.0",
|
||||||
"babel-eslint": "7.1.1",
|
"@babel/preset-env": "7.10.0",
|
||||||
"babel-loader": "^6.2.9",
|
"babel-eslint": "10.1.0",
|
||||||
"babel-plugin-transform-es2015-classes": "^6.22.0",
|
"babel-loader": "^8.0.2",
|
||||||
"babel-preset-es2015": "^6.22.0",
|
"babel-preset-env": "1.7.0",
|
||||||
"clean-webpack-plugin": "^0.1.15",
|
"clean-webpack-plugin": "^3.0.0",
|
||||||
"codecov": "1.0.1",
|
"codecov": "3.7.1",
|
||||||
"diacritics": "1.3.0",
|
"diacritics": "1.3.0",
|
||||||
|
"esdoc": "1.1.0",
|
||||||
|
"esdoc-standard-plugin": "1.0.0",
|
||||||
|
"eslint": "6.5.0",
|
||||||
|
"format-number": "3.0.0",
|
||||||
"grunt": "^1.0.1",
|
"grunt": "^1.0.1",
|
||||||
"grunt-babel": "^6.0.0",
|
"grunt-cli": "1.3.2",
|
||||||
"grunt-cli": "1.2.0",
|
"grunt-contrib-clean": "^2.0.0",
|
||||||
"grunt-contrib-clean": "^1.0.0",
|
"grunt-contrib-connect": "^2.0.0",
|
||||||
"grunt-contrib-connect": "^1.0.2",
|
|
||||||
"grunt-contrib-copy": "^1.0.0",
|
"grunt-contrib-copy": "^1.0.0",
|
||||||
"grunt-contrib-stylus": "^1.2.0",
|
|
||||||
"grunt-contrib-watch": "^1.0.0",
|
"grunt-contrib-watch": "^1.0.0",
|
||||||
"grunt-esdoc": "^0.0.4",
|
"grunt-qunit-istanbul": "1.1.0",
|
||||||
"grunt-eslint": "19.0.0",
|
"grunt-shell": "3.0.0",
|
||||||
"grunt-gh-pages": "^2.0.0",
|
|
||||||
"grunt-qunit-istanbul": "1.0.0",
|
|
||||||
"grunt-string-replace": "^1.3.1",
|
"grunt-string-replace": "^1.3.1",
|
||||||
"grunt-webpack": "^2.0.1",
|
|
||||||
"isparta-loader": "2.0.0",
|
"isparta-loader": "2.0.0",
|
||||||
"script-loader": "^0.7.0",
|
"script-loader": "^0.7.0",
|
||||||
"string-replace-webpack-plugin": "^0.0.5",
|
"string-replace-webpack-plugin": "^0.1.3",
|
||||||
"sugar-date": "2.0.4",
|
"stylus": "^0.54.5",
|
||||||
"webpack": "^2.2.1",
|
"sugar-date": "2.0.6",
|
||||||
"webpack-dev-server": "^2.3.0"
|
"uglifyjs-webpack-plugin": "2.2.0",
|
||||||
|
"webpack": "^4.38.0",
|
||||||
|
"webpack-cli": "^3.0.8",
|
||||||
|
"webpack-dev-server": "^3.1.11"
|
||||||
},
|
},
|
||||||
"dependencies": {},
|
"dependencies": {},
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/koalyptus/TableFilter/issues"
|
"url": "https://github.com/koalyptus/TableFilter/issues"
|
||||||
},
|
},
|
||||||
"homepage": "http://koalyptus.github.io/TableFilter"
|
"homepage": "https://www.tablefilter.com"
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,4 +19,4 @@ export const has = (arr, val, caseSensitive) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
};
|
||||||
|
|
25
src/dom.js
25
src/dom.js
|
@ -18,7 +18,7 @@ export const getText = (node) => {
|
||||||
return trim(node.innerText);
|
return trim(node.innerText);
|
||||||
}
|
}
|
||||||
return trim(node.textContent);
|
return trim(node.textContent);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the first text node contained in the supplied node
|
* Returns the first text node contained in the supplied node
|
||||||
|
@ -32,11 +32,11 @@ export const getFirstTextNode = (node) => {
|
||||||
return n.data;
|
return n.data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an html element with given collection of attributes
|
* Creates an html element with given collection of attributes
|
||||||
* @param {String} tag a string of the html tag to create
|
* @param {String} tag html tag name
|
||||||
* @param {Array} an undetermined number of arrays containing the with 2
|
* @param {Array} an undetermined number of arrays containing the with 2
|
||||||
* items, the attribute name and its value ['id','myId']
|
* items, the attribute name and its value ['id','myId']
|
||||||
* @return {Object} created element
|
* @return {Object} created element
|
||||||
|
@ -55,9 +55,8 @@ export const createElm = (...args) => {
|
||||||
el.setAttribute(arg[0], arg[1]);
|
el.setAttribute(arg[0], arg[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return el;
|
return el;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes passed node from DOM
|
* Removes passed node from DOM
|
||||||
|
@ -88,7 +87,7 @@ export const hasClass = (ele, cls) => {
|
||||||
return ele.classList.contains(cls);
|
return ele.classList.contains(cls);
|
||||||
}
|
}
|
||||||
return ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
|
return ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the specified class to the passed element
|
* Adds the specified class to the passed element
|
||||||
|
@ -111,7 +110,7 @@ export const addClass = (ele, cls) => {
|
||||||
else if (!hasClass(ele, cls)) {
|
else if (!hasClass(ele, cls)) {
|
||||||
ele.className += ' ' + cls;
|
ele.className += ' ' + cls;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the specified class to the passed element
|
* Removes the specified class to the passed element
|
||||||
|
@ -129,7 +128,7 @@ export const removeClass = (ele, cls) => {
|
||||||
}
|
}
|
||||||
let reg = new RegExp('(\\s|^)' + cls + '(\\s|$)', 'g');
|
let reg = new RegExp('(\\s|^)' + cls + '(\\s|$)', 'g');
|
||||||
ele.className = ele.className.replace(reg, '');
|
ele.className = ele.className.replace(reg, '');
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates and returns an option element
|
* Creates and returns an option element
|
||||||
|
@ -145,23 +144,25 @@ export const createOpt = (text, value, isSel) => {
|
||||||
createElm('option', ['value', value]);
|
createElm('option', ['value', value]);
|
||||||
opt.appendChild(createText(text));
|
opt.appendChild(createText(text));
|
||||||
return opt;
|
return opt;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates and returns a checklist item
|
* Creates and returns a checklist item
|
||||||
* @param {String} id index of check item
|
* @param {String} id index of check item
|
||||||
* @param {String} chkValue check item value
|
* @param {String} chkValue check item value
|
||||||
* @param {String} labelText check item label text
|
* @param {String} labelText check item label text
|
||||||
|
* @param {Array} extraAttr array containing attribute name and its value
|
||||||
* @return {Object} li DOM element
|
* @return {Object} li DOM element
|
||||||
*/
|
*/
|
||||||
export const createCheckItem = (id, chkValue, labelText) => {
|
export const createCheckItem = (id, chkValue, labelText, extraAttr = []) => {
|
||||||
let li = createElm('li');
|
let li = createElm('li');
|
||||||
let label = createElm('label', ['for', id]);
|
let label = createElm('label', ['for', id]);
|
||||||
let check = createElm('input',
|
let check = createElm('input',
|
||||||
['id', id],
|
['id', id],
|
||||||
['name', id],
|
['name', id],
|
||||||
['type', 'checkbox'],
|
['type', 'checkbox'],
|
||||||
['value', chkValue]
|
['value', chkValue],
|
||||||
|
extraAttr
|
||||||
);
|
);
|
||||||
label.appendChild(check);
|
label.appendChild(check);
|
||||||
label.appendChild(createText(labelText));
|
label.appendChild(createText(labelText));
|
||||||
|
@ -169,7 +170,7 @@ export const createCheckItem = (id, chkValue, labelText) => {
|
||||||
li.label = label;
|
li.label = label;
|
||||||
li.check = check;
|
li.check = check;
|
||||||
return li;
|
return li;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the element matching the supplied Id
|
* Returns the element matching the supplied Id
|
||||||
|
|
23
src/event.js
23
src/event.js
|
@ -99,3 +99,26 @@ export const keyCode = (evt) => {
|
||||||
return evt.charCode ? evt.charCode :
|
return evt.charCode ? evt.charCode :
|
||||||
(evt.keyCode ? evt.keyCode : (evt.which ? evt.which : 0));
|
(evt.keyCode ? evt.keyCode : (evt.which ? evt.which : 0));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check code of pressed key is one of the expected key codes
|
||||||
|
*
|
||||||
|
* @param {Event} evt key event
|
||||||
|
* @param {Array} keyCodes list of keycodes to check
|
||||||
|
*/
|
||||||
|
export const isKeyPressed = (evt, keyCodes = []) => {
|
||||||
|
return keyCodes.indexOf(keyCode(evt)) !== -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bind passed function to passed scope
|
||||||
|
* @param {Function} fn function
|
||||||
|
* @param {Object} scope object instance
|
||||||
|
*/
|
||||||
|
export function bound(fn, scope) {
|
||||||
|
let boundFnName = `${fn.name}_bound`;
|
||||||
|
if (!scope[boundFnName]) {
|
||||||
|
scope[boundFnName] = fn.bind(scope);
|
||||||
|
}
|
||||||
|
return scope[boundFnName];
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import {Feature} from '../../feature';
|
import {Feature} from '../../feature';
|
||||||
import {tag} from '../../dom';
|
import {tag} from '../../dom';
|
||||||
import {INPUT} from '../../const';
|
import {INPUT} from '../../const';
|
||||||
|
import {defaultsStr} from '../../settings';
|
||||||
import {root} from '../../root';
|
import {root} from '../../root';
|
||||||
|
|
||||||
const INSTANTIATION_ERROR = `Failed to instantiate EditTable object.
|
const INSTANTIATION_ERROR = `Failed to instantiate EditTable object.
|
||||||
|
@ -20,19 +21,19 @@ export default class AdapterEzEditTable extends Feature {
|
||||||
* @param {Object} cfg Configuration options for ezEditTable library
|
* @param {Object} cfg Configuration options for ezEditTable library
|
||||||
*/
|
*/
|
||||||
constructor(tf, cfg) {
|
constructor(tf, cfg) {
|
||||||
super(tf, cfg.name);
|
super(tf, AdapterEzEditTable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module description
|
* Module description
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.desc = cfg.description || 'ezEditTable adapter';
|
this.desc = defaultsStr(cfg.description, 'ezEditTable adapter');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filename of ezEditTable library
|
* Filename of ezEditTable library
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.filename = cfg.filename || 'ezEditTable.js';
|
this.filename = defaultsStr(cfg.filename, 'ezEditTable.js');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Path to ezEditTable library
|
* Path to ezEditTable library
|
||||||
|
@ -50,13 +51,15 @@ export default class AdapterEzEditTable extends Feature {
|
||||||
* Path to ezEditTable stylesheet
|
* Path to ezEditTable stylesheet
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.stylesheet = cfg.stylesheet || this.vendorPath + 'ezEditTable.css';
|
this.stylesheet = defaultsStr(cfg.stylesheet,
|
||||||
|
this.vendorPath + 'ezEditTable.css');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name of ezEditTable stylesheet
|
* Name of ezEditTable stylesheet
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.stylesheetName = cfg.stylesheet_name || 'ezEditTableCss';
|
this.stylesheetName = defaultsStr(cfg.stylesheet_name,
|
||||||
|
'ezEditTableCss');
|
||||||
|
|
||||||
// Enable the ezEditTable's scroll into view behaviour if grid layout on
|
// Enable the ezEditTable's scroll into view behaviour if grid layout on
|
||||||
cfg.scroll_into_view = cfg.scroll_into_view === false ?
|
cfg.scroll_into_view = cfg.scroll_into_view === false ?
|
||||||
|
@ -117,7 +120,7 @@ export default class AdapterEzEditTable extends Feature {
|
||||||
//start row for EditTable constructor needs to be calculated
|
//start row for EditTable constructor needs to be calculated
|
||||||
let startRow,
|
let startRow,
|
||||||
cfg = this.cfg,
|
cfg = this.cfg,
|
||||||
thead = tag(tf.tbl, 'thead');
|
thead = tag(tf.dom(), 'thead');
|
||||||
|
|
||||||
//if thead exists and startRow not specified, startRow is calculated
|
//if thead exists and startRow not specified, startRow is calculated
|
||||||
//automatically by EditTable
|
//automatically by EditTable
|
||||||
|
@ -158,7 +161,7 @@ export default class AdapterEzEditTable extends Feature {
|
||||||
et.ClearSelections();
|
et.ClearSelections();
|
||||||
/* eslint-enable */
|
/* eslint-enable */
|
||||||
let cellIndex = selectedElm.cellIndex,
|
let cellIndex = selectedElm.cellIndex,
|
||||||
row = tf.tbl.rows[nextRowIndex];
|
row = tf.dom().rows[nextRowIndex];
|
||||||
if (et.defaultSelection === 'both') {
|
if (et.defaultSelection === 'both') {
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
slc.SelectRowByIndex(nextRowIndex);
|
slc.SelectRowByIndex(nextRowIndex);
|
||||||
|
@ -172,7 +175,7 @@ export default class AdapterEzEditTable extends Feature {
|
||||||
}
|
}
|
||||||
//Table is filtered
|
//Table is filtered
|
||||||
if (tf.validRowsIndex.length !== tf.getRowsNb()) {
|
if (tf.validRowsIndex.length !== tf.getRowsNb()) {
|
||||||
let r = tf.tbl.rows[nextRowIndex];
|
let r = tf.dom().rows[nextRowIndex];
|
||||||
if (r) {
|
if (r) {
|
||||||
r.scrollIntoView(false);
|
r.scrollIntoView(false);
|
||||||
}
|
}
|
||||||
|
@ -208,7 +211,7 @@ export default class AdapterEzEditTable extends Feature {
|
||||||
paging = tf.feature('paging'),
|
paging = tf.feature('paging'),
|
||||||
//pgup/pgdown keys
|
//pgup/pgdown keys
|
||||||
d = keyCode === 34 || keyCode === 33 ?
|
d = keyCode === 34 || keyCode === 33 ?
|
||||||
(paging && paging.pagingLength || et.nbRowsPerPage) :
|
(paging && paging.pageLength || et.nbRowsPerPage) :
|
||||||
1;
|
1;
|
||||||
|
|
||||||
//If next row is not valid, next valid filtered row needs to be
|
//If next row is not valid, next valid filtered row needs to be
|
||||||
|
@ -278,11 +281,11 @@ export default class AdapterEzEditTable extends Feature {
|
||||||
if (tf.feature('paging').nbPages > 1) {
|
if (tf.feature('paging').nbPages > 1) {
|
||||||
let paging = tf.feature('paging');
|
let paging = tf.feature('paging');
|
||||||
//page length is re-assigned in case it has changed
|
//page length is re-assigned in case it has changed
|
||||||
et.nbRowsPerPage = paging.pagingLength;
|
et.nbRowsPerPage = paging.pageLength;
|
||||||
let validIndexes = tf.validRowsIndex,
|
let validIndexes = tf.validRowsIndex,
|
||||||
validIdxLen = validIndexes.length,
|
validIdxLen = validIndexes.length,
|
||||||
pagingEndRow = parseInt(paging.startPagingRow, 10) +
|
pagingEndRow = parseInt(paging.startPagingRow, 10) +
|
||||||
parseInt(paging.pagingLength, 10);
|
parseInt(paging.pageLength, 10);
|
||||||
let rowIndex = row.rowIndex;
|
let rowIndex = row.rowIndex;
|
||||||
|
|
||||||
if ((rowIndex === validIndexes[validIdxLen - 1]) &&
|
if ((rowIndex === validIndexes[validIdxLen - 1]) &&
|
||||||
|
@ -502,3 +505,5 @@ export default class AdapterEzEditTable extends Feature {
|
||||||
this.initialized = false;
|
this.initialized = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AdapterEzEditTable.meta = {altName: 'advancedGrid'};
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
import {Feature} from '../../feature';
|
import {Feature} from '../../feature';
|
||||||
import {createText, elm} from '../../dom';
|
import {createText, elm} from '../../dom';
|
||||||
import {isArray, isFn, isUndef, isEmpty, EMPTY_FN} from '../../types';
|
import {isArray, isEmpty, EMPTY_FN} from '../../types';
|
||||||
import {numSortAsc} from '../../sort';
|
import {numSortAsc} from '../../sort';
|
||||||
|
import {FORMATTED_NUMBER} from '../../const';
|
||||||
|
import formatNumber from 'format-number';
|
||||||
|
import {defaultsFn, defaultsArr} from '../../settings';
|
||||||
|
import {bound} from '../../event';
|
||||||
|
|
||||||
const EVENTS = [
|
const EVENTS = [
|
||||||
'after-filtering',
|
'after-filtering',
|
||||||
|
@ -29,21 +33,19 @@ export default class ColOps extends Feature {
|
||||||
* @param {Object} opts Configuration object
|
* @param {Object} opts Configuration object
|
||||||
*/
|
*/
|
||||||
constructor(tf, opts) {
|
constructor(tf, opts) {
|
||||||
super(tf, opts.name);
|
super(tf, ColOps);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired before columns operations start
|
* Callback fired before columns operations start
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onBeforeOperation = isFn(opts.on_before_operation) ?
|
this.onBeforeOperation = defaultsFn(opts.on_before_operation, EMPTY_FN);
|
||||||
opts.on_before_operation : EMPTY_FN;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired after columns operations are completed
|
* Callback fired after columns operations are completed
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onAfterOperation = isFn(opts.on_after_operation) ?
|
this.onAfterOperation = defaultsFn(opts.on_after_operation, EMPTY_FN);
|
||||||
opts.on_after_operation : EMPTY_FN;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration options
|
* Configuration options
|
||||||
|
@ -55,46 +57,53 @@ export default class ColOps extends Feature {
|
||||||
* List of DOM element IDs containing column's calculation result
|
* List of DOM element IDs containing column's calculation result
|
||||||
* @type {Array}
|
* @type {Array}
|
||||||
*/
|
*/
|
||||||
this.labelIds = opts.id || [];
|
this.labelIds = defaultsArr(opts.id, []);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of columns' indexes for calculations
|
* List of columns' indexes for calculations
|
||||||
* @type {Array}
|
* @type {Array}
|
||||||
*/
|
*/
|
||||||
this.colIndexes = opts.col || [];
|
this.colIndexes = defaultsArr(opts.col, []);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of operations - possible values: 'sum', 'mean', 'min', 'max',
|
* List of operations - possible values: 'sum', 'mean', 'min', 'max',
|
||||||
* 'median', 'q1', 'q3'
|
* 'median', 'q1', 'q3'
|
||||||
* @type {Array}
|
* @type {Array}
|
||||||
*/
|
*/
|
||||||
this.operations = opts.operation || [];
|
this.operations = defaultsArr(opts.operation, []);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of write methods used to write the result - possible values:
|
* List of write methods used to write the result - possible values:
|
||||||
* 'innerHTML', 'setValue', 'createTextNode'
|
* 'innerHTML', 'setValue', 'createTextNode'
|
||||||
* @type {Array}
|
* @type {Array}
|
||||||
*/
|
*/
|
||||||
this.outputTypes = opts.write_method || [];
|
this.outputTypes = defaultsArr(opts.write_method, []);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of format objects used for formatting the result -
|
||||||
|
* refer to https://github.com/componitable/format-number to check
|
||||||
|
* configuration options
|
||||||
|
* @type {Array}
|
||||||
|
*/
|
||||||
|
this.formatResults = defaultsArr(opts.format_result, []);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of row indexes displaying the results
|
* List of row indexes displaying the results
|
||||||
* @type {Array}
|
* @type {Array}
|
||||||
*/
|
*/
|
||||||
this.totRowIndexes = opts.tot_row_index || [];
|
this.totRowIndexes = defaultsArr(opts.tot_row_index, []);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of row indexes excluded from calculations
|
* List of row indexes excluded from calculations
|
||||||
* @type {Array}
|
* @type {Array}
|
||||||
*/
|
*/
|
||||||
this.excludeRows = opts.exclude_row || [];
|
this.excludeRows = defaultsArr(opts.exclude_row, []);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of decimal precision for calculation results
|
* List of decimal precision for calculation results
|
||||||
* @type {Array}
|
* @type {Array}
|
||||||
*/
|
*/
|
||||||
this.decimalPrecisions = isUndef(opts.decimal_precision) ?
|
this.decimalPrecisions = defaultsArr(opts.decimal_precision, 2);
|
||||||
2 : opts.decimal_precision;
|
|
||||||
|
|
||||||
this.enable();
|
this.enable();
|
||||||
}
|
}
|
||||||
|
@ -107,7 +116,7 @@ export default class ColOps extends Feature {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// subscribe to events
|
// subscribe to events
|
||||||
this.emitter.on(EVENTS, () => this.calcAll());
|
this.emitter.on(EVENTS, bound(this.calcAll, this));
|
||||||
|
|
||||||
this.calcAll();
|
this.calcAll();
|
||||||
|
|
||||||
|
@ -140,13 +149,9 @@ export default class ColOps extends Feature {
|
||||||
this.onBeforeOperation(tf, this);
|
this.onBeforeOperation(tf, this);
|
||||||
this.emitter.emit('before-column-operation', tf, this);
|
this.emitter.emit('before-column-operation', tf, this);
|
||||||
|
|
||||||
let colIndexes = this.colIndexes,
|
let { colIndexes, operations: colOperations, outputTypes,
|
||||||
colOperations = this.operations,
|
totRowIndexes, excludeRows, formatResults,
|
||||||
outputTypes = this.outputTypes,
|
decimalPrecisions } = this;
|
||||||
totRowIndexes = this.totRowIndexes,
|
|
||||||
excludeRows = this.excludeRows,
|
|
||||||
decimalPrecisions = isUndef(this.decimalPrecisions) ?
|
|
||||||
2 : this.decimalPrecisions;
|
|
||||||
|
|
||||||
//nuovella: determine unique list of columns to operate on
|
//nuovella: determine unique list of columns to operate on
|
||||||
let uIndexes = [];
|
let uIndexes = [];
|
||||||
|
@ -157,7 +162,7 @@ export default class ColOps extends Feature {
|
||||||
});
|
});
|
||||||
|
|
||||||
let nbCols = uIndexes.length,
|
let nbCols = uIndexes.length,
|
||||||
rows = tf.tbl.rows,
|
rows = tf.dom().rows,
|
||||||
colValues = [];
|
colValues = [];
|
||||||
|
|
||||||
for (let u = 0; u < nbCols; u++) {
|
for (let u = 0; u < nbCols; u++) {
|
||||||
|
@ -165,7 +170,7 @@ export default class ColOps extends Feature {
|
||||||
//use uIndexes because we only want to pass through this loop
|
//use uIndexes because we only want to pass through this loop
|
||||||
//once for each column get the values in this unique column
|
//once for each column get the values in this unique column
|
||||||
colValues.push(
|
colValues.push(
|
||||||
tf.getFilteredDataCol(uIndexes[u], false, true, excludeRows)
|
tf.getVisibleColumnData(uIndexes[u], false, excludeRows)
|
||||||
);
|
);
|
||||||
|
|
||||||
let curValues = colValues[u];
|
let curValues = colValues[u];
|
||||||
|
@ -176,6 +181,7 @@ export default class ColOps extends Feature {
|
||||||
precisions = [],
|
precisions = [],
|
||||||
labels = [],
|
labels = [],
|
||||||
writeType,
|
writeType,
|
||||||
|
formatResult = [],
|
||||||
idx = 0;
|
idx = 0;
|
||||||
|
|
||||||
for (let k = 0; k < colIndexes.length; k++) {
|
for (let k = 0; k < colIndexes.length; k++) {
|
||||||
|
@ -186,6 +192,8 @@ export default class ColOps extends Feature {
|
||||||
precisions[idx] = decimalPrecisions[k];
|
precisions[idx] = decimalPrecisions[k];
|
||||||
labels[idx] = this.labelIds[k];
|
labels[idx] = this.labelIds[k];
|
||||||
writeType = isArray(outputTypes) ? outputTypes[k] : null;
|
writeType = isArray(outputTypes) ? outputTypes[k] : null;
|
||||||
|
formatResult[idx] =
|
||||||
|
this.configureFormat(uIndexes[u], formatResults[k]);
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +227,8 @@ export default class ColOps extends Feature {
|
||||||
result,
|
result,
|
||||||
labels[i],
|
labels[i],
|
||||||
writeType,
|
writeType,
|
||||||
precisions[i]
|
precisions[i],
|
||||||
|
formatResult[i]
|
||||||
);
|
);
|
||||||
|
|
||||||
}//for i
|
}//for i
|
||||||
|
@ -245,8 +254,8 @@ export default class ColOps extends Feature {
|
||||||
*/
|
*/
|
||||||
columnCalc(colIndex, operation = SUM, precision) {
|
columnCalc(colIndex, operation = SUM, precision) {
|
||||||
let excludeRows = this.excludeRows || [];
|
let excludeRows = this.excludeRows || [];
|
||||||
let colValues =
|
let colValues = tf.getVisibleColumnData(colIndex, false, excludeRows);
|
||||||
this.tf.getFilteredDataCol(colIndex, false, true, excludeRows);
|
|
||||||
return Number(this.calc(colValues, operation, precision));
|
return Number(this.calc(colValues, operation, precision));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,7 +411,8 @@ export default class ColOps extends Feature {
|
||||||
* @param {Number} [precision=2] Applied decimal precision
|
* @param {Number} [precision=2] Applied decimal precision
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
writeResult(result = 0, label, writeType = 'innerhtml', precision = 2) {
|
writeResult(result = 0, label, writeType = 'innerhtml',
|
||||||
|
precision = 2, format = {}) {
|
||||||
let labelElm = elm(label);
|
let labelElm = elm(label);
|
||||||
|
|
||||||
if (!labelElm) {
|
if (!labelElm) {
|
||||||
|
@ -412,6 +422,8 @@ export default class ColOps extends Feature {
|
||||||
result = result.toFixed(precision);
|
result = result.toFixed(precision);
|
||||||
if (isNaN(result) || !isFinite(result)) {
|
if (isNaN(result) || !isFinite(result)) {
|
||||||
result = '';
|
result = '';
|
||||||
|
} else {
|
||||||
|
result = formatNumber(format)(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (writeType.toLowerCase()) {
|
switch (writeType.toLowerCase()) {
|
||||||
|
@ -429,13 +441,38 @@ export default class ColOps extends Feature {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure the format options used to format the operation result based
|
||||||
|
* on column type.
|
||||||
|
* @param {Number} colIndex Column index
|
||||||
|
* @param {Object} [format={}] Format object
|
||||||
|
* @returns {Object}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
configureFormat(colIndex, format = {}) {
|
||||||
|
let tf = this.tf;
|
||||||
|
if (tf.hasType(colIndex, [FORMATTED_NUMBER])) {
|
||||||
|
let colType = tf.colTypes[colIndex];
|
||||||
|
if (colType.decimal && !format.decimal) {
|
||||||
|
format.decimal = colType.decimal;
|
||||||
|
}
|
||||||
|
if (colType.thousands && !format.integerSeparator) {
|
||||||
|
format.integerSeparator = colType.thousands;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
format.decimal = format.decimal || '';
|
||||||
|
format.integerSeparator = format.integerSeparator || '';
|
||||||
|
}
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
/** Remove extension */
|
/** Remove extension */
|
||||||
destroy() {
|
destroy() {
|
||||||
if (!this.initialized) {
|
if (!this.initialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// unsubscribe to events
|
// unsubscribe to events
|
||||||
this.emitter.off(EVENTS, () => this.calcAll());
|
this.emitter.off(EVENTS, bound(this.calcAll, this));
|
||||||
|
|
||||||
this.initialized = false;
|
this.initialized = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
import {Feature} from '../../feature';
|
import {Feature} from '../../feature';
|
||||||
import {
|
import {
|
||||||
addClass, removeClass, createCheckItem, createElm, elm, removeElm,
|
addClass, removeClass, createCheckItem, createElm, elm, removeElm,
|
||||||
getText
|
getText, tag
|
||||||
} from '../../dom';
|
} from '../../dom';
|
||||||
import {isFn, EMPTY_FN} from '../../types';
|
import {isUndef, EMPTY_FN, isNull} from '../../types';
|
||||||
import {addEvt, targetEvt, removeEvt} from '../../event';
|
import {addEvt, targetEvt, removeEvt} from '../../event';
|
||||||
import {root} from '../../root';
|
import {root} from '../../root';
|
||||||
|
import {NONE} from '../../const';
|
||||||
|
import {
|
||||||
|
defaultsBool, defaultsStr, defaultsFn, defaultsNb, defaultsArr
|
||||||
|
} from '../../settings';
|
||||||
|
import {RIGHT} from '../../modules/toolbar';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Columns Visibility extension
|
* Columns Visibility extension
|
||||||
|
@ -18,7 +23,7 @@ export default class ColsVisibility extends Feature {
|
||||||
* @param {Object} Configuration object
|
* @param {Object} Configuration object
|
||||||
*/
|
*/
|
||||||
constructor(tf, f) {
|
constructor(tf, f) {
|
||||||
super(tf, f.name);
|
super(tf, ColsVisibility);
|
||||||
|
|
||||||
// Configuration object
|
// Configuration object
|
||||||
let cfg = this.config;
|
let cfg = this.config;
|
||||||
|
@ -33,7 +38,7 @@ export default class ColsVisibility extends Feature {
|
||||||
* Module description
|
* Module description
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.desc = f.description || 'Columns visibility manager';
|
this.desc = defaultsStr(f.description, 'Columns visibility manager');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* show/hide columns container element
|
* show/hide columns container element
|
||||||
|
@ -57,13 +62,13 @@ export default class ColsVisibility extends Feature {
|
||||||
* Enable tick to hide a column, defaults to true
|
* Enable tick to hide a column, defaults to true
|
||||||
* @type {Boolean}
|
* @type {Boolean}
|
||||||
*/
|
*/
|
||||||
this.tickToHide = f.tick_to_hide === false ? false : true;
|
this.tickToHide = defaultsBool(f.tick_to_hide, true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable columns manager UI, defaults to true
|
* Enable columns manager UI, defaults to true
|
||||||
* @type {Boolean}
|
* @type {Boolean}
|
||||||
*/
|
*/
|
||||||
this.manager = f.manager === false ? false : true;
|
this.manager = defaultsBool(f.manager, true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Headers HTML table reference only if headers are external
|
* Headers HTML table reference only if headers are external
|
||||||
|
@ -75,112 +80,115 @@ export default class ColsVisibility extends Feature {
|
||||||
* Headers row index only if headers are external
|
* Headers row index only if headers are external
|
||||||
* @type {Number}
|
* @type {Number}
|
||||||
*/
|
*/
|
||||||
this.headersIndex = f.headers_index || 1;
|
this.headersIndex = defaultsNb(f.headers_index, 1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID of main container element
|
* ID of main container element
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.contElTgtId = f.container_target_id || null;
|
this.contElTgtId = defaultsStr(f.container_target_id, null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Alternative text for column headers in column manager UI
|
* Alternative text for column headers in column manager UI
|
||||||
* @type {Array}
|
* @type {Array}
|
||||||
*/
|
*/
|
||||||
this.headersText = f.headers_text || null;
|
this.headersText = defaultsArr(f.headers_text, []);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID of button's container element
|
* ID of button's container element
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.btnTgtId = f.btn_target_id || null;
|
this.btnTgtId = defaultsStr(f.btn_target_id, null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Button's text, defaults to Columns▼
|
* Button's text, defaults to Columns▼
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.btnText = f.btn_text || 'Columns▼';
|
this.btnText = defaultsStr(f.btn_text, 'Columns▼');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Button's inner HTML
|
* Button's inner HTML
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.btnHtml = f.btn_html || null;
|
this.btnHtml = defaultsStr(f.btn_html, null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for button
|
* Css class for button
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.btnCssClass = f.btn_css_class || 'colVis';
|
this.btnCssClass = defaultsStr(f.btn_css_class, 'colVis');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Columns manager UI close link text, defaults to 'Close'
|
* Columns manager UI close link text, defaults to 'Close'
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.btnCloseText = f.btn_close_text || 'Close';
|
this.btnCloseText = defaultsStr(f.btn_close_text, 'Close');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Columns manager UI close link HTML
|
* Columns manager UI close link HTML
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.btnCloseHtml = f.btn_close_html || null;
|
this.btnCloseHtml = defaultsStr(f.btn_close_html, null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css for columns manager UI close link
|
* Css for columns manager UI close link
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.btnCloseCssClass = f.btn_close_css_class || this.btnCssClass;
|
this.btnCloseCssClass = defaultsStr(f.btn_close_css_class,
|
||||||
|
this.btnCssClass);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extension's stylesheet filename
|
* Extension's stylesheet filename
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.stylesheet = f.stylesheet || 'colsVisibility.css';
|
this.stylesheet = defaultsStr(f.stylesheet, 'colsVisibility.css');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css for columns manager UI span
|
* Css for columns manager UI span
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.spanCssClass = f.span_css_class || 'colVisSpan';
|
this.spanCssClass = defaultsStr(f.span_css_class, 'colVisSpan');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css for columns manager UI main container
|
* Css for columns manager UI main container
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.contCssClass = f.cont_css_class || 'colVisCont';
|
this.contCssClass = defaultsStr(f.cont_css_class, 'colVisCont');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css for columns manager UI checklist (ul)
|
* Css for columns manager UI checklist (ul)
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.listCssClass = cfg.list_css_class || 'cols_checklist';
|
this.listCssClass = defaultsStr(cfg.list_css_class, 'cols_checklist');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css for columns manager UI checklist item (li)
|
* Css for columns manager UI checklist item (li)
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.listItemCssClass = cfg.checklist_item_css_class ||
|
this.listItemCssClass = defaultsStr(cfg.checklist_item_css_class,
|
||||||
'cols_checklist_item';
|
'cols_checklist_item');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css for columns manager UI checklist item selected state (li)
|
* Css for columns manager UI checklist item selected state (li)
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.listSlcItemCssClass = cfg.checklist_selected_item_css_class ||
|
this.listSlcItemCssClass = defaultsStr(
|
||||||
'cols_checklist_slc_item';
|
cfg.checklist_selected_item_css_class,
|
||||||
|
'cols_checklist_slc_item'
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Text preceding the columns list, defaults to 'Hide' or 'Show'
|
* Text preceding the columns list, defaults to 'Hide' or 'Show'
|
||||||
* depending on tick mode (tick_to_hide option)
|
* depending on tick mode (tick_to_hide option)
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.text = f.text || (this.tickToHide ? 'Hide: ' : 'Show: ');
|
this.text = defaultsStr(f.text, this.tickToHide ? 'Hide: ' : 'Show: ');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of columns indexes to be hidden at initialization
|
* List of columns indexes to be hidden at initialization
|
||||||
* @type {Array}
|
* @type {Array}
|
||||||
*/
|
*/
|
||||||
this.atStart = f.at_start || [];
|
this.atStart = defaultsArr(f.at_start, []);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable hover behaviour on columns manager button/link
|
* Enable hover behaviour on columns manager button/link
|
||||||
|
@ -198,7 +206,13 @@ export default class ColsVisibility extends Feature {
|
||||||
* Text for select all option, defaults to 'Select all:'
|
* Text for select all option, defaults to 'Select all:'
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.tickAllText = f.tick_all_text || 'Select all:';
|
this.tickAllText = defaultsStr(f.tick_all_text, 'Select all:');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default position in toolbar ('left'|'center'|'right')
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
this.toolbarPosition = defaultsStr(f.toolbar_position, RIGHT);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of indexes of hidden columns
|
* List of indexes of hidden columns
|
||||||
|
@ -216,73 +230,66 @@ export default class ColsVisibility extends Feature {
|
||||||
* Callback fired when the extension is initialized
|
* Callback fired when the extension is initialized
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onLoaded = isFn(f.on_loaded) ? f.on_loaded : EMPTY_FN;
|
this.onLoaded = defaultsFn(f.on_loaded, EMPTY_FN);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired before the columns manager is opened
|
* Callback fired before the columns manager is opened
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onBeforeOpen = isFn(f.on_before_open) ?
|
this.onBeforeOpen = defaultsFn(f.on_before_open, EMPTY_FN);
|
||||||
f.on_before_open : EMPTY_FN;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired after the columns manager is opened
|
* Callback fired after the columns manager is opened
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onAfterOpen = isFn(f.on_after_open) ? f.on_after_open : EMPTY_FN;
|
this.onAfterOpen = defaultsFn(f.on_after_open, EMPTY_FN);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired before the columns manager is closed
|
* Callback fired before the columns manager is closed
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onBeforeClose = isFn(f.on_before_close) ?
|
this.onBeforeClose = defaultsFn(f.on_before_close, EMPTY_FN);
|
||||||
f.on_before_close : EMPTY_FN;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired after the columns manager is closed
|
* Callback fired after the columns manager is closed
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onAfterClose = isFn(f.on_after_close) ?
|
this.onAfterClose = defaultsFn(f.on_after_close, EMPTY_FN);
|
||||||
f.on_after_close : EMPTY_FN;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired before a column is hidden
|
* Callback fired before a column is hidden
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onBeforeColHidden = isFn(f.on_before_col_hidden) ?
|
this.onBeforeColHidden = defaultsFn(f.on_before_col_hidden, EMPTY_FN);
|
||||||
f.on_before_col_hidden : EMPTY_FN;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired after a column is hidden
|
* Callback fired after a column is hidden
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onAfterColHidden = isFn(f.on_after_col_hidden) ?
|
this.onAfterColHidden = defaultsFn(f.on_after_col_hidden, EMPTY_FN);
|
||||||
f.on_after_col_hidden : EMPTY_FN;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired before a column is displayed
|
* Callback fired before a column is displayed
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onBeforeColDisplayed = isFn(f.on_before_col_displayed) ?
|
this.onBeforeColDisplayed = defaultsFn(f.on_before_col_displayed,
|
||||||
f.on_before_col_displayed : EMPTY_FN;
|
EMPTY_FN);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired after a column is displayed
|
* Callback fired after a column is displayed
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onAfterColDisplayed = isFn(f.on_after_col_displayed) ?
|
this.onAfterColDisplayed = defaultsFn(f.on_after_col_displayed,
|
||||||
f.on_after_col_displayed : EMPTY_FN;
|
EMPTY_FN);
|
||||||
|
|
||||||
//Grid layout support
|
//Grid layout support
|
||||||
if (tf.gridLayout) {
|
if (tf.gridLayout) {
|
||||||
this.headersTbl = tf.feature('gridLayout').headTbl; //headers table
|
this.headersTbl = tf.feature('gridLayout').headTbl; //headers table
|
||||||
this.headersIndex = 0; //headers index
|
this.headersIndex = 0; //headers index
|
||||||
this.onAfterColDisplayed = function () { };
|
|
||||||
this.onAfterColHidden = function () { };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Loads extension stylesheet
|
//Loads extension stylesheet
|
||||||
tf.import(f.name + 'Style', tf.stylePath + this.stylesheet, null,
|
tf.import(f.name + 'Style', tf.getStylePath() + this.stylesheet, null,
|
||||||
'link');
|
'link');
|
||||||
|
|
||||||
this.enable();
|
this.enable();
|
||||||
|
@ -324,7 +331,7 @@ export default class ColsVisibility extends Feature {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.contEl.style.display = contDisplay === 'inline' ?
|
this.contEl.style.display = contDisplay === 'inline' ?
|
||||||
'none' : 'inline';
|
NONE : 'inline';
|
||||||
|
|
||||||
if (contDisplay !== 'inline') {
|
if (contDisplay !== 'inline') {
|
||||||
this.onAfterOpen(this);
|
this.onAfterOpen(this);
|
||||||
|
@ -369,6 +376,9 @@ export default class ColsVisibility extends Feature {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.emitter.emit('initializing-extension', this,
|
||||||
|
!isNull(this.btnTgtId));
|
||||||
|
|
||||||
this.emitter.on(['hide-column'],
|
this.emitter.on(['hide-column'],
|
||||||
(tf, colIndex) => this.hideCol(colIndex));
|
(tf, colIndex) => this.hideCol(colIndex));
|
||||||
|
|
||||||
|
@ -381,6 +391,7 @@ export default class ColsVisibility extends Feature {
|
||||||
this.boundMouseup = this.onMouseup.bind(this);
|
this.boundMouseup = this.onMouseup.bind(this);
|
||||||
|
|
||||||
this.emitter.emit('columns-visibility-initialized', this.tf, this);
|
this.emitter.emit('columns-visibility-initialized', this.tf, this);
|
||||||
|
this.emitter.emit('extension-initialized', this);
|
||||||
|
|
||||||
// Hide columns at start at very end of initialization, do not move
|
// Hide columns at start at very end of initialization, do not move
|
||||||
// as order is important
|
// as order is important
|
||||||
|
@ -398,11 +409,10 @@ export default class ColsVisibility extends Feature {
|
||||||
let span = createElm('span');
|
let span = createElm('span');
|
||||||
span.className = this.spanCssClass;
|
span.className = this.spanCssClass;
|
||||||
|
|
||||||
//Container element (rdiv or custom element)
|
// Container element (rdiv or custom element)
|
||||||
if (!this.btnTgtId) {
|
let targetEl = !this.btnTgtId ?
|
||||||
tf.setToolbar();
|
tf.feature('toolbar').container(this.toolbarPosition) :
|
||||||
}
|
elm(this.btnTgtId);
|
||||||
let targetEl = !this.btnTgtId ? tf.rDiv : elm(this.btnTgtId);
|
|
||||||
|
|
||||||
if (!this.btnTgtId) {
|
if (!this.btnTgtId) {
|
||||||
let firstChild = targetEl.firstChild;
|
let firstChild = targetEl.firstChild;
|
||||||
|
@ -423,7 +433,7 @@ export default class ColsVisibility extends Feature {
|
||||||
} else {
|
} else {
|
||||||
addEvt(btn, 'mouseover', (evt) => this.toggle(evt));
|
addEvt(btn, 'mouseover', (evt) => this.toggle(evt));
|
||||||
}
|
}
|
||||||
} else { //Custom html
|
} else { // Custom html
|
||||||
span.innerHTML = this.btnHtml;
|
span.innerHTML = this.btnHtml;
|
||||||
let colVisEl = span.firstChild;
|
let colVisEl = span.firstChild;
|
||||||
if (!this.enableHover) {
|
if (!this.enableHover) {
|
||||||
|
@ -459,7 +469,7 @@ export default class ColsVisibility extends Feature {
|
||||||
let ul = createElm('ul');
|
let ul = createElm('ul');
|
||||||
ul.className = this.listCssClass;
|
ul.className = this.listCssClass;
|
||||||
|
|
||||||
let tbl = this.headersTbl ? this.headersTbl : tf.tbl;
|
let tbl = this.headersTbl || tf.dom();
|
||||||
let headerIndex = this.headersTbl ?
|
let headerIndex = this.headersTbl ?
|
||||||
this.headersIndex : tf.getHeadersRowIndex();
|
this.headersIndex : tf.getHeadersRowIndex();
|
||||||
let headerRow = tbl.rows[headerIndex];
|
let headerRow = tbl.rows[headerIndex];
|
||||||
|
@ -485,8 +495,7 @@ export default class ColsVisibility extends Feature {
|
||||||
|
|
||||||
for (let i = 0; i < headerRow.cells.length; i++) {
|
for (let i = 0; i < headerRow.cells.length; i++) {
|
||||||
let cell = headerRow.cells[i];
|
let cell = headerRow.cells[i];
|
||||||
let cellText = this.headersText && this.headersText[i] ?
|
let cellText = this.headersText[i] || this._getHeaderText(cell);
|
||||||
this.headersText[i] : this._getHeaderText(cell);
|
|
||||||
let liElm = createCheckItem('col_' + i + '_' + tf.id, cellText,
|
let liElm = createCheckItem('col_' + i + '_' + tf.id, cellText,
|
||||||
cellText);
|
cellText);
|
||||||
addClass(liElm, this.listItemCssClass);
|
addClass(liElm, this.listItemCssClass);
|
||||||
|
@ -535,18 +544,17 @@ export default class ColsVisibility extends Feature {
|
||||||
*/
|
*/
|
||||||
setHidden(colIndex, hide) {
|
setHidden(colIndex, hide) {
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
let tbl = tf.tbl;
|
let tbl = tf.dom();
|
||||||
|
|
||||||
if (hide) {
|
if (hide) {
|
||||||
this.onBeforeColHidden(this, colIndex);
|
this.onBeforeColHidden(this, colIndex);
|
||||||
}
|
} else {
|
||||||
if (!hide) {
|
|
||||||
this.onBeforeColDisplayed(this, colIndex);
|
this.onBeforeColDisplayed(this, colIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._hideCells(tbl, colIndex, hide);
|
this._hideElements(tbl, colIndex, hide);
|
||||||
if (this.headersTbl) {
|
if (this.headersTbl) {
|
||||||
this._hideCells(this.headersTbl, colIndex, hide);
|
this._hideElements(this.headersTbl, colIndex, hide);
|
||||||
}
|
}
|
||||||
|
|
||||||
let hiddenCols = this.hiddenCols;
|
let hiddenCols = this.hiddenCols;
|
||||||
|
@ -561,46 +569,11 @@ export default class ColsVisibility extends Feature {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let gridLayout;
|
|
||||||
let headTbl;
|
|
||||||
let gridColElms;
|
|
||||||
if (hide) {
|
if (hide) {
|
||||||
//This event is fired just after a column is displayed for
|
|
||||||
//grid_layout support
|
|
||||||
//TODO: grid layout module should be responsible for those
|
|
||||||
//calculations
|
|
||||||
if (tf.gridLayout) {
|
|
||||||
gridLayout = tf.feature('gridLayout');
|
|
||||||
headTbl = gridLayout.headTbl;
|
|
||||||
gridColElms = gridLayout.colElms;
|
|
||||||
let hiddenWidth = parseInt(
|
|
||||||
gridColElms[colIndex].style.width, 10);
|
|
||||||
|
|
||||||
let headTblW = parseInt(headTbl.style.width, 10);
|
|
||||||
headTbl.style.width = headTblW - hiddenWidth + 'px';
|
|
||||||
tbl.style.width = headTbl.style.width;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.onAfterColHidden(this, colIndex);
|
this.onAfterColHidden(this, colIndex);
|
||||||
this.emitter.emit('column-hidden', tf, this, colIndex,
|
this.emitter.emit('column-hidden', tf, this, colIndex,
|
||||||
this.hiddenCols);
|
this.hiddenCols);
|
||||||
}
|
} else {
|
||||||
|
|
||||||
if (!hide) {
|
|
||||||
//This event is fired just after a column is displayed for
|
|
||||||
//grid_layout support
|
|
||||||
//TODO: grid layout module should be responsible for those
|
|
||||||
//calculations
|
|
||||||
if (tf.gridLayout) {
|
|
||||||
gridLayout = tf.feature('gridLayout');
|
|
||||||
headTbl = gridLayout.headTbl;
|
|
||||||
gridColElms = gridLayout.colElms;
|
|
||||||
let width = parseInt(gridColElms[colIndex].style.width, 10);
|
|
||||||
headTbl.style.width =
|
|
||||||
(parseInt(headTbl.style.width, 10) + width) + 'px';
|
|
||||||
tf.tbl.style.width = headTbl.style.width;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.onAfterColDisplayed(this, colIndex);
|
this.onAfterColDisplayed(this, colIndex);
|
||||||
this.emitter.emit('column-shown', tf, this, colIndex,
|
this.emitter.emit('column-shown', tf, this, colIndex,
|
||||||
this.hiddenCols);
|
this.hiddenCols);
|
||||||
|
@ -612,7 +585,7 @@ export default class ColsVisibility extends Feature {
|
||||||
* @param {Number} colIndex Column index
|
* @param {Number} colIndex Column index
|
||||||
*/
|
*/
|
||||||
showCol(colIndex) {
|
showCol(colIndex) {
|
||||||
if (colIndex === undefined || !this.isColHidden(colIndex)) {
|
if (isUndef(colIndex) || !this.isColHidden(colIndex)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.manager && this.contEl) {
|
if (this.manager && this.contEl) {
|
||||||
|
@ -630,7 +603,7 @@ export default class ColsVisibility extends Feature {
|
||||||
* @param {Number} colIndex Column index
|
* @param {Number} colIndex Column index
|
||||||
*/
|
*/
|
||||||
hideCol(colIndex) {
|
hideCol(colIndex) {
|
||||||
if (colIndex === undefined || this.isColHidden(colIndex)) {
|
if (isUndef(colIndex) || this.isColHidden(colIndex)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.manager && this.contEl) {
|
if (this.manager && this.contEl) {
|
||||||
|
@ -659,7 +632,7 @@ export default class ColsVisibility extends Feature {
|
||||||
* @param {Number} colIndex Column index
|
* @param {Number} colIndex Column index
|
||||||
*/
|
*/
|
||||||
toggleCol(colIndex) {
|
toggleCol(colIndex) {
|
||||||
if (colIndex === undefined || this.isColHidden(colIndex)) {
|
if (isUndef(colIndex) || this.isColHidden(colIndex)) {
|
||||||
this.showCol(colIndex);
|
this.showCol(colIndex);
|
||||||
} else {
|
} else {
|
||||||
this.hideCol(colIndex);
|
this.hideCol(colIndex);
|
||||||
|
@ -721,16 +694,29 @@ export default class ColsVisibility extends Feature {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
_hideCells(tbl, colIndex, hide) {
|
_hideElements(tbl, colIdx, hide) {
|
||||||
|
this._hideCells(tbl, colIdx, hide);
|
||||||
|
this._hideCol(tbl, colIdx, hide);
|
||||||
|
}
|
||||||
|
|
||||||
|
_hideCells(tbl, colIdx, hide) {
|
||||||
for (let i = 0; i < tbl.rows.length; i++) {
|
for (let i = 0; i < tbl.rows.length; i++) {
|
||||||
let row = tbl.rows[i];
|
let row = tbl.rows[i];
|
||||||
let cell = row.cells[colIndex];
|
let cell = row.cells[colIdx];
|
||||||
if (cell) {
|
if (cell) {
|
||||||
cell.style.display = hide ? 'none' : '';
|
cell.style.display = hide ? NONE : '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_hideCol(tbl, colIdx, hide) {
|
||||||
|
let colElms = tag(tbl, 'col');
|
||||||
|
if (colElms.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
colElms[colIdx].style.display = hide ? NONE : '';
|
||||||
|
}
|
||||||
|
|
||||||
_hideAtStart() {
|
_hideAtStart() {
|
||||||
this.atStart.forEach((colIdx) => {
|
this.atStart.forEach((colIdx) => {
|
||||||
this.hideCol(colIdx);
|
this.hideCol(colIdx);
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
import {Feature} from '../../feature';
|
import {Feature} from '../../feature';
|
||||||
import {createElm, removeElm, elm} from '../../dom';
|
import {createElm, removeElm, elm} from '../../dom';
|
||||||
import {isFn, isUndef, EMPTY_FN} from '../../types';
|
import {EMPTY_FN, isNull} from '../../types';
|
||||||
import {addEvt} from '../../event';
|
import {addEvt} from '../../event';
|
||||||
|
import {
|
||||||
|
defaultsBool, defaultsStr, defaultsFn, defaultsNb,
|
||||||
|
} from '../../settings';
|
||||||
|
import {RIGHT} from '../../modules/toolbar';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filters Visibility extension
|
* Filters Visibility extension
|
||||||
|
@ -14,7 +18,7 @@ export default class FiltersVisibility extends Feature {
|
||||||
* @param {Object} Configuration object
|
* @param {Object} Configuration object
|
||||||
*/
|
*/
|
||||||
constructor(tf, f) {
|
constructor(tf, f) {
|
||||||
super(tf, f.name);
|
super(tf, FiltersVisibility);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module name
|
* Module name
|
||||||
|
@ -26,25 +30,26 @@ export default class FiltersVisibility extends Feature {
|
||||||
* Module description
|
* Module description
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.desc = f.description || 'Filters row visibility manager';
|
this.desc = defaultsStr(f.description,
|
||||||
|
'Filters row visibility manager');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extension's stylesheet filename
|
* Extension's stylesheet filename
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.stylesheet = f.stylesheet || 'filtersVisibility.css';
|
this.stylesheet = defaultsStr(f.stylesheet , 'filtersVisibility.css');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expand icon filename
|
* Expand icon filename
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.icnExpand = f.expand_icon_name || 'icn_exp.png';
|
this.icnExpand = defaultsStr(f.expand_icon_name, 'icn_exp.png');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collapse icon filename
|
* Collapse icon filename
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.icnCollapse = f.collapse_icon_name || 'icn_clp.png';
|
this.icnCollapse = defaultsStr(f.collapse_icon_name, 'icn_clp.png');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main container element
|
* Main container element
|
||||||
|
@ -88,13 +93,13 @@ export default class FiltersVisibility extends Feature {
|
||||||
* Enable expand/collapse icon, defaults to true
|
* Enable expand/collapse icon, defaults to true
|
||||||
* @type {Boolean}
|
* @type {Boolean}
|
||||||
*/
|
*/
|
||||||
this.enableIcon = f.enable_icon === false ? false : true;
|
this.enableIcon = defaultsBool(f.enable_icon, true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom text for button
|
* Custom text for button
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.btnText = f.btn_text || '';
|
this.btnText = defaultsStr(f.btn_text, '');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collapse button HTML
|
* Collapse button HTML
|
||||||
|
@ -116,62 +121,65 @@ export default class FiltersVisibility extends Feature {
|
||||||
* Button's custom HTML
|
* Button's custom HTML
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.btnHtml = f.btn_html || null;
|
this.btnHtml = defaultsStr(f.btn_html, null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for expand/collapse filters button
|
* Css class for expand/collapse filters button
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.btnCssClass = f.btn_css_class || 'btnExpClpFlt';
|
this.btnCssClass = defaultsStr(f.btn_css_class, 'btnExpClpFlt');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for main container
|
* Css class for main container
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.contCssClass = f.cont_css_class || 'expClpFlt';
|
this.contCssClass = defaultsStr(f.cont_css_class, 'expClpFlt');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filters row index
|
* Filters row index
|
||||||
* @type {Number}
|
* @type {Number}
|
||||||
*/
|
*/
|
||||||
this.filtersRowIndex = !isUndef(f.filters_row_index) ?
|
this.filtersRowIndex = defaultsNb(f.filters_row_index,
|
||||||
f.filters_row_index : tf.getFiltersRowIndex();
|
tf.getFiltersRowIndex());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make filters visible at initialization, defaults to true
|
* Make filters visible at initialization, defaults to true
|
||||||
* @type {Boolean}
|
* @type {Boolean}
|
||||||
*/
|
*/
|
||||||
this.visibleAtStart = !isUndef(f.visible_at_start) ?
|
this.visibleAtStart = defaultsNb(f.visible_at_start, true);
|
||||||
Boolean(f.visible_at_start) : true;
|
|
||||||
|
/**
|
||||||
|
* Default position in toolbar ('left'|'center'|'right')
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
this.toolbarPosition = defaultsStr(f.toolbar_position, RIGHT);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired before filters row is shown
|
* Callback fired before filters row is shown
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onBeforeShow = isFn(f.on_before_show) ?
|
this.onBeforeShow = defaultsFn(f.on_before_show, EMPTY_FN);
|
||||||
f.on_before_show : EMPTY_FN;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired after filters row is shown
|
* Callback fired after filters row is shown
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onAfterShow = isFn(f.on_after_show) ? f.on_after_show : EMPTY_FN;
|
this.onAfterShow = defaultsFn(f.on_after_show, EMPTY_FN);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired before filters row is hidden
|
* Callback fired before filters row is hidden
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onBeforeHide = isFn(f.on_before_hide) ?
|
this.onBeforeHide = defaultsFn(f.on_before_hide, EMPTY_FN);
|
||||||
f.on_before_hide : EMPTY_FN;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired after filters row is hidden
|
* Callback fired after filters row is hidden
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onAfterHide = isFn(f.on_after_hide) ? f.on_after_hide : EMPTY_FN;
|
this.onAfterHide = defaultsFn(f.on_after_hide, EMPTY_FN);
|
||||||
|
|
||||||
//Import extension's stylesheet
|
//Import extension's stylesheet
|
||||||
tf.import(f.name + 'Style', tf.stylePath + this.stylesheet, null,
|
tf.import(f.name + 'Style', tf.getStylePath() + this.stylesheet, null,
|
||||||
'link');
|
'link');
|
||||||
|
|
||||||
this.enable();
|
this.enable();
|
||||||
|
@ -185,15 +193,17 @@ export default class FiltersVisibility extends Feature {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.emitter.emit('initializing-extension', this,
|
||||||
|
!isNull(this.targetId));
|
||||||
|
|
||||||
this.buildUI();
|
this.buildUI();
|
||||||
|
|
||||||
/**
|
/** @inherited */
|
||||||
* @inherited
|
|
||||||
*/
|
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
|
|
||||||
this.emitter.on(['show-filters'], (tf, visible) => this.show(visible));
|
this.emitter.on(['show-filters'], (tf, visible) => this.show(visible));
|
||||||
this.emitter.emit('filters-visibility-initialized', this.tf, this);
|
this.emitter.emit('filters-visibility-initialized', this.tf, this);
|
||||||
|
this.emitter.emit('extension-initialized', this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -204,11 +214,10 @@ export default class FiltersVisibility extends Feature {
|
||||||
let span = createElm('span');
|
let span = createElm('span');
|
||||||
span.className = this.contCssClass;
|
span.className = this.contCssClass;
|
||||||
|
|
||||||
//Container element (rdiv or custom element)
|
// Container element (rdiv or custom element)
|
||||||
if (!this.targetId) {
|
let targetEl = !this.targetId ?
|
||||||
tf.setToolbar();
|
tf.feature('toolbar').container(this.toolbarPosition) :
|
||||||
}
|
elm(this.targetId);
|
||||||
let targetEl = !this.targetId ? tf.rDiv : elm(this.targetId);
|
|
||||||
|
|
||||||
if (!this.targetId) {
|
if (!this.targetId) {
|
||||||
let firstChild = targetEl.firstChild;
|
let firstChild = targetEl.firstChild;
|
||||||
|
@ -224,7 +233,7 @@ export default class FiltersVisibility extends Feature {
|
||||||
btn.title = this.btnText || this.defaultText;
|
btn.title = this.btnText || this.defaultText;
|
||||||
btn.innerHTML = this.collapseBtnHtml;
|
btn.innerHTML = this.collapseBtnHtml;
|
||||||
span.appendChild(btn);
|
span.appendChild(btn);
|
||||||
} else { //Custom html
|
} else { // Custom html
|
||||||
span.innerHTML = this.btnHtml;
|
span.innerHTML = this.btnHtml;
|
||||||
btn = span.firstChild;
|
btn = span.firstChild;
|
||||||
}
|
}
|
||||||
|
@ -244,7 +253,7 @@ export default class FiltersVisibility extends Feature {
|
||||||
*/
|
*/
|
||||||
toggle() {
|
toggle() {
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
let tbl = tf.gridLayout ? tf.feature('gridLayout').headTbl : tf.tbl;
|
let tbl = tf.gridLayout ? tf.feature('gridLayout').headTbl : tf.dom();
|
||||||
let fltRow = tbl.rows[this.filtersRowIndex];
|
let fltRow = tbl.rows[this.filtersRowIndex];
|
||||||
let isDisplayed = fltRow.style.display === '';
|
let isDisplayed = fltRow.style.display === '';
|
||||||
|
|
||||||
|
@ -258,7 +267,7 @@ export default class FiltersVisibility extends Feature {
|
||||||
*/
|
*/
|
||||||
show(visible = true) {
|
show(visible = true) {
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
let tbl = tf.gridLayout ? tf.feature('gridLayout').headTbl : tf.tbl;
|
let tbl = tf.gridLayout ? tf.feature('gridLayout').headTbl : tf.dom();
|
||||||
let fltRow = tbl.rows[this.filtersRowIndex];
|
let fltRow = tbl.rows[this.filtersRowIndex];
|
||||||
|
|
||||||
if (visible) {
|
if (visible) {
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import {Feature} from '../../feature';
|
import {Feature} from '../../feature';
|
||||||
import {isArray, isFn, isUndef, isObj, EMPTY_FN} from '../../types';
|
import {isUndef, isObj, EMPTY_FN} from '../../types';
|
||||||
import {createElm, elm, getText, tag} from '../../dom';
|
import {createElm, elm, tag} from '../../dom';
|
||||||
import {addEvt} from '../../event';
|
import {addEvt, bound} from '../../event';
|
||||||
import {parse as parseNb} from '../../number';
|
import {parse as parseNb} from '../../number';
|
||||||
import {
|
import {
|
||||||
NONE, CELL_TAG, HEADER_TAG, STRING, NUMBER, DATE, FORMATTED_NUMBER,
|
NONE, CELL_TAG, HEADER_TAG, STRING, NUMBER, DATE, FORMATTED_NUMBER,
|
||||||
IP_ADDRESS
|
IP_ADDRESS
|
||||||
} from '../../const';
|
} from '../../const';
|
||||||
|
import {defaultsStr, defaultsFn, defaultsArr} from '../../settings';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SortableTable Adapter module
|
* SortableTable Adapter module
|
||||||
|
@ -19,7 +20,7 @@ export default class AdapterSortableTable extends Feature {
|
||||||
* @param {Object} opts Configuration object
|
* @param {Object} opts Configuration object
|
||||||
*/
|
*/
|
||||||
constructor(tf, opts) {
|
constructor(tf, opts) {
|
||||||
super(tf, opts.name);
|
super(tf, AdapterSortableTable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module name
|
* Module name
|
||||||
|
@ -31,7 +32,7 @@ export default class AdapterSortableTable extends Feature {
|
||||||
* Module description
|
* Module description
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.desc = opts.description || 'Sortable table';
|
this.desc = defaultsStr(opts.description, 'Sortable table');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicate whether table previously sorted
|
* Indicate whether table previously sorted
|
||||||
|
@ -44,15 +45,14 @@ export default class AdapterSortableTable extends Feature {
|
||||||
* List of sort type per column basis
|
* List of sort type per column basis
|
||||||
* @type {Array}
|
* @type {Array}
|
||||||
*/
|
*/
|
||||||
this.sortTypes = isArray(opts.types) ? opts.types : tf.colTypes;
|
this.sortTypes = defaultsArr(opts.types, tf.colTypes);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Column to be sorted at initialization, ie:
|
* Column to be sorted at initialization, ie:
|
||||||
* sort_col_at_start: [1, true]
|
* sort_col_at_start: [1, true]
|
||||||
* @type {Array}
|
* @type {Array}
|
||||||
*/
|
*/
|
||||||
this.sortColAtStart = isArray(opts.sort_col_at_start) ?
|
this.sortColAtStart = defaultsArr(opts.sort_col_at_start, null);
|
||||||
opts.sort_col_at_start : null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable asynchronous sort, if triggers are external
|
* Enable asynchronous sort, if triggers are external
|
||||||
|
@ -64,7 +64,7 @@ export default class AdapterSortableTable extends Feature {
|
||||||
* List of element IDs triggering sort on a per column basis
|
* List of element IDs triggering sort on a per column basis
|
||||||
* @type {Array}
|
* @type {Array}
|
||||||
*/
|
*/
|
||||||
this.triggerIds = isArray(opts.trigger_ids) ? opts.trigger_ids : [];
|
this.triggerIds = defaultsArr(opts.trigger_ids, []);
|
||||||
|
|
||||||
// edit .sort-arrow.descending / .sort-arrow.ascending in
|
// edit .sort-arrow.descending / .sort-arrow.ascending in
|
||||||
// tablefilter.css to reflect any path change
|
// tablefilter.css to reflect any path change
|
||||||
|
@ -72,58 +72,57 @@ export default class AdapterSortableTable extends Feature {
|
||||||
* Path to images
|
* Path to images
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.imgPath = opts.images_path || tf.themesPath;
|
this.imgPath = defaultsStr(opts.images_path, tf.themesPath);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Blank image file name
|
* Blank image file name
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.imgBlank = opts.image_blank || 'blank.png';
|
this.imgBlank = defaultsStr(opts.image_blank, 'blank.png');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for sort indicator image
|
* Css class for sort indicator image
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.imgClassName = opts.image_class_name || 'sort-arrow';
|
this.imgClassName = defaultsStr(opts.image_class_name, 'sort-arrow');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for ascending sort indicator image
|
* Css class for ascending sort indicator image
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.imgAscClassName = opts.image_asc_class_name || 'ascending';
|
this.imgAscClassName = defaultsStr(opts.image_asc_class_name,
|
||||||
|
'ascending');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for descending sort indicator image
|
* Css class for descending sort indicator image
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.imgDescClassName = opts.image_desc_class_name || 'descending';
|
this.imgDescClassName = defaultsStr(opts.image_desc_class_name,
|
||||||
|
'descending');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cell attribute key storing custom value used for sorting
|
* Cell attribute key storing custom value used for sorting
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.customKey = opts.custom_key || 'data-tf-sortKey';
|
this.customKey = defaultsStr(opts.custom_key, 'data-tf-sortKey');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired when sort extension is instanciated
|
* Callback fired when sort extension is instanciated
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onSortLoaded = isFn(opts.on_sort_loaded) ?
|
this.onSortLoaded = defaultsFn(opts.on_sort_loaded, EMPTY_FN);
|
||||||
opts.on_sort_loaded : EMPTY_FN;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired before a table column is sorted
|
* Callback fired before a table column is sorted
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onBeforeSort = isFn(opts.on_before_sort) ?
|
this.onBeforeSort = defaultsFn(opts.on_before_sort, EMPTY_FN);
|
||||||
opts.on_before_sort : EMPTY_FN;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired after a table column is sorted
|
* Callback fired after a table column is sorted
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onAfterSort = isFn(opts.on_after_sort) ?
|
this.onAfterSort = defaultsFn(opts.on_after_sort, EMPTY_FN);
|
||||||
opts.on_after_sort : EMPTY_FN;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SortableTable instance
|
* SortableTable instance
|
||||||
|
@ -190,8 +189,7 @@ export default class AdapterSortableTable extends Feature {
|
||||||
this.stt.sort(sortColAtStart[0], sortColAtStart[1]);
|
this.stt.sort(sortColAtStart[0], sortColAtStart[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.emitter.on(['sort'],
|
this.emitter.on(['sort'], bound(this.sortByColumnIndexHandler, this));
|
||||||
(tf, colIdx, desc) => this.sortByColumnIndex(colIdx, desc));
|
|
||||||
|
|
||||||
/** @inherited */
|
/** @inherited */
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
|
@ -208,6 +206,11 @@ export default class AdapterSortableTable extends Feature {
|
||||||
this.stt.sort(colIdx, desc);
|
this.stt.sort(colIdx, desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @private */
|
||||||
|
sortByColumnIndexHandler(tf, colIdx, desc) {
|
||||||
|
this.sortByColumnIndex(colIdx, desc);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set SortableTable overrides for TableFilter integration
|
* Set SortableTable overrides for TableFilter integration
|
||||||
*/
|
*/
|
||||||
|
@ -358,17 +361,17 @@ export default class AdapterSortableTable extends Feature {
|
||||||
/**
|
/**
|
||||||
* Overrides getInnerText in order to avoid Firefox unexpected sorting
|
* Overrides getInnerText in order to avoid Firefox unexpected sorting
|
||||||
* behaviour with untrimmed text elements
|
* behaviour with untrimmed text elements
|
||||||
* @param {Object} oNode DOM element
|
* @param {Object} cell DOM element
|
||||||
* @return {String} DOM element inner text
|
* @return {String} DOM element inner text
|
||||||
*/
|
*/
|
||||||
SortableTable.getInnerText = function (oNode) {
|
SortableTable.getInnerText = function (cell) {
|
||||||
if (!oNode) {
|
if (!cell) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (oNode.getAttribute(adpt.customKey)) {
|
if (cell.getAttribute(adpt.customKey)) {
|
||||||
return oNode.getAttribute(adpt.customKey);
|
return cell.getAttribute(adpt.customKey);
|
||||||
} else {
|
} else {
|
||||||
return getText(oNode);
|
return tf.getCellValue(cell);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -378,8 +381,8 @@ export default class AdapterSortableTable extends Feature {
|
||||||
*/
|
*/
|
||||||
addSortType(...args) {
|
addSortType(...args) {
|
||||||
// Extract the arguments
|
// Extract the arguments
|
||||||
let [id, caster, sorter] = args;
|
let [id, caster, sorter, getRowValue] = args;
|
||||||
SortableTable.prototype.addSortType(id, caster, sorter);
|
SortableTable.prototype.addSortType(id, caster, sorter, getRowValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -391,7 +394,7 @@ export default class AdapterSortableTable extends Feature {
|
||||||
sortTypes = this.sortTypes,
|
sortTypes = this.sortTypes,
|
||||||
_sortTypes = [];
|
_sortTypes = [];
|
||||||
|
|
||||||
for (let i = 0; i < tf.nbCells; i++) {
|
tf.eachCol((i) => {
|
||||||
let colType;
|
let colType;
|
||||||
if (sortTypes[i]) {
|
if (sortTypes[i]) {
|
||||||
colType = sortTypes[i];
|
colType = sortTypes[i];
|
||||||
|
@ -421,7 +424,7 @@ export default class AdapterSortableTable extends Feature {
|
||||||
colType = STRING;
|
colType = STRING;
|
||||||
}
|
}
|
||||||
_sortTypes.push(colType);
|
_sortTypes.push(colType);
|
||||||
}
|
});
|
||||||
|
|
||||||
//Public TF method to add sort type
|
//Public TF method to add sort type
|
||||||
|
|
||||||
|
@ -430,7 +433,7 @@ export default class AdapterSortableTable extends Feature {
|
||||||
this.addSortType(STRING);
|
this.addSortType(STRING);
|
||||||
this.addSortType(IP_ADDRESS, ipAddress, sortIP);
|
this.addSortType(IP_ADDRESS, ipAddress, sortIP);
|
||||||
|
|
||||||
this.stt = new SortableTable(tf.tbl, _sortTypes);
|
this.stt = new SortableTable(tf.dom(), _sortTypes);
|
||||||
|
|
||||||
/*** external table headers adapter ***/
|
/*** external table headers adapter ***/
|
||||||
if (this.asyncSort && this.triggerIds.length > 0) {
|
if (this.asyncSort && this.triggerIds.length > 0) {
|
||||||
|
@ -487,8 +490,7 @@ export default class AdapterSortableTable extends Feature {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
this.emitter.off(['sort'],
|
this.emitter.off(['sort'], bound(this.sortByColumnIndexHandler, this));
|
||||||
(tf, colIdx, desc) => this.sortByColumnIndex(colIdx, desc));
|
|
||||||
this.sorted = false;
|
this.sorted = false;
|
||||||
this.stt.destroy();
|
this.stt.destroy();
|
||||||
|
|
||||||
|
@ -506,9 +508,12 @@ export default class AdapterSortableTable extends Feature {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AdapterSortableTable.meta = {altName: 'sort'};
|
||||||
|
|
||||||
//Converters
|
//Converters
|
||||||
function ipAddress(value) {
|
function ipAddress(value) {
|
||||||
let vals = value.split('.');
|
let vals = value.split('.');
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
for (let x in vals) {
|
for (let x in vals) {
|
||||||
let val = vals[x];
|
let val = vals[x];
|
||||||
while (3 > val.length) {
|
while (3 > val.length) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
import {toCamelCase} from './string';
|
||||||
|
|
||||||
const NOTIMPLEMENTED = 'Not implemented.';
|
const NOT_IMPLEMENTED = 'Not implemented.';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class defining the interface of a TableFilter feature
|
* Base class defining the interface of a TableFilter feature
|
||||||
|
@ -8,9 +9,11 @@ export class Feature {
|
||||||
/**
|
/**
|
||||||
* Creates an instance of Feature
|
* Creates an instance of Feature
|
||||||
* @param {Object} tf TableFilter instance
|
* @param {Object} tf TableFilter instance
|
||||||
* @param {String} feature Feature name known by TableFilter
|
* @param {Class} feature Feature class for TableFilter registration
|
||||||
*/
|
*/
|
||||||
constructor(tf, feature) {
|
constructor(tf, cls) {
|
||||||
|
cls.meta = cls.meta || {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TableFilter instance
|
* TableFilter instance
|
||||||
* @type {TableFilter}
|
* @type {TableFilter}
|
||||||
|
@ -18,16 +21,18 @@ export class Feature {
|
||||||
this.tf = tf;
|
this.tf = tf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Feature name
|
* Feature name is the camelised class name as per TableFilter's
|
||||||
|
* convention
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.feature = feature;
|
this.feature = cls.meta.altName || cls.meta.name
|
||||||
|
|| toCamelCase(cls.name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TableFilter feature setting
|
* TableFilter feature setting
|
||||||
* @type {Boolean}
|
* @type {Boolean}
|
||||||
*/
|
*/
|
||||||
this.enabled = tf[feature];
|
this.enabled = tf[this.feature];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TableFilter configuration
|
* TableFilter configuration
|
||||||
|
@ -55,7 +60,7 @@ export class Feature {
|
||||||
* Initialize the feature
|
* Initialize the feature
|
||||||
*/
|
*/
|
||||||
init() {
|
init() {
|
||||||
throw new Error(NOTIMPLEMENTED);
|
throw new Error(NOT_IMPLEMENTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,7 +75,7 @@ export class Feature {
|
||||||
* Destroy the feature
|
* Destroy the feature
|
||||||
*/
|
*/
|
||||||
destroy() {
|
destroy() {
|
||||||
throw new Error(NOTIMPLEMENTED);
|
throw new Error(NOT_IMPLEMENTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -92,6 +97,6 @@ export class Feature {
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
isEnabled() {
|
isEnabled() {
|
||||||
return this.enabled;
|
return this.enabled === true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import {Feature} from '../feature';
|
import {Feature} from '../feature';
|
||||||
import {addClass, removeClass} from '../dom';
|
import {addClass, removeClass} from '../dom';
|
||||||
|
import {defaultsStr} from '../settings';
|
||||||
|
import {bound} from '../event';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rows with alternating background color for improved readability
|
* Rows with alternating background color for improved readability
|
||||||
|
@ -12,20 +14,21 @@ export class AlternateRows extends Feature {
|
||||||
* @param {Object} tf TableFilter instance
|
* @param {Object} tf TableFilter instance
|
||||||
*/
|
*/
|
||||||
constructor(tf) {
|
constructor(tf) {
|
||||||
super(tf, 'alternateRows');
|
super(tf, AlternateRows);
|
||||||
|
|
||||||
let config = this.config;
|
let config = this.config;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for even rows (default: 'even')
|
* Css class for even rows (default: 'even')
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.evenCss = config.even_row_css_class || 'even';
|
this.evenCss = defaultsStr(config.even_row_css_class, 'even');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for odd rows (default: 'odd')
|
* Css class for odd rows (default: 'odd')
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.oddCss = config.odd_row_css_class || 'odd';
|
this.oddCss = defaultsStr(config.odd_row_css_class, 'odd');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,10 +43,9 @@ export class AlternateRows extends Feature {
|
||||||
|
|
||||||
// Subscribe to events
|
// Subscribe to events
|
||||||
this.emitter.on(['row-processed', 'row-paged'],
|
this.emitter.on(['row-processed', 'row-paged'],
|
||||||
(tf, rowIndex, arrIndex, isValid) =>
|
bound(this.processRowHandler, this));
|
||||||
this.processRow(rowIndex, arrIndex, isValid));
|
this.emitter.on(['column-sorted', 'rows-changed'],
|
||||||
this.emitter.on(['column-sorted'], () => this.processAll());
|
bound(this.processAll, this));
|
||||||
this.emitter.on(['rows-changed'], () => this.processAll());
|
|
||||||
|
|
||||||
/** @inherited */
|
/** @inherited */
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
|
@ -94,7 +96,7 @@ export class AlternateRows extends Feature {
|
||||||
if (!this.isEnabled() || isNaN(rowIdx)) {
|
if (!this.isEnabled() || isNaN(rowIdx)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let rows = this.tf.tbl.rows;
|
let rows = this.tf.dom().rows;
|
||||||
let i = isNaN(idx) ? rowIdx : idx;
|
let i = isNaN(idx) ? rowIdx : idx;
|
||||||
this.removeRowBg(rowIdx);
|
this.removeRowBg(rowIdx);
|
||||||
|
|
||||||
|
@ -110,11 +112,16 @@ export class AlternateRows extends Feature {
|
||||||
if (isNaN(idx)) {
|
if (isNaN(idx)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let rows = this.tf.tbl.rows;
|
let rows = this.tf.dom().rows;
|
||||||
removeClass(rows[idx], this.oddCss);
|
removeClass(rows[idx], this.oddCss);
|
||||||
removeClass(rows[idx], this.evenCss);
|
removeClass(rows[idx], this.evenCss);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @private */
|
||||||
|
processRowHandler(tf, rowIndex, arrIndex, isValid) {
|
||||||
|
this.processRow(rowIndex, arrIndex, isValid);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes all alternating backgrounds
|
* Removes all alternating backgrounds
|
||||||
*/
|
*/
|
||||||
|
@ -122,17 +129,15 @@ export class AlternateRows extends Feature {
|
||||||
if (!this.initialized) {
|
if (!this.initialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let nbRows = this.tf.getRowsNb(true);
|
|
||||||
for (let i = 0; i < nbRows; i++) {
|
let eachRow = this.tf.eachRow(0);
|
||||||
this.removeRowBg(i);
|
eachRow((row, i) => this.removeRowBg(i));
|
||||||
}
|
|
||||||
|
|
||||||
// Unsubscribe to events
|
// Unsubscribe to events
|
||||||
this.emitter.off(['row-processed', 'row-paged'],
|
this.emitter.off(['row-processed', 'row-paged'],
|
||||||
(tf, rowIndex, arrIndex, isValid) =>
|
bound(this.processRowHandler, this));
|
||||||
this.processRow(rowIndex, arrIndex, isValid));
|
this.emitter.off(['column-sorted', 'rows-changed'],
|
||||||
this.emitter.off(['column-sorted'], () => this.processAll());
|
bound(this.processAll, this));
|
||||||
this.emitter.off(['rows-changed'], () => this.processAll());
|
|
||||||
|
|
||||||
this.initialized = false;
|
this.initialized = false;
|
||||||
}
|
}
|
||||||
|
|
160
src/modules/baseDropdown.js
Normal file
160
src/modules/baseDropdown.js
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
import {Feature} from '../feature';
|
||||||
|
import {
|
||||||
|
ignoreCase, numSortAsc, numSortDesc,
|
||||||
|
dateSortAsc, dateSortDesc, sortNumberStr, sortDateStr
|
||||||
|
} from '../sort';
|
||||||
|
import {isArray, isObj, isEmpty} from '../types';
|
||||||
|
import {NUMBER, FORMATTED_NUMBER, DATE} from '../const';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for Dropdown and CheckList UI components
|
||||||
|
* @export
|
||||||
|
* @class BaseDropdown
|
||||||
|
* @extends {Feature}
|
||||||
|
*/
|
||||||
|
export class BaseDropdown extends Feature {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance of BaseDropdown
|
||||||
|
* @param {TableFilter} tf
|
||||||
|
*/
|
||||||
|
constructor(tf, cls) {
|
||||||
|
super(tf, cls);
|
||||||
|
|
||||||
|
let f = this.config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter options custom sorter on a column basis
|
||||||
|
* @type {Object}
|
||||||
|
*/
|
||||||
|
this.customSorter = isObj(f.filter_options_sorter) &&
|
||||||
|
isArray(f.filter_options_sorter.col) &&
|
||||||
|
isArray(f.filter_options_sorter.comparer) ?
|
||||||
|
f.filter_options_sorter :
|
||||||
|
null;
|
||||||
|
|
||||||
|
// TODO: move here all properties shared by Dropdown and CheckList
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has custom options
|
||||||
|
* @type {Boolean}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.isCustom = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of options values
|
||||||
|
* @type {Array}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.opts = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of options texts for custom values
|
||||||
|
* @type {Array}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.optsTxt = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of options to be excluded from the checklist filter
|
||||||
|
* @type {Array}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.excludedOpts = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort passed options based on the type of the specified column
|
||||||
|
* @param {Number} colIndex Column index
|
||||||
|
* @param {Array} [options=[]] Collection of values
|
||||||
|
* @return {Array} Sorted values
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
sortOptions(colIndex, options = []) {
|
||||||
|
let {tf} = this;
|
||||||
|
|
||||||
|
if (tf.isCustomOptions(colIndex) || !tf.sortSlc ||
|
||||||
|
(isArray(tf.sortSlc) && tf.sortSlc.indexOf(colIndex) === -1)) {
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
let { caseSensitive, sortFilterOptionsDesc } = tf;
|
||||||
|
let isSortDesc = sortFilterOptionsDesc.indexOf(colIndex) !== -1;
|
||||||
|
let compareFn;
|
||||||
|
|
||||||
|
if (this.customSorter &&
|
||||||
|
this.customSorter.col.indexOf(colIndex) !== -1) {
|
||||||
|
var idx = this.customSorter.col.indexOf(colIndex);
|
||||||
|
compareFn = this.customSorter.comparer[idx];
|
||||||
|
}
|
||||||
|
else if (tf.hasType(colIndex, [NUMBER, FORMATTED_NUMBER])) {
|
||||||
|
let decimal = tf.getDecimal(colIndex);
|
||||||
|
let comparer = isSortDesc ? numSortDesc : numSortAsc;
|
||||||
|
compareFn = sortNumberStr(comparer, decimal);
|
||||||
|
}
|
||||||
|
else if (tf.hasType(colIndex, [DATE])) {
|
||||||
|
let locale = tf.feature('dateType').getLocale(colIndex);
|
||||||
|
let comparer = isSortDesc ? dateSortDesc : dateSortAsc;
|
||||||
|
compareFn = sortDateStr(comparer, locale);
|
||||||
|
} else { // string
|
||||||
|
compareFn = caseSensitive ? undefined : ignoreCase;
|
||||||
|
if (isSortDesc) {
|
||||||
|
return options.sort(compareFn).reverse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return options.sort(compareFn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regenerate filters of specified columns and maintain selection if any
|
||||||
|
* @param {Array} colIndexes Collection of column indexes
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
refreshFilters(colIndexes) {
|
||||||
|
colIndexes.forEach((colIdx) => {
|
||||||
|
let values = this.getValues(colIdx);
|
||||||
|
this.build(colIdx, this.tf.linkedFilters);
|
||||||
|
this.selectOptions(colIdx, values);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check passed row contains a valid linked value
|
||||||
|
* @param {Number} rowIdx Row index
|
||||||
|
* @param {Number} activeFilterIdx Current active filter index
|
||||||
|
* @returns {Boolean}
|
||||||
|
*/
|
||||||
|
isValidLinkedValue(rowIdx, activeFilterIdx) {
|
||||||
|
let tf = this.tf;
|
||||||
|
|
||||||
|
if (tf.disableExcludedOptions) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tf.paging) {
|
||||||
|
if (!isEmpty(activeFilterIdx) && tf.isRowValid(rowIdx)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (tf.isRowDisplayed(rowIdx)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh linked filters to offer only selected options
|
||||||
|
*/
|
||||||
|
linkFilters() {
|
||||||
|
let tf = this.tf;
|
||||||
|
if (!tf.linkedFilters || !tf.activeFilterId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.refreshAll();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,29 +1,28 @@
|
||||||
import {Feature} from '../feature';
|
import {BaseDropdown} from './baseDropdown';
|
||||||
import {
|
import {
|
||||||
addClass, createCheckItem, createText, createElm, elm, getText,
|
addClass, createCheckItem, createText, createElm, elm, removeClass, tag
|
||||||
removeClass, tag
|
|
||||||
} from '../dom';
|
} from '../dom';
|
||||||
import {has} from '../array';
|
import {has} from '../array';
|
||||||
import {matchCase, trim, rgxEsc} from '../string';
|
import {matchCase, trim, rgxEsc} from '../string';
|
||||||
import {ignoreCase, numSortAsc, numSortDesc} from '../sort';
|
|
||||||
import {addEvt, removeEvt, targetEvt} from '../event';
|
import {addEvt, removeEvt, targetEvt} from '../event';
|
||||||
import {isEmpty} from '../types';
|
import {isEmpty} from '../types';
|
||||||
import {CHECKLIST, NONE} from '../const';
|
import {CHECKLIST, NONE} from '../const';
|
||||||
|
import {defaultsStr, defaultsBool} from '../settings';
|
||||||
const SORT_ERROR = 'Filter options for column {0} cannot be sorted in ' +
|
|
||||||
'{1} manner.';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checklist filter UI component
|
* Checklist filter UI component
|
||||||
|
* @export
|
||||||
|
* @class CheckList
|
||||||
|
* @extends {BaseDropdown}
|
||||||
*/
|
*/
|
||||||
export class CheckList extends Feature {
|
export class CheckList extends BaseDropdown {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an instance of CheckList
|
* Creates an instance of CheckList
|
||||||
* @param {TableFilter} tf TableFilter instance
|
* @param {TableFilter} tf TableFilter instance
|
||||||
*/
|
*/
|
||||||
constructor(tf) {
|
constructor(tf) {
|
||||||
super(tf, 'checkList');
|
super(tf, CheckList);
|
||||||
|
|
||||||
let f = this.config;
|
let f = this.config;
|
||||||
|
|
||||||
|
@ -37,48 +36,57 @@ export class CheckList extends Feature {
|
||||||
* Css class for the container of the checklist filter (div)
|
* Css class for the container of the checklist filter (div)
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.containerCssClass = f.div_checklist_css_class || 'div_checklist';
|
this.containerCssClass = defaultsStr(f.div_checklist_css_class,
|
||||||
|
'div_checklist');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for the checklist filter element (ul)
|
* Css class for the checklist filter element (ul)
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.filterCssClass = f.checklist_css_class || 'flt_checklist';
|
this.filterCssClass = defaultsStr(f.checklist_css_class,
|
||||||
|
'flt_checklist');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for the item of a checklist (li)
|
* Css class for the item of a checklist (li)
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.itemCssClass = f.checklist_item_css_class || 'flt_checklist_item';
|
this.itemCssClass = defaultsStr(f.checklist_item_css_class,
|
||||||
|
'flt_checklist_item');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for a selected item of a checklist (li)
|
* Css class for a selected item of a checklist (li)
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.selectedItemCssClass =
|
this.selectedItemCssClass = defaultsStr(
|
||||||
f.checklist_selected_item_css_class || 'flt_checklist_slc_item';
|
f.checklist_selected_item_css_class,
|
||||||
|
'flt_checklist_slc_item'
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Text placed in the filter's container when load filter on demand
|
* Text placed in the filter's container when load filter on demand
|
||||||
* feature is enabled
|
* feature is enabled
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.activateText =
|
this.activateText = defaultsStr(
|
||||||
f.activate_checklist_text || 'Click to load filter data';
|
f.activate_checklist_text,
|
||||||
|
'Click to load filter data'
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for a disabled item of a checklist (li)
|
* Css class for a disabled item of a checklist (li)
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.disabledItemCssClass = f.checklist_item_disabled_css_class ||
|
this.disabledItemCssClass = defaultsStr(
|
||||||
'flt_checklist_item_disabled';
|
f.checklist_item_disabled_css_class,
|
||||||
|
'flt_checklist_item_disabled'
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable the reset filter option as first item
|
* Enable the reset filter option as first item
|
||||||
* @type {Boolean}
|
* @type {Boolean}
|
||||||
*/
|
*/
|
||||||
this.enableResetOption = f.enable_checklist_reset_filter === false ?
|
this.enableResetOption = defaultsBool(f.enable_checklist_reset_filter,
|
||||||
false : true;
|
true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prefix for container element ID
|
* Prefix for container element ID
|
||||||
|
@ -86,34 +94,6 @@ export class CheckList extends Feature {
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.prfx = 'chkdiv_';
|
this.prfx = 'chkdiv_';
|
||||||
|
|
||||||
/**
|
|
||||||
* Has custom options
|
|
||||||
* @type {Boolean}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.isCustom = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of options values
|
|
||||||
* @type {Array}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.opts = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of options texts for custom values
|
|
||||||
* @type {Array}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.optsTxt = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of options to be excluded from the checklist filter
|
|
||||||
* @type {Array}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.excludedOpts = [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -126,7 +106,7 @@ export class CheckList extends Feature {
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
|
|
||||||
this.emitter.emit('filter-focus', tf, elm);
|
this.emitter.emit('filter-focus', tf, elm);
|
||||||
this.setCheckListValues(elm);
|
this.setItemOption(elm);
|
||||||
tf.filter();
|
tf.filter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,13 +129,8 @@ export class CheckList extends Feature {
|
||||||
* Refresh all checklist filters
|
* Refresh all checklist filters
|
||||||
*/
|
*/
|
||||||
refreshAll() {
|
refreshAll() {
|
||||||
let tf = this.tf;
|
let colIdxs = this.tf.getFiltersByType(CHECKLIST, true);
|
||||||
let fltsIdxs = tf.getFiltersByType(CHECKLIST, true);
|
this.refreshFilters(colIdxs);
|
||||||
fltsIdxs.forEach((colIdx) => {
|
|
||||||
let values = this.getValues(colIdx);
|
|
||||||
this.build(colIdx, tf.linkedFilters);
|
|
||||||
this.selectOptions(colIdx, values);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -167,7 +142,7 @@ export class CheckList extends Feature {
|
||||||
init(colIndex, isExternal, container) {
|
init(colIndex, isExternal, container) {
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
let externalFltTgtId = isExternal ?
|
let externalFltTgtId = isExternal ?
|
||||||
tf.externalFltTgtIds[colIndex] : null;
|
tf.externalFltIds[colIndex] : null;
|
||||||
|
|
||||||
let divCont = createElm('div',
|
let divCont = createElm('div',
|
||||||
['id', `${this.prfx}${colIndex}_${tf.id}`],
|
['id', `${this.prfx}${colIndex}_${tf.id}`],
|
||||||
|
@ -203,6 +178,8 @@ export class CheckList extends Feature {
|
||||||
|
|
||||||
this.emitter.on(['rows-changed'], () => this.refreshAll());
|
this.emitter.on(['rows-changed'], () => this.refreshAll());
|
||||||
|
|
||||||
|
this.emitter.on(['after-filtering'], () => this.linkFilters());
|
||||||
|
|
||||||
/** @inherited */
|
/** @inherited */
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
}
|
}
|
||||||
|
@ -214,11 +191,13 @@ export class CheckList extends Feature {
|
||||||
*/
|
*/
|
||||||
build(colIndex, isLinked = false) {
|
build(colIndex, isLinked = false) {
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
colIndex = parseInt(colIndex, 10);
|
colIndex = Number(colIndex);
|
||||||
|
|
||||||
this.emitter.emit('before-populating-filter', tf, colIndex);
|
this.emitter.emit('before-populating-filter', tf, colIndex);
|
||||||
|
|
||||||
|
/** @inherited */
|
||||||
this.opts = [];
|
this.opts = [];
|
||||||
|
/** @inherited */
|
||||||
this.optsTxt = [];
|
this.optsTxt = [];
|
||||||
|
|
||||||
let flt = this.containers[colIndex];
|
let flt = this.containers[colIndex];
|
||||||
|
@ -227,71 +206,10 @@ export class CheckList extends Feature {
|
||||||
['colIndex', colIndex]);
|
['colIndex', colIndex]);
|
||||||
ul.className = this.filterCssClass;
|
ul.className = this.filterCssClass;
|
||||||
|
|
||||||
let rows = tf.tbl.rows;
|
|
||||||
let nbRows = tf.getRowsNb(true);
|
|
||||||
let caseSensitive = tf.caseSensitive;
|
let caseSensitive = tf.caseSensitive;
|
||||||
|
/** @inherited */
|
||||||
this.isCustom = tf.isCustomOptions(colIndex);
|
this.isCustom = tf.isCustomOptions(colIndex);
|
||||||
|
|
||||||
let activeIdx;
|
|
||||||
let activeFilterId = tf.getActiveFilterId();
|
|
||||||
if (isLinked && activeFilterId) {
|
|
||||||
activeIdx = tf.getColumnIndexFromFilterId(activeFilterId);
|
|
||||||
}
|
|
||||||
|
|
||||||
let filteredDataCol = [];
|
|
||||||
if (isLinked && tf.disableExcludedOptions) {
|
|
||||||
this.excludedOpts = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
flt.innerHTML = '';
|
|
||||||
|
|
||||||
for (let k = tf.refRow; k < nbRows; k++) {
|
|
||||||
// always visible rows don't need to appear on selects as always
|
|
||||||
// valid
|
|
||||||
if (tf.hasVisibleRows && tf.visibleRows.indexOf(k) !== -1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let cells = rows[k].cells;
|
|
||||||
let ncells = cells.length;
|
|
||||||
|
|
||||||
// checks if row has exact cell #
|
|
||||||
if (ncells !== tf.nbCells || this.isCustom) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// this loop retrieves cell data
|
|
||||||
for (let j = 0; j < ncells; j++) {
|
|
||||||
if (colIndex !== j) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (isLinked && !tf.disableExcludedOptions &&
|
|
||||||
(!tf.paging && !tf.isRowDisplayed(k)) ||
|
|
||||||
(tf.paging && activeIdx && !tf.isRowValid(k))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let cellValue = tf.getCellValue(cells[j]);
|
|
||||||
//Vary Peter's patch
|
|
||||||
let cellString = matchCase(cellValue, caseSensitive);
|
|
||||||
// checks if celldata is already in array
|
|
||||||
if (!has(this.opts, cellString, caseSensitive)) {
|
|
||||||
this.opts.push(cellValue);
|
|
||||||
}
|
|
||||||
let filteredCol = filteredDataCol[j];
|
|
||||||
if (isLinked && tf.disableExcludedOptions) {
|
|
||||||
if (!filteredCol) {
|
|
||||||
filteredCol = tf.getFilteredDataCol(j);
|
|
||||||
}
|
|
||||||
if (!has(filteredCol, cellString, caseSensitive) &&
|
|
||||||
!has(this.excludedOpts, cellString,
|
|
||||||
caseSensitive)) {
|
|
||||||
this.excludedOpts.push(cellValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Retrieves custom values
|
//Retrieves custom values
|
||||||
if (this.isCustom) {
|
if (this.isCustom) {
|
||||||
let customValues = tf.getCustomOptions(colIndex);
|
let customValues = tf.getCustomOptions(colIndex);
|
||||||
|
@ -299,48 +217,64 @@ export class CheckList extends Feature {
|
||||||
this.optsTxt = customValues[1];
|
this.optsTxt = customValues[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tf.sortSlc && !this.isCustom) {
|
let activeIdx;
|
||||||
if (!caseSensitive) {
|
let activeFilterId = tf.getActiveFilterId();
|
||||||
this.opts.sort(ignoreCase);
|
|
||||||
|
if (isLinked && activeFilterId) {
|
||||||
|
activeIdx = tf.getColumnIndexFromFilterId(activeFilterId);
|
||||||
|
}
|
||||||
|
|
||||||
|
let filteredDataCol = [];
|
||||||
|
if (isLinked && tf.disableExcludedOptions) {
|
||||||
|
/** @inherited */
|
||||||
|
this.excludedOpts = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
flt.innerHTML = '';
|
||||||
|
|
||||||
|
let eachRow = tf.eachRow();
|
||||||
|
eachRow(
|
||||||
|
(row) => {
|
||||||
|
let cellValue = tf.getCellValue(row.cells[colIndex]);
|
||||||
|
//Vary Peter's patch
|
||||||
|
let cellString = matchCase(cellValue, caseSensitive);
|
||||||
|
// checks if celldata is already in array
|
||||||
|
if (!has(this.opts, cellString, caseSensitive)) {
|
||||||
|
this.opts.push(cellValue);
|
||||||
|
}
|
||||||
|
let filteredCol = filteredDataCol[colIndex];
|
||||||
|
if (isLinked && tf.disableExcludedOptions) {
|
||||||
|
if (!filteredCol) {
|
||||||
|
filteredCol = tf.getVisibleColumnValues(colIndex);
|
||||||
|
}
|
||||||
|
if (!has(filteredCol, cellString, caseSensitive) &&
|
||||||
|
!has(this.excludedOpts, cellString, caseSensitive)) {
|
||||||
|
this.excludedOpts.push(cellValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// continue conditions function
|
||||||
|
(row, k) => {
|
||||||
|
// excluded rows don't need to appear on selects as always valid
|
||||||
|
if (tf.excludeRows.indexOf(k) !== -1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// checks if row has expected number of cells
|
||||||
|
if (row.cells.length !== tf.nbCells || this.isCustom) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLinked && !this.isValidLinkedValue(k, activeIdx)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
//sort options
|
||||||
|
this.opts = this.sortOptions(colIndex, this.opts);
|
||||||
if (this.excludedOpts) {
|
if (this.excludedOpts) {
|
||||||
this.excludedOpts.sort(ignoreCase);
|
this.excludedOpts = this.sortOptions(colIndex, this.excludedOpts);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.opts.sort();
|
|
||||||
if (this.excludedOpts) {
|
|
||||||
this.excludedOpts.sort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//asc sort
|
|
||||||
if (tf.sortNumAsc.indexOf(colIndex) !== -1) {
|
|
||||||
try {
|
|
||||||
this.opts.sort(numSortAsc);
|
|
||||||
if (this.excludedOpts) {
|
|
||||||
this.excludedOpts.sort(numSortAsc);
|
|
||||||
}
|
|
||||||
if (this.isCustom) {
|
|
||||||
this.optsTxt.sort(numSortAsc);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
throw new Error(SORT_ERROR.replace('{0}', colIndex)
|
|
||||||
.replace('{1}', 'ascending'));
|
|
||||||
}//in case there are alphanumeric values
|
|
||||||
}
|
|
||||||
//desc sort
|
|
||||||
if (tf.sortNumDesc.indexOf(colIndex) !== -1) {
|
|
||||||
try {
|
|
||||||
this.opts.sort(numSortDesc);
|
|
||||||
if (this.excludedOpts) {
|
|
||||||
this.excludedOpts.sort(numSortDesc);
|
|
||||||
}
|
|
||||||
if (this.isCustom) {
|
|
||||||
this.optsTxt.sort(numSortDesc);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
throw new Error(SORT_ERROR.replace('{0}', colIndex)
|
|
||||||
.replace('{1}', 'descending'));
|
|
||||||
}//in case there are alphanumeric values
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.addChecks(colIndex, ul);
|
this.addChecks(colIndex, ul);
|
||||||
|
@ -368,7 +302,9 @@ export class CheckList extends Feature {
|
||||||
let val = this.opts[y]; //item value
|
let val = this.opts[y]; //item value
|
||||||
let lbl = this.isCustom ? this.optsTxt[y] : val; //item text
|
let lbl = this.isCustom ? this.optsTxt[y] : val; //item text
|
||||||
let fltId = tf.fltIds[colIndex];
|
let fltId = tf.fltIds[colIndex];
|
||||||
let li = createCheckItem(`${fltId}_${(y + chkCt)}`, val, lbl);
|
let lblIdx = y + chkCt;
|
||||||
|
let li = createCheckItem(`${fltId}_${lblIdx}`, val, lbl,
|
||||||
|
['data-idx', lblIdx]);
|
||||||
li.className = this.itemCssClass;
|
li.className = this.itemCssClass;
|
||||||
|
|
||||||
if (tf.linkedFilters && tf.disableExcludedOptions &&
|
if (tf.linkedFilters && tf.disableExcludedOptions &&
|
||||||
|
@ -400,7 +336,7 @@ export class CheckList extends Feature {
|
||||||
let chkCt = 1;
|
let chkCt = 1;
|
||||||
let fltId = tf.fltIds[colIndex];
|
let fltId = tf.fltIds[colIndex];
|
||||||
let li0 = createCheckItem(`${fltId}_0`, '',
|
let li0 = createCheckItem(`${fltId}_0`, '',
|
||||||
tf.getClearFilterText(colIndex));
|
tf.getClearFilterText(colIndex), ['data-idx', 0]);
|
||||||
li0.className = this.itemCssClass;
|
li0.className = this.itemCssClass;
|
||||||
ul.appendChild(li0);
|
ul.appendChild(li0);
|
||||||
|
|
||||||
|
@ -412,7 +348,7 @@ export class CheckList extends Feature {
|
||||||
|
|
||||||
if (tf.enableEmptyOption) {
|
if (tf.enableEmptyOption) {
|
||||||
let li1 = createCheckItem(`${fltId}_1`, tf.emOperator,
|
let li1 = createCheckItem(`${fltId}_1`, tf.emOperator,
|
||||||
tf.emptyText);
|
tf.emptyText, ['data-idx', 1]);
|
||||||
li1.className = this.itemCssClass;
|
li1.className = this.itemCssClass;
|
||||||
ul.appendChild(li1);
|
ul.appendChild(li1);
|
||||||
addEvt(li1.check, 'click', evt => this.optionClick(evt));
|
addEvt(li1.check, 'click', evt => this.optionClick(evt));
|
||||||
|
@ -421,7 +357,7 @@ export class CheckList extends Feature {
|
||||||
|
|
||||||
if (tf.enableNonEmptyOption) {
|
if (tf.enableNonEmptyOption) {
|
||||||
let li2 = createCheckItem(`${fltId}_2`, tf.nmOperator,
|
let li2 = createCheckItem(`${fltId}_2`, tf.nmOperator,
|
||||||
tf.nonEmptyText);
|
tf.nonEmptyText, ['data-idx', 2]);
|
||||||
li2.className = this.itemCssClass;
|
li2.className = this.itemCssClass;
|
||||||
ul.appendChild(li2);
|
ul.appendChild(li2);
|
||||||
addEvt(li2.check, 'click', evt => this.optionClick(evt));
|
addEvt(li2.check, 'click', evt => this.optionClick(evt));
|
||||||
|
@ -431,83 +367,75 @@ export class CheckList extends Feature {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store checked options in DOM element attribute
|
* Set/unset value of passed item option in filter's DOM element attribute
|
||||||
* @param {Object} o checklist option DOM element
|
* @param {Object} o checklist option DOM element
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
setCheckListValues(o) {
|
setItemOption(o) {
|
||||||
if (!o) {
|
if (!o) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
let chkValue = o.value; //checked item value
|
let chkValue = o.value; //checked item value
|
||||||
// TODO: provide helper to extract column index, ugly!
|
let chkIndex = o.dataset.idx;
|
||||||
let chkIndex = parseInt(o.id.split('_')[2], 10);
|
|
||||||
let colIdx = tf.getColumnIndexFromFilterId(o.id);
|
let colIdx = tf.getColumnIndexFromFilterId(o.id);
|
||||||
let itemTag = 'LI';
|
|
||||||
|
|
||||||
let n = tf.getFilterElement(parseInt(colIdx, 10));
|
let n = tf.getFilterElement(parseInt(colIdx, 10));
|
||||||
let li = n.childNodes[chkIndex];
|
let items = n.childNodes;
|
||||||
let colIndex = n.getAttribute('colIndex');
|
let li = items[chkIndex];
|
||||||
let fltValue = n.getAttribute('value'); //filter value (ul tag)
|
//selected values (ul tag)
|
||||||
let fltIndexes = n.getAttribute('indexes'); //selected items (ul tag)
|
let slcValues = n.getAttribute('value') || '';
|
||||||
|
//selected items indexes (ul tag)
|
||||||
|
let slcIndexes = n.getAttribute('indexes') || '';
|
||||||
|
|
||||||
if (o.checked) {
|
if (o.checked) {
|
||||||
//show all item
|
//show all item
|
||||||
if (chkValue === '') {
|
if (chkValue === '') {
|
||||||
if ((fltIndexes && fltIndexes !== '')) {
|
|
||||||
//items indexes
|
//items indexes
|
||||||
let indSplit = fltIndexes.split(tf.separator);
|
let indexes = slcIndexes.split(tf.separator);
|
||||||
//checked items loop
|
indexes.forEach(idx => {
|
||||||
for (let u = 0; u < indSplit.length; u++) {
|
idx = Number(idx);
|
||||||
//checked item
|
let li = items[idx];
|
||||||
let cChk = elm(tf.fltIds[colIndex] + '_' +
|
let chx = tag(li, 'input')[0];
|
||||||
indSplit[u]);
|
if (chx && idx > 0) {
|
||||||
if (cChk) {
|
chx.checked = false;
|
||||||
cChk.checked = false;
|
removeClass(li, this.selectedItemCssClass);
|
||||||
removeClass(n.childNodes[indSplit[u]],
|
|
||||||
this.selectedItemCssClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
n.setAttribute('value', '');
|
n.setAttribute('value', '');
|
||||||
n.setAttribute('indexes', '');
|
n.setAttribute('indexes', '');
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
fltValue = (fltValue) ? fltValue : '';
|
let indexes = slcIndexes + chkIndex + tf.separator;
|
||||||
chkValue = trim(fltValue + ' ' + chkValue + ' ' +
|
let values =
|
||||||
tf.orOperator);
|
trim(slcValues + ' ' + chkValue + ' ' + tf.orOperator);
|
||||||
chkIndex = fltIndexes + chkIndex + tf.separator;
|
|
||||||
n.setAttribute('value', chkValue);
|
n.setAttribute('value', values);
|
||||||
n.setAttribute('indexes', chkIndex);
|
n.setAttribute('indexes', indexes);
|
||||||
//1st option unchecked
|
|
||||||
if (elm(tf.fltIds[colIndex] + '_0')) {
|
//uncheck first option
|
||||||
elm(tf.fltIds[colIndex] + '_0').checked = false;
|
let chx0 = tag(items[0], 'input')[0];
|
||||||
|
if (chx0) {
|
||||||
|
chx0.checked = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (li.nodeName === itemTag) {
|
removeClass(items[0], this.selectedItemCssClass);
|
||||||
removeClass(n.childNodes[0], this.selectedItemCssClass);
|
|
||||||
addClass(li, this.selectedItemCssClass);
|
addClass(li, this.selectedItemCssClass);
|
||||||
}
|
|
||||||
} else { //removes values and indexes
|
} else { //removes values and indexes
|
||||||
if (chkValue !== '') {
|
let replaceValue =
|
||||||
let replaceValue = new RegExp(
|
new RegExp(rgxEsc(chkValue + ' ' + tf.orOperator));
|
||||||
rgxEsc(chkValue + ' ' + tf.orOperator));
|
let values = slcValues.replace(replaceValue, '');
|
||||||
fltValue = fltValue.replace(replaceValue, '');
|
let replaceIndex = new RegExp(rgxEsc(chkIndex + tf.separator));
|
||||||
n.setAttribute('value', trim(fltValue));
|
let indexes = slcIndexes.replace(replaceIndex, '');
|
||||||
|
|
||||||
|
n.setAttribute('value', trim(values));
|
||||||
|
n.setAttribute('indexes', indexes);
|
||||||
|
|
||||||
let replaceIndex = new RegExp(
|
|
||||||
rgxEsc(chkIndex + tf.separator));
|
|
||||||
fltIndexes = fltIndexes.replace(replaceIndex, '');
|
|
||||||
n.setAttribute('indexes', fltIndexes);
|
|
||||||
}
|
|
||||||
if (li.nodeName === itemTag) {
|
|
||||||
removeClass(li, this.selectedItemCssClass);
|
removeClass(li, this.selectedItemCssClass);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select filter options programmatically
|
* Select filter options programmatically
|
||||||
|
@ -517,39 +445,36 @@ export class CheckList extends Feature {
|
||||||
selectOptions(colIndex, values = []) {
|
selectOptions(colIndex, values = []) {
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
let flt = tf.getFilterElement(colIndex);
|
let flt = tf.getFilterElement(colIndex);
|
||||||
if (tf.getFilterType(colIndex) !== CHECKLIST || !flt ||
|
if (!flt || values.length === 0) {
|
||||||
values.length === 0) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let lisNb = tag(flt, 'li').length;
|
let lis = tag(flt, 'li');
|
||||||
|
|
||||||
flt.setAttribute('value', '');
|
flt.setAttribute('value', '');
|
||||||
flt.setAttribute('indexes', '');
|
flt.setAttribute('indexes', '');
|
||||||
|
|
||||||
for (let k = 0; k < lisNb; k++) {
|
[].forEach.call(lis, (li) => {
|
||||||
let li = tag(flt, 'li')[k];
|
|
||||||
let lbl = tag(li, 'label')[0];
|
|
||||||
let chk = tag(li, 'input')[0];
|
let chk = tag(li, 'input')[0];
|
||||||
let lblTxt = matchCase(getText(lbl), tf.caseSensitive);
|
let chkVal = matchCase(chk.value, tf.caseSensitive);
|
||||||
|
|
||||||
if (lblTxt !== '' && has(values, lblTxt, tf.caseSensitive)) {
|
if (chkVal !== '' && has(values, chkVal, tf.caseSensitive)) {
|
||||||
chk.checked = true;
|
chk.checked = true;
|
||||||
} else {
|
} else {
|
||||||
// Check non-empty-text or empty-text option
|
// Check non-empty-text or empty-text option
|
||||||
if (values.indexOf(tf.nmOperator) !== -1 &&
|
if (values.indexOf(tf.nmOperator) !== -1 &&
|
||||||
lblTxt === matchCase(tf.nonEmptyText, tf.caseSensitive)) {
|
chkVal === matchCase(tf.nonEmptyText, tf.caseSensitive)) {
|
||||||
chk.checked = true;
|
chk.checked = true;
|
||||||
}
|
}
|
||||||
else if (values.indexOf(tf.emOperator) !== -1 &&
|
else if (values.indexOf(tf.emOperator) !== -1 &&
|
||||||
lblTxt === matchCase(tf.emptyText, tf.caseSensitive)) {
|
chkVal === matchCase(tf.emptyText, tf.caseSensitive)) {
|
||||||
chk.checked = true;
|
chk.checked = true;
|
||||||
} else {
|
} else {
|
||||||
chk.checked = false;
|
chk.checked = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.setCheckListValues(chk);
|
this.setItemOption(chk);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -560,9 +485,12 @@ export class CheckList extends Feature {
|
||||||
getValues(colIndex) {
|
getValues(colIndex) {
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
let flt = tf.getFilterElement(colIndex);
|
let flt = tf.getFilterElement(colIndex);
|
||||||
|
if (!flt) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
let fltAttr = flt.getAttribute('value');
|
let fltAttr = flt.getAttribute('value');
|
||||||
let values = isEmpty(fltAttr) ? '' : fltAttr;
|
let values = isEmpty(fltAttr) ? '' : fltAttr;
|
||||||
|
|
||||||
//removes last operator ||
|
//removes last operator ||
|
||||||
values = values.substr(0, values.length - 3);
|
values = values.substr(0, values.length - 3);
|
||||||
//turn || separated values into array
|
//turn || separated values into array
|
||||||
|
@ -584,6 +512,7 @@ export class CheckList extends Feature {
|
||||||
(tf, colIndex, values) => this.selectOptions(colIndex, values)
|
(tf, colIndex, values) => this.selectOptions(colIndex, values)
|
||||||
);
|
);
|
||||||
this.emitter.off(['rows-changed'], () => this.refreshAll());
|
this.emitter.off(['rows-changed'], () => this.refreshAll());
|
||||||
|
this.emitter.off(['after-filtering'], () => this.linkFilters());
|
||||||
|
|
||||||
this.initialized = false;
|
this.initialized = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
import {Feature} from '../feature';
|
import {Feature} from '../feature';
|
||||||
import {createElm, createText, elm, removeElm} from '../dom';
|
import {createElm, createText, elm, removeElm} from '../dom';
|
||||||
import {addEvt} from '../event';
|
import {addEvt} from '../event';
|
||||||
|
import {defaultsStr} from '../settings';
|
||||||
|
import {isNull} from '../types';
|
||||||
|
import {RIGHT} from './toolbar';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear button UI component
|
* Clear button UI component
|
||||||
|
@ -12,15 +15,48 @@ export class ClearButton extends Feature {
|
||||||
* @param {TableFilter} tf TableFilter instance
|
* @param {TableFilter} tf TableFilter instance
|
||||||
*/
|
*/
|
||||||
constructor(tf) {
|
constructor(tf) {
|
||||||
super(tf, 'btnReset');
|
super(tf, ClearButton);
|
||||||
|
|
||||||
let f = this.config;
|
let f = this.config.btn_reset || {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Container element ID
|
* Container element ID
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.targetId = f.btn_reset_target_id || null;
|
this.targetId = defaultsStr(f.target_id, null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Text for the clear button
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
this.text = defaultsStr(f.text, null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Css class for reset button
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
this.cssClass = defaultsStr(f.css_class, 'reset');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tooltip text for the clear button
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
this.tooltip = f.tooltip || 'Clear filters';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom Html string for the clear button
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
this.html = defaultsStr(f.html,
|
||||||
|
(!tf.enableIcons || this.text ? null :
|
||||||
|
'<input type="button" value="" class="' + this.cssClass +
|
||||||
|
'" ' + 'title="' + this.tooltip + '" />'));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default position in toolbar ('left'|'center'|'right')
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
this.toolbarPosition = defaultsStr(f.toolbar_position, RIGHT);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear button container element
|
* Clear button container element
|
||||||
|
@ -35,33 +71,6 @@ export class ClearButton extends Feature {
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.element = null;
|
this.element = null;
|
||||||
|
|
||||||
/**
|
|
||||||
* Text for the clear button
|
|
||||||
* @type {String}
|
|
||||||
*/
|
|
||||||
this.text = f.btn_reset_text || 'Reset';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Css class for reset button
|
|
||||||
* @type {String}
|
|
||||||
*/
|
|
||||||
this.cssClass = f.btn_reset_css_class || 'reset';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tooltip text for the clear button
|
|
||||||
* @type {String}
|
|
||||||
*/
|
|
||||||
this.tooltip = f.btn_reset_tooltip || 'Clear filters';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Custom Html string for the clear button
|
|
||||||
* @type {String}
|
|
||||||
*/
|
|
||||||
this.html = f.btn_reset_html ||
|
|
||||||
(!tf.enableIcons ? null :
|
|
||||||
'<input type="button" value="" class="' + this.cssClass +
|
|
||||||
'" ' + 'title="' + this.tooltip + '" />');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -85,13 +94,13 @@ export class ClearButton extends Feature {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.emitter.emit('initializing-feature', this, !isNull(this.targetId));
|
||||||
|
|
||||||
let cont = createElm('span');
|
let cont = createElm('span');
|
||||||
|
|
||||||
// reset button is added to defined element
|
let targetEl = !this.targetId ?
|
||||||
if (!this.targetId) {
|
tf.feature('toolbar').container(this.toolbarPosition) :
|
||||||
tf.setToolbar();
|
elm(this.targetId);
|
||||||
}
|
|
||||||
let targetEl = !this.targetId ? tf.rDiv : elm(this.targetId);
|
|
||||||
targetEl.appendChild(cont);
|
targetEl.appendChild(cont);
|
||||||
|
|
||||||
if (!this.html) {
|
if (!this.html) {
|
||||||
|
@ -110,6 +119,8 @@ export class ClearButton extends Feature {
|
||||||
|
|
||||||
/** @inherited */
|
/** @inherited */
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
|
|
||||||
|
this.emitter.emit('feature-initialized', this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -126,3 +137,6 @@ export class ClearButton extends Feature {
|
||||||
this.initialized = false;
|
this.initialized = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: remove as soon as feature name is fixed
|
||||||
|
ClearButton.meta = {altName: 'btnReset'};
|
||||||
|
|
|
@ -17,7 +17,7 @@ export class DateType extends Feature {
|
||||||
* @param {TableFilter} tf TableFilter instance
|
* @param {TableFilter} tf TableFilter instance
|
||||||
*/
|
*/
|
||||||
constructor(tf) {
|
constructor(tf) {
|
||||||
super(tf, 'dateType');
|
super(tf, DateType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global locale
|
* Global locale
|
||||||
|
@ -94,6 +94,16 @@ export class DateType extends Feature {
|
||||||
return isObj(colType) ? colType : {};
|
return isObj(colType) ? colType : {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the locale code for supplied column index as per configuration
|
||||||
|
* or global setting
|
||||||
|
* @param {Number} colIndex Column index
|
||||||
|
* @returns {String} Locale code (ie: 'en-us')
|
||||||
|
*/
|
||||||
|
getLocale(colIndex) {
|
||||||
|
return this.getOptions(colIndex).locale || this.locale;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add date time format(s) to a locale as specified by the passed
|
* Add date time format(s) to a locale as specified by the passed
|
||||||
* collection of column types, ie:
|
* collection of column types, ie:
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
import {Feature} from '../feature';
|
import {BaseDropdown} from './baseDropdown';
|
||||||
import {createElm, createOpt, elm} from '../dom';
|
import {createElm, createOpt, elm} from '../dom';
|
||||||
import {has} from '../array';
|
import {has} from '../array';
|
||||||
import {matchCase} from '../string';
|
import {matchCase} from '../string';
|
||||||
import {ignoreCase, numSortAsc, numSortDesc} from '../sort';
|
|
||||||
import {addEvt, targetEvt} from '../event';
|
import {addEvt, targetEvt} from '../event';
|
||||||
import {SELECT, MULTIPLE, NONE} from '../const';
|
import {SELECT, MULTIPLE, NONE} from '../const';
|
||||||
|
import {defaultsStr, defaultsBool} from '../settings';
|
||||||
const SORT_ERROR = 'Filter options for column {0} cannot be sorted in ' +
|
|
||||||
'{1} manner.';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dropdown filter UI component
|
* Dropdown filter UI component
|
||||||
|
* @export
|
||||||
|
* @class Dropdown
|
||||||
|
* @extends {BaseDropdown}
|
||||||
*/
|
*/
|
||||||
export class Dropdown extends Feature {
|
export class Dropdown extends BaseDropdown {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an instance of Dropdown
|
* Creates an instance of Dropdown
|
||||||
* @param {TableFilter} tf TableFilter instance
|
* @param {TableFilter} tf TableFilter instance
|
||||||
*/
|
*/
|
||||||
constructor(tf) {
|
constructor(tf) {
|
||||||
super(tf, 'dropdown');
|
super(tf, Dropdown);
|
||||||
|
|
||||||
// Configuration object
|
// Configuration object
|
||||||
let f = this.config;
|
let f = this.config;
|
||||||
|
@ -28,41 +28,21 @@ export class Dropdown extends Feature {
|
||||||
* Enable the reset filter option as first item
|
* Enable the reset filter option as first item
|
||||||
* @type {Boolean}
|
* @type {Boolean}
|
||||||
*/
|
*/
|
||||||
this.enableSlcResetFilter = f.enable_slc_reset_filter === false ?
|
this.enableSlcResetFilter =
|
||||||
false : true;
|
defaultsBool(f.enable_slc_reset_filter, true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Non empty option text
|
* Non empty option text
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.nonEmptyText = f.non_empty_text || '(Non empty)';
|
this.nonEmptyText = defaultsStr(f.non_empty_text, '(Non empty)');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tooltip text appearing on multiple select
|
* Tooltip text appearing on multiple select
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.multipleSlcTooltip = f.multiple_slc_tooltip ||
|
this.multipleSlcTooltip = defaultsStr(f.multiple_slc_tooltip,
|
||||||
'Use Ctrl/Cmd key for multiple selections';
|
'Use Ctrl/Cmd key for multiple selections');
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates drop-down has custom options
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.isCustom = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of options values
|
|
||||||
* @type {Array}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.opts = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of options texts for custom values
|
|
||||||
* @type {Array}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.optsTxt = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -96,15 +76,10 @@ export class Dropdown extends Feature {
|
||||||
* Refresh all drop-down filters
|
* Refresh all drop-down filters
|
||||||
*/
|
*/
|
||||||
refreshAll() {
|
refreshAll() {
|
||||||
let tf = this.tf;
|
let selectFlts = this.tf.getFiltersByType(SELECT, true);
|
||||||
let selectFlts = tf.getFiltersByType(SELECT, true);
|
let multipleFlts = this.tf.getFiltersByType(MULTIPLE, true);
|
||||||
let multipleFlts = tf.getFiltersByType(MULTIPLE, true);
|
let colIdxs = selectFlts.concat(multipleFlts);
|
||||||
let flts = selectFlts.concat(multipleFlts);
|
this.refreshFilters(colIdxs);
|
||||||
flts.forEach((colIdx) => {
|
|
||||||
let values = this.getValues(colIdx);
|
|
||||||
this.build(colIdx, tf.linkedFilters);
|
|
||||||
this.selectOptions(colIdx, values);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -117,7 +92,7 @@ export class Dropdown extends Feature {
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
let col = tf.getFilterType(colIndex);
|
let col = tf.getFilterType(colIndex);
|
||||||
let externalFltTgtId = isExternal ?
|
let externalFltTgtId = isExternal ?
|
||||||
tf.externalFltTgtIds[colIndex] : null;
|
tf.externalFltIds[colIndex] : null;
|
||||||
|
|
||||||
let slc = createElm(SELECT,
|
let slc = createElm(SELECT,
|
||||||
['id', tf.buildFilterId(colIndex)],
|
['id', tf.buildFilterId(colIndex)],
|
||||||
|
@ -162,6 +137,8 @@ export class Dropdown extends Feature {
|
||||||
);
|
);
|
||||||
this.emitter.on(['rows-changed'], () => this.refreshAll());
|
this.emitter.on(['rows-changed'], () => this.refreshAll());
|
||||||
|
|
||||||
|
this.emitter.on(['after-filtering'], () => this.linkFilters());
|
||||||
|
|
||||||
/** @inherited */
|
/** @inherited */
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
}
|
}
|
||||||
|
@ -173,21 +150,28 @@ export class Dropdown extends Feature {
|
||||||
*/
|
*/
|
||||||
build(colIndex, isLinked = false) {
|
build(colIndex, isLinked = false) {
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
colIndex = parseInt(colIndex, 10);
|
colIndex = Number(colIndex);
|
||||||
|
|
||||||
this.emitter.emit('before-populating-filter', tf, colIndex);
|
this.emitter.emit('before-populating-filter', tf, colIndex);
|
||||||
|
|
||||||
|
/** @inherited */
|
||||||
this.opts = [];
|
this.opts = [];
|
||||||
|
/** @inherited */
|
||||||
this.optsTxt = [];
|
this.optsTxt = [];
|
||||||
|
|
||||||
let slcId = tf.fltIds[colIndex];
|
let slc = tf.getFilterElement(colIndex);
|
||||||
let slc = elm(slcId);
|
|
||||||
let rows = tf.tbl.rows;
|
|
||||||
let nbRows = tf.getRowsNb(true);
|
|
||||||
|
|
||||||
//custom select test
|
//custom select test
|
||||||
|
/** @inherited */
|
||||||
this.isCustom = tf.isCustomOptions(colIndex);
|
this.isCustom = tf.isCustomOptions(colIndex);
|
||||||
|
|
||||||
|
//Retrieves custom values
|
||||||
|
if (this.isCustom) {
|
||||||
|
let customValues = tf.getCustomOptions(colIndex);
|
||||||
|
this.opts = customValues[0];
|
||||||
|
this.optsTxt = customValues[1];
|
||||||
|
}
|
||||||
|
|
||||||
//custom selects text
|
//custom selects text
|
||||||
let activeIdx;
|
let activeIdx;
|
||||||
let activeFilterId = tf.getActiveFilterId();
|
let activeFilterId = tf.getActiveFilterId();
|
||||||
|
@ -202,35 +186,12 @@ export class Dropdown extends Feature {
|
||||||
filteredDataCol = [];
|
filteredDataCol = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let k = tf.refRow; k < nbRows; k++) {
|
let eachRow = tf.eachRow();
|
||||||
// always visible rows don't need to appear on selects as always
|
eachRow(
|
||||||
// valid
|
(row) => {
|
||||||
if (tf.hasVisibleRows && tf.visibleRows.indexOf(k) !== -1) {
|
let cellValue = tf.getCellValue(row.cells[colIndex]);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let cell = rows[k].cells,
|
|
||||||
nchilds = cell.length;
|
|
||||||
|
|
||||||
// checks if row has exact cell #
|
|
||||||
if (nchilds !== tf.nbCells || this.isCustom) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// this loop retrieves cell data
|
|
||||||
for (let j = 0; j < nchilds; j++) {
|
|
||||||
if (colIndex !== j) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (isLinked && !tf.disableExcludedOptions &&
|
|
||||||
(!tf.paging && !tf.isRowDisplayed(k)) ||
|
|
||||||
(tf.paging && activeIdx && !tf.isRowValid(k))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let cellValue = tf.getCellValue(cell[j]),
|
|
||||||
//Vary Peter's patch
|
//Vary Peter's patch
|
||||||
cellString = matchCase(cellValue, tf.caseSensitive);
|
let cellString = matchCase(cellValue, tf.caseSensitive);
|
||||||
|
|
||||||
// checks if celldata is already in array
|
// checks if celldata is already in array
|
||||||
if (!has(this.opts, cellString, tf.caseSensitive)) {
|
if (!has(this.opts, cellString, tf.caseSensitive)) {
|
||||||
|
@ -238,66 +199,38 @@ export class Dropdown extends Feature {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLinked && tf.disableExcludedOptions) {
|
if (isLinked && tf.disableExcludedOptions) {
|
||||||
let filteredCol = filteredDataCol[j];
|
let filteredCol = filteredDataCol[colIndex];
|
||||||
if (!filteredCol) {
|
if (!filteredCol) {
|
||||||
filteredCol = tf.getFilteredDataCol(j);
|
filteredCol = tf.getVisibleColumnValues(colIndex);
|
||||||
}
|
}
|
||||||
if (!has(filteredCol, cellString, tf.caseSensitive) &&
|
if (!has(filteredCol, cellString, tf.caseSensitive) &&
|
||||||
!has(excludedOpts, cellString, tf.caseSensitive)) {
|
!has(excludedOpts, cellString, tf.caseSensitive)) {
|
||||||
excludedOpts.push(cellValue);
|
excludedOpts.push(cellValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}//for j
|
},
|
||||||
}//for k
|
// continue conditions function
|
||||||
|
(row, k) => {
|
||||||
//Retrieves custom values
|
// excluded rows don't need to appear on selects as always valid
|
||||||
if (this.isCustom) {
|
if (tf.excludeRows.indexOf(k) !== -1) {
|
||||||
let customValues = tf.getCustomOptions(colIndex);
|
return true;
|
||||||
this.opts = customValues[0];
|
|
||||||
this.optsTxt = customValues[1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tf.sortSlc && !this.isCustom) {
|
// checks if row has expected number of cells
|
||||||
if (!tf.caseSensitive) {
|
if (row.cells.length !== tf.nbCells || this.isCustom) {
|
||||||
this.opts.sort(ignoreCase);
|
return true;
|
||||||
if (excludedOpts) {
|
|
||||||
excludedOpts.sort(ignoreCase);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.opts.sort();
|
|
||||||
if (excludedOpts) { excludedOpts.sort(); }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//asc sort
|
if (isLinked && !this.isValidLinkedValue(k, activeIdx)) {
|
||||||
if (tf.sortNumAsc.indexOf(colIndex) !== -1) {
|
return true;
|
||||||
try {
|
}
|
||||||
this.opts.sort(numSortAsc);
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
//sort options
|
||||||
|
this.opts = this.sortOptions(colIndex, this.opts);
|
||||||
if (excludedOpts) {
|
if (excludedOpts) {
|
||||||
excludedOpts.sort(numSortAsc);
|
excludedOpts = this.sortOptions(colIndex, excludedOpts);
|
||||||
}
|
|
||||||
if (this.isCustom) {
|
|
||||||
this.optsTxt.sort(numSortAsc);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
throw new Error(SORT_ERROR.replace('{0}', colIndex)
|
|
||||||
.replace('{1}', 'ascending'));
|
|
||||||
}//in case there are alphanumeric values
|
|
||||||
}
|
|
||||||
//desc sort
|
|
||||||
if (tf.sortNumDesc.indexOf(colIndex) !== -1) {
|
|
||||||
try {
|
|
||||||
this.opts.sort(numSortDesc);
|
|
||||||
if (excludedOpts) {
|
|
||||||
excludedOpts.sort(numSortDesc);
|
|
||||||
}
|
|
||||||
if (this.isCustom) {
|
|
||||||
this.optsTxt.sort(numSortDesc);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
throw new Error(SORT_ERROR.replace('{0}', colIndex)
|
|
||||||
.replace('{1}', 'ascending'));
|
|
||||||
}//in case there are alphanumeric values
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//populates drop-down
|
//populates drop-down
|
||||||
|
@ -437,6 +370,7 @@ export class Dropdown extends Feature {
|
||||||
(tf, colIndex, values) => this.selectOptions(colIndex, values)
|
(tf, colIndex, values) => this.selectOptions(colIndex, values)
|
||||||
);
|
);
|
||||||
this.emitter.off(['rows-changed'], () => this.refreshAll());
|
this.emitter.off(['rows-changed'], () => this.refreshAll());
|
||||||
|
this.emitter.off(['after-filtering'], () => this.linkFilters());
|
||||||
this.initialized = false;
|
this.initialized = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,9 @@ import {createElm, removeElm, elm, tag} from '../dom';
|
||||||
import {addEvt, targetEvt} from '../event';
|
import {addEvt, targetEvt} from '../event';
|
||||||
import {contains} from '../string';
|
import {contains} from '../string';
|
||||||
import {NONE} from '../const';
|
import {NONE} from '../const';
|
||||||
|
import {
|
||||||
|
defaultsBool, defaultsStr, defaultsNb, defaultsArr
|
||||||
|
} from '../settings';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Grid layout, table with fixed headers
|
* Grid layout, table with fixed headers
|
||||||
|
@ -14,77 +17,76 @@ export class GridLayout extends Feature {
|
||||||
* @param {TableFilter} tf TableFilter instance
|
* @param {TableFilter} tf TableFilter instance
|
||||||
*/
|
*/
|
||||||
constructor(tf) {
|
constructor(tf) {
|
||||||
super(tf, 'gridLayout');
|
super(tf, GridLayout);
|
||||||
|
|
||||||
let f = this.config;
|
let f = this.config.grid_layout || {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Grid-layout container width as CSS string
|
* Grid-layout container width as CSS string
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.width = f.grid_width || null;
|
this.width = defaultsStr(f.width, null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Grid-layout container height as CSS string
|
* Grid-layout container height as CSS string
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.height = f.grid_height || null;
|
this.height = defaultsStr(f.height, null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for main container element
|
* Css class for main container element
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.mainContCssClass = f.grid_cont_css_class || 'grd_Cont';
|
this.mainContCssClass = defaultsStr(f.cont_css_class, 'grd_Cont');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for body table container element
|
* Css class for body table container element
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.contCssClass = f.grid_tbl_cont_css_class || 'grd_tblCont';
|
this.contCssClass = defaultsStr(f.tbl_cont_css_class, 'grd_tblCont');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for headers table container element
|
* Css class for headers table container element
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.headContCssClass = f.grid_tblHead_cont_css_class ||
|
this.headContCssClass = defaultsStr(f.tbl_head_css_class,
|
||||||
'grd_headTblCont';
|
'grd_headTblCont');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for toolbar container element (rows counter, paging etc.)
|
* Css class for toolbar container element (rows counter, paging etc.)
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.infDivCssClass = f.grid_inf_grid_css_class || 'grd_inf';
|
this.infDivCssClass = defaultsStr(f.inf_grid_css_class, 'grd_inf');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Index of the headers row, default: 0
|
* Index of the headers row, default: 0
|
||||||
* @type {Number}
|
* @type {Number}
|
||||||
*/
|
*/
|
||||||
this.headRowIndex = f.grid_headers_row_index || 0;
|
this.headRowIndex = defaultsNb(f.headers_row_index, 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collection of the header row indexes to be moved into headers table
|
* Collection of the header row indexes to be moved into headers table
|
||||||
* @type {Array}
|
* @type {Array}
|
||||||
*/
|
*/
|
||||||
this.headRows = f.grid_headers_rows || [0];
|
this.headRows = defaultsArr(f.headers_rows, [0]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable or disable column filters generation, default: true
|
* Enable or disable column filters generation, default: true
|
||||||
* @type {Boolean}
|
* @type {Boolean}
|
||||||
*/
|
*/
|
||||||
this.enableFilters = f.grid_enable_default_filters === false ?
|
this.filters = defaultsBool(f.filters, true);
|
||||||
false : true;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable or disable column headers, default: false
|
* Enable or disable column headers, default: false
|
||||||
* @type {Boolean}
|
* @type {Boolean}
|
||||||
*/
|
*/
|
||||||
this.noHeaders = Boolean(f.grid_no_headers);
|
this.noHeaders = Boolean(f.no_headers);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Grid-layout default column widht as CSS string
|
* Grid-layout default column widht as CSS string
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.defaultColWidth = f.grid_default_col_width || '100px';
|
this.defaultColWidth = defaultsStr(f.default_col_width, '100px');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of column elements
|
* List of column elements
|
||||||
|
@ -112,14 +114,14 @@ export class GridLayout extends Feature {
|
||||||
* @type {String}
|
* @type {String}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.sourceTblHtml = tf.tbl.outerHTML;
|
this.sourceTblHtml = tf.dom().outerHTML;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates if working table has column elements
|
* Indicates if working table has column elements
|
||||||
* @type {Boolean}
|
* @type {Boolean}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.tblHasColTag = tag(tf.tbl, 'col').length > 0 ? true : false;
|
this.tblHasColTag = tag(tf.dom(), 'col').length > 0 ? true : false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main container element
|
* Main container element
|
||||||
|
@ -146,7 +148,7 @@ export class GridLayout extends Feature {
|
||||||
this.headTbl = null;
|
this.headTbl = null;
|
||||||
|
|
||||||
// filters flag at TF level
|
// filters flag at TF level
|
||||||
tf.fltGrid = this.enableFilters;
|
tf.fltGrid = this.filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -155,7 +157,7 @@ export class GridLayout extends Feature {
|
||||||
*/
|
*/
|
||||||
init() {
|
init() {
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
let tbl = tf.tbl;
|
let tbl = tf.dom();
|
||||||
|
|
||||||
if (this.initialized) {
|
if (this.initialized) {
|
||||||
return;
|
return;
|
||||||
|
@ -167,9 +169,6 @@ export class GridLayout extends Feature {
|
||||||
// Assign default column widths
|
// Assign default column widths
|
||||||
this.setDefaultColWidths();
|
this.setDefaultColWidths();
|
||||||
|
|
||||||
// Initial table width
|
|
||||||
let tblW = this.initialTableWidth();
|
|
||||||
|
|
||||||
//Main container: it will contain all the elements
|
//Main container: it will contain all the elements
|
||||||
this.tblMainCont = this.createContainer(
|
this.tblMainCont = this.createContainer(
|
||||||
'div', this.mainContCssClass);
|
'div', this.mainContCssClass);
|
||||||
|
@ -190,6 +189,7 @@ export class GridLayout extends Feature {
|
||||||
|
|
||||||
//In case table width is expressed in %
|
//In case table width is expressed in %
|
||||||
if (tbl.style.width === '') {
|
if (tbl.style.width === '') {
|
||||||
|
let tblW = this.initialTableWidth();
|
||||||
tbl.style.width = (contains('%', tblW) ?
|
tbl.style.width = (contains('%', tblW) ?
|
||||||
tbl.clientWidth : tblW) + 'px';
|
tbl.clientWidth : tblW) + 'px';
|
||||||
}
|
}
|
||||||
|
@ -200,7 +200,6 @@ export class GridLayout extends Feature {
|
||||||
//Headers table container: div wrapping headers table
|
//Headers table container: div wrapping headers table
|
||||||
this.headTblCont = this.createContainer(
|
this.headTblCont = this.createContainer(
|
||||||
'div', this.headContCssClass);
|
'div', this.headContCssClass);
|
||||||
this.setConfigWidth(this.headTblCont);
|
|
||||||
|
|
||||||
//Headers table
|
//Headers table
|
||||||
this.headTbl = createElm('table');
|
this.headTbl = createElm('table');
|
||||||
|
@ -233,22 +232,16 @@ export class GridLayout extends Feature {
|
||||||
tbl.removeChild(thead[0]);
|
tbl.removeChild(thead[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Headers table style
|
// ensure table layout is always set even if already set in css
|
||||||
|
// definitions, potentially with custom css class this could be lost
|
||||||
this.headTbl.style.tableLayout = 'fixed';
|
this.headTbl.style.tableLayout = 'fixed';
|
||||||
tbl.style.tableLayout = 'fixed';
|
tbl.style.tableLayout = 'fixed';
|
||||||
this.headTbl.cellPadding = tbl.cellPadding;
|
|
||||||
this.headTbl.cellSpacing = tbl.cellSpacing;
|
|
||||||
// this.headTbl.style.width = tbl.style.width;
|
|
||||||
|
|
||||||
//content table without headers needs col widths to be reset
|
//content table without headers needs col widths to be reset
|
||||||
tf.setColWidths(this.headTbl);
|
tf.setColWidths(this.headTbl);
|
||||||
|
|
||||||
//Headers container width
|
//Headers container width
|
||||||
// this.headTblCont.style.width = this.tblCont.clientWidth+'px';
|
this.headTbl.style.width = tbl.style.width;
|
||||||
|
|
||||||
tbl.style.width = '';
|
|
||||||
//
|
|
||||||
this.headTbl.style.width = tbl.clientWidth + 'px';
|
|
||||||
//
|
//
|
||||||
|
|
||||||
//scroll synchronisation
|
//scroll synchronisation
|
||||||
|
@ -288,10 +281,6 @@ export class GridLayout extends Feature {
|
||||||
filtersRow.style.display = NONE;
|
filtersRow.style.display = NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tbl.clientWidth !== this.headTbl.clientWidth) {
|
|
||||||
tbl.style.width = this.headTbl.clientWidth + 'px';
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @inherited */
|
/** @inherited */
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
}
|
}
|
||||||
|
@ -305,7 +294,6 @@ export class GridLayout extends Feature {
|
||||||
tf.refRow = 0;
|
tf.refRow = 0;
|
||||||
tf.headersRow = 0;
|
tf.headersRow = 0;
|
||||||
tf.filtersRowIndex = 1;
|
tf.filtersRowIndex = 1;
|
||||||
tf.isExternalFlt = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -314,12 +302,13 @@ export class GridLayout extends Feature {
|
||||||
*/
|
*/
|
||||||
setDefaultColWidths() {
|
setDefaultColWidths() {
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
if (tf.hasColWidths) {
|
if (tf.colWidths.length > 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (let k = 0, len = tf.getCellsNb(); k < len; k++) {
|
|
||||||
|
tf.eachCol((k) => {
|
||||||
let colW;
|
let colW;
|
||||||
let cell = tf.tbl.rows[tf.getHeadersRowIndex()].cells[k];
|
let cell = tf.dom().rows[tf.getHeadersRowIndex()].cells[k];
|
||||||
if (cell.width !== '') {
|
if (cell.width !== '') {
|
||||||
colW = cell.width;
|
colW = cell.width;
|
||||||
} else if (cell.style.width !== '') {
|
} else if (cell.style.width !== '') {
|
||||||
|
@ -328,8 +317,8 @@ export class GridLayout extends Feature {
|
||||||
colW = this.defaultColWidth;
|
colW = this.defaultColWidth;
|
||||||
}
|
}
|
||||||
tf.colWidths[k] = colW;
|
tf.colWidths[k] = colW;
|
||||||
}
|
});
|
||||||
tf.hasColWidths = true;
|
|
||||||
tf.setColWidths();
|
tf.setColWidths();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,7 +328,7 @@ export class GridLayout extends Feature {
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
initialTableWidth() {
|
initialTableWidth() {
|
||||||
let tbl = this.tf.tbl;
|
let tbl = this.tf.dom();
|
||||||
let width; //initial table width
|
let width; //initial table width
|
||||||
|
|
||||||
if (tbl.width !== '') {
|
if (tbl.width !== '') {
|
||||||
|
@ -374,14 +363,14 @@ export class GridLayout extends Feature {
|
||||||
createFiltersRow() {
|
createFiltersRow() {
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
let filtersRow = createElm('tr');
|
let filtersRow = createElm('tr');
|
||||||
if (this.enableFilters && tf.fltGrid) {
|
if (this.filters && tf.fltGrid) {
|
||||||
tf.externalFltTgtIds = [];
|
tf.externalFltIds = [];
|
||||||
for (let j = 0; j < tf.getCellsNb(); j++) {
|
tf.eachCol((j) => {
|
||||||
let fltTdId = `${tf.prfxFlt + j + this.prfxGridFltTd + tf.id}`;
|
let fltTdId = `${tf.prfxFlt + j + this.prfxGridFltTd + tf.id}`;
|
||||||
let cl = createElm(tf.fltCellTag, ['id', fltTdId]);
|
let cl = createElm(tf.fltCellTag, ['id', fltTdId]);
|
||||||
filtersRow.appendChild(cl);
|
filtersRow.appendChild(cl);
|
||||||
tf.externalFltTgtIds[j] = fltTdId;
|
tf.externalFltIds[j] = fltTdId;
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
return filtersRow;
|
return filtersRow;
|
||||||
}
|
}
|
||||||
|
@ -392,15 +381,15 @@ export class GridLayout extends Feature {
|
||||||
*/
|
*/
|
||||||
setColumnElements() {
|
setColumnElements() {
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
let cols = tag(tf.tbl, 'col');
|
let cols = tag(tf.dom(), 'col');
|
||||||
this.tblHasColTag = cols.length > 0;
|
this.tblHasColTag = cols.length > 0;
|
||||||
|
|
||||||
for (let k = (tf.nbCells - 1); k >= 0; k--) {
|
for (let k = (tf.getCellsNb() - 1); k >= 0; k--) {
|
||||||
let col;
|
let col;
|
||||||
|
|
||||||
if (!this.tblHasColTag) {
|
if (!this.tblHasColTag) {
|
||||||
col = createElm('col');
|
col = createElm('col');
|
||||||
tf.tbl.insertBefore(col, tf.tbl.firstChild);
|
tf.dom().insertBefore(col, tf.dom().firstChild);
|
||||||
} else {
|
} else {
|
||||||
col = cols[k];
|
col = cols[k];
|
||||||
}
|
}
|
||||||
|
@ -423,7 +412,7 @@ export class GridLayout extends Feature {
|
||||||
} else {
|
} else {
|
||||||
// Headers row are moved from content table to headers table
|
// Headers row are moved from content table to headers table
|
||||||
for (let i = 0; i < this.headRows.length; i++) {
|
for (let i = 0; i < this.headRows.length; i++) {
|
||||||
let row = this.tf.tbl.rows[this.headRows[i]];
|
let row = this.tf.dom().rows[this.headRows[i]];
|
||||||
tableHead.appendChild(row);
|
tableHead.appendChild(row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -454,7 +443,7 @@ export class GridLayout extends Feature {
|
||||||
getSortTriggerIds(row) {
|
getSortTriggerIds(row) {
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
let sortTriggers = [];
|
let sortTriggers = [];
|
||||||
for (let n = 0; n < tf.getCellsNb(); n++) {
|
tf.eachCol((n) => {
|
||||||
let c = row.cells[n];
|
let c = row.cells[n];
|
||||||
let thId = c.getAttribute('id');
|
let thId = c.getAttribute('id');
|
||||||
if (!thId || thId === '') {
|
if (!thId || thId === '') {
|
||||||
|
@ -462,7 +451,7 @@ export class GridLayout extends Feature {
|
||||||
c.setAttribute('id', thId);
|
c.setAttribute('id', thId);
|
||||||
}
|
}
|
||||||
sortTriggers.push(thId);
|
sortTriggers.push(thId);
|
||||||
}
|
});
|
||||||
return sortTriggers;
|
return sortTriggers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -471,7 +460,7 @@ export class GridLayout extends Feature {
|
||||||
*/
|
*/
|
||||||
destroy() {
|
destroy() {
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
let tbl = tf.tbl;
|
let tbl = tf.dom();
|
||||||
|
|
||||||
if (!this.initialized) {
|
if (!this.initialized) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -86,7 +86,7 @@ export class Hash {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a URL hash into a state JSON object
|
* Converts a URL hash into a JSON object
|
||||||
*
|
*
|
||||||
* @param {String} hash URL hash fragment
|
* @param {String} hash URL hash fragment
|
||||||
* @returns {Object} JSON object
|
* @returns {Object} JSON object
|
||||||
|
|
|
@ -3,10 +3,13 @@ import {createElm, createText, elm, removeElm} from '../dom';
|
||||||
import {addEvt, targetEvt, removeEvt} from '../event';
|
import {addEvt, targetEvt, removeEvt} from '../event';
|
||||||
import {NONE} from '../const';
|
import {NONE} from '../const';
|
||||||
import {root} from '../root';
|
import {root} from '../root';
|
||||||
|
import {isEmpty, isNull} from '../types';
|
||||||
|
import {defaultsStr, defaultsNb} from '../settings';
|
||||||
|
import {RIGHT} from './toolbar';
|
||||||
|
|
||||||
const WIKI_URL = 'https://github.com/koalyptus/TableFilter/wiki/' +
|
const WIKI_URL = 'https://github.com/koalyptus/TableFilter/wiki/' +
|
||||||
'4.-Filter-operators';
|
'4.-Filter-operators';
|
||||||
const WEBSITE_URL = 'http://koalyptus.github.io/TableFilter/';
|
const WEBSITE_URL = 'https://www.tablefilter.com/';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Help UI component
|
* Help UI component
|
||||||
|
@ -18,29 +21,27 @@ export class Help extends Feature {
|
||||||
* @param {TableFilter} tf TableFilter instance
|
* @param {TableFilter} tf TableFilter instance
|
||||||
*/
|
*/
|
||||||
constructor(tf) {
|
constructor(tf) {
|
||||||
super(tf, 'help');
|
super(tf, Help);
|
||||||
|
|
||||||
let f = this.config;
|
let f = this.config.help_instructions || {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID of main custom container element
|
* ID of main custom container element
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.tgtId = f.help_instructions_target_id || null;
|
this.tgtId = defaultsStr(f.target_id, null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID of custom container element for instructions
|
* ID of custom container element for instructions
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.contTgtId = f.help_instructions_container_target_id ||
|
this.contTgtId = defaultsStr(f.container_target_id, null);
|
||||||
null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instructions text (accepts HTML)
|
* Instructions text (accepts HTML)
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.instrText = f.help_instructions_text ?
|
this.instrText = !isEmpty(f.text) ? f.text :
|
||||||
f.help_instructions_text :
|
|
||||||
'Use the filters above each column to filter and limit table ' +
|
'Use the filters above each column to filter and limit table ' +
|
||||||
'data. Advanced searches can be performed by using the following ' +
|
'data. Advanced searches can be performed by using the following ' +
|
||||||
'operators: <br /><b><</b>, <b><=</b>, <b>></b>, ' +
|
'operators: <br /><b><</b>, <b><=</b>, <b>></b>, ' +
|
||||||
|
@ -53,32 +54,31 @@ export class Help extends Feature {
|
||||||
* Instructions HTML
|
* Instructions HTML
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.instrHtml = f.help_instructions_html || null;
|
this.instrHtml = defaultsStr(f.html, null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Help button text ('?')
|
* Help button text ('?')
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.btnText = f.help_instructions_btn_text || '?';
|
this.btnText = defaultsStr(f.btn_text, '?');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom help button HTML
|
* Custom help button HTML
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.btnHtml = f.help_instructions_btn_html || null;
|
this.btnHtml = defaultsStr(f.btn_html, null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for help button
|
* Css class for help button
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.btnCssClass = f.help_instructions_btn_css_class || 'helpBtn';
|
this.btnCssClass = defaultsStr(f.btn_css_class, 'helpBtn');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for help container element
|
* Css class for help container element
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.contCssClass = f.help_instructions_container_css_class ||
|
this.contCssClass = defaultsStr(f.container_css_class, 'helpCont');
|
||||||
'helpCont';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Button DOM element
|
* Button DOM element
|
||||||
|
@ -92,6 +92,15 @@ export class Help extends Feature {
|
||||||
*/
|
*/
|
||||||
this.cont = null;
|
this.cont = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjust container left position when table's horizontal scroll is
|
||||||
|
* on, typically when `responsive` option is enabled.
|
||||||
|
* @type {Number}
|
||||||
|
* @defaultValue 25
|
||||||
|
*/
|
||||||
|
this.contAdjustLeftPosition =
|
||||||
|
defaultsNb(f.container_adjust_left_position, 25);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bound mouseup wrapper
|
* Bound mouseup wrapper
|
||||||
* @private
|
* @private
|
||||||
|
@ -109,6 +118,12 @@ export class Help extends Feature {
|
||||||
'<div align="center" style="margin-top:8px;">' +
|
'<div align="center" style="margin-top:8px;">' +
|
||||||
'<a href="javascript:void(0);" class="close">Close</a></div></div>';
|
'<a href="javascript:void(0);" class="close">Close</a></div></div>';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default position in toolbar ('left'|'center'|'right')
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
this.toolbarPosition = defaultsStr(f.toolbar_position, RIGHT);
|
||||||
|
|
||||||
this.emitter.on(['init-help'], () => this.init());
|
this.emitter.on(['init-help'], () => this.init());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,6 +153,8 @@ export class Help extends Feature {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.emitter.emit('initializing-feature', this, !isNull(this.tgtId));
|
||||||
|
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
|
|
||||||
let btn = createElm('span');
|
let btn = createElm('span');
|
||||||
|
@ -146,10 +163,9 @@ export class Help extends Feature {
|
||||||
this.boundMouseup = this.onMouseup.bind(this);
|
this.boundMouseup = this.onMouseup.bind(this);
|
||||||
|
|
||||||
//help button is added to defined element
|
//help button is added to defined element
|
||||||
if (!this.tgtId) {
|
let targetEl = !this.tgtId ?
|
||||||
tf.setToolbar();
|
tf.feature('toolbar').container(this.toolbarPosition) :
|
||||||
}
|
elm(this.tgtId);
|
||||||
let targetEl = !this.tgtId ? tf.rDiv : elm(this.tgtId);
|
|
||||||
targetEl.appendChild(btn);
|
targetEl.appendChild(btn);
|
||||||
|
|
||||||
let divContainer = !this.contTgtId ? btn : elm(this.contTgtId);
|
let divContainer = !this.contTgtId ? btn : elm(this.contTgtId);
|
||||||
|
@ -187,15 +203,17 @@ export class Help extends Feature {
|
||||||
this.btn = btn;
|
this.btn = btn;
|
||||||
/** @inherited */
|
/** @inherited */
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
|
|
||||||
|
this.emitter.emit('feature-initialized', this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toggle help pop-up
|
* Toggle help pop-up
|
||||||
*/
|
*/
|
||||||
toggle() {
|
toggle() {
|
||||||
// check only if explicitily set to false as in this case undefined
|
// check only if explicitily disabled as in this case undefined
|
||||||
// signifies the help feature is enabled by default
|
// signifies the help feature is enabled by default
|
||||||
if (this.enabled === false) {
|
if (!this.isEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,9 +223,21 @@ export class Help extends Feature {
|
||||||
let divDisplay = this.cont.style.display;
|
let divDisplay = this.cont.style.display;
|
||||||
if (divDisplay === '' || divDisplay === NONE) {
|
if (divDisplay === '' || divDisplay === NONE) {
|
||||||
this.cont.style.display = 'inline';
|
this.cont.style.display = 'inline';
|
||||||
|
|
||||||
|
// if table element has an horizontal scrollbar adjust container
|
||||||
|
// left position accordingly
|
||||||
|
if (this.tf.dom().scrollLeft > 0) {
|
||||||
|
this.cont.style.left = `${
|
||||||
|
this.btn.offsetLeft
|
||||||
|
- this.tf.dom().scrollLeft
|
||||||
|
+ this.contAdjustLeftPosition
|
||||||
|
}px`;
|
||||||
|
}
|
||||||
|
|
||||||
addEvt(root, 'mouseup', this.boundMouseup);
|
addEvt(root, 'mouseup', this.boundMouseup);
|
||||||
} else {
|
} else {
|
||||||
this.cont.style.display = NONE;
|
this.cont.style.display = NONE;
|
||||||
|
this.cont.style.left = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,8 +255,10 @@ export class Help extends Feature {
|
||||||
this.cont = null;
|
this.cont = null;
|
||||||
|
|
||||||
this.boundMouseup = null;
|
this.boundMouseup = null;
|
||||||
|
|
||||||
this.initialized = false;
|
this.initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: remove as soon as feature name is fixed
|
||||||
|
Help.meta = {alwaysInstantiate: true};
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import {createText, createElm, getText} from '../dom';
|
import {createText, createElm, getText} from '../dom';
|
||||||
import {isArray} from '../types';
|
import {isNull} from '../types';
|
||||||
import {rgxEsc} from '../string';
|
import {rgxEsc} from '../string';
|
||||||
|
import {defaultsStr} from '../settings';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Highlight matched keywords upon filtering
|
* Highlight matched keywords upon filtering
|
||||||
|
@ -21,7 +22,7 @@ export class HighlightKeyword {
|
||||||
* Css class for highlighted term
|
* Css class for highlighted term
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.highlightCssClass = f.highlight_css_class || 'keyword';
|
this.highlightCssClass = defaultsStr(f.highlight_css_class, 'keyword');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TableFilter instance
|
* TableFilter instance
|
||||||
|
@ -99,12 +100,13 @@ export class HighlightKeyword {
|
||||||
* @param {String} cssClass Css class to remove
|
* @param {String} cssClass Css class to remove
|
||||||
*/
|
*/
|
||||||
unhighlight(term, cssClass) {
|
unhighlight(term, cssClass) {
|
||||||
let highlightedNodes = this.tf.tbl.querySelectorAll(`.${cssClass}`);
|
let highlightedNodes = this.tf.dom().querySelectorAll(`.${cssClass}`);
|
||||||
for (let i = 0; i < highlightedNodes.length; i++) {
|
for (let i = 0; i < highlightedNodes.length; i++) {
|
||||||
let n = highlightedNodes[i];
|
let n = highlightedNodes[i];
|
||||||
let nodeVal = getText(n);
|
let nodeVal = getText(n);
|
||||||
|
|
||||||
if (nodeVal.toLowerCase().indexOf(term.toLowerCase()) !== -1) {
|
if (isNull(term) ||
|
||||||
|
nodeVal.toLowerCase().indexOf(term.toLowerCase()) !== -1) {
|
||||||
let parentNode = n.parentNode;
|
let parentNode = n.parentNode;
|
||||||
parentNode.replaceChild(createText(nodeVal), n);
|
parentNode.replaceChild(createText(nodeVal), n);
|
||||||
parentNode.normalize();
|
parentNode.normalize();
|
||||||
|
@ -119,15 +121,8 @@ export class HighlightKeyword {
|
||||||
if (!this.tf.highlightKeywords) {
|
if (!this.tf.highlightKeywords) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// iterate filters values to unhighlight all values
|
|
||||||
this.tf.getFiltersValue().forEach((val) => {
|
this.unhighlight(null, this.highlightCssClass);
|
||||||
if (isArray(val)) {
|
|
||||||
val.forEach((item) =>
|
|
||||||
this.unhighlight(item, this.highlightCssClass));
|
|
||||||
} else {
|
|
||||||
this.unhighlight(val, this.highlightCssClass);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Remove feature */
|
/** Remove feature */
|
||||||
|
@ -177,3 +172,9 @@ export class HighlightKeyword {
|
||||||
this.highlight(cell, term, this.highlightCssClass);
|
this.highlight(cell, term, this.highlightCssClass);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: remove as soon as feature name is fixed
|
||||||
|
HighlightKeyword.meta = {
|
||||||
|
name: 'highlightKeyword',
|
||||||
|
altName: 'highlightKeywords'
|
||||||
|
};
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import {Feature} from '../feature';
|
import {Feature} from '../feature';
|
||||||
import {createElm, createText, elm, removeElm} from '../dom';
|
import {createElm, createText, elm, removeElm} from '../dom';
|
||||||
import {isFn, EMPTY_FN} from '../types';
|
import {EMPTY_FN} from '../types';
|
||||||
import {root} from '../root';
|
import {root} from '../root';
|
||||||
import {NONE} from '../const';
|
import {NONE} from '../const';
|
||||||
|
import {defaultsStr, defaultsFn} from '../settings';
|
||||||
|
|
||||||
const EVENTS = [
|
const BEFORE_ACTION_EVENTS = [
|
||||||
'before-filtering',
|
'before-filtering',
|
||||||
'before-populating-filter',
|
'before-populating-filter',
|
||||||
'before-page-change',
|
'before-page-change',
|
||||||
|
@ -16,6 +17,18 @@ const EVENTS = [
|
||||||
'before-loading-themes'
|
'before-loading-themes'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const AFTER_ACTION_EVENTS = [
|
||||||
|
'after-filtering',
|
||||||
|
'after-populating-filter',
|
||||||
|
'after-page-change',
|
||||||
|
'after-clearing-filters',
|
||||||
|
'after-page-length-change',
|
||||||
|
'after-reset-page',
|
||||||
|
'after-reset-page-length',
|
||||||
|
'after-loading-extensions',
|
||||||
|
'after-loading-themes'
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activity indicator
|
* Activity indicator
|
||||||
*
|
*
|
||||||
|
@ -31,15 +44,15 @@ export class Loader extends Feature {
|
||||||
* @param {TableFilter} tf TableFilter instance
|
* @param {TableFilter} tf TableFilter instance
|
||||||
*/
|
*/
|
||||||
constructor(tf) {
|
constructor(tf) {
|
||||||
super(tf, 'loader');
|
super(tf, Loader);
|
||||||
|
|
||||||
let f = this.config;
|
let f = this.config.loader || {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID of custom container element
|
* ID of custom container element
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.targetId = f.loader_target_id || null;
|
this.targetId = defaultsStr(f.target_id, null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loader container DOM element
|
* Loader container DOM element
|
||||||
|
@ -51,19 +64,19 @@ export class Loader extends Feature {
|
||||||
* Text displayed when indicator is visible
|
* Text displayed when indicator is visible
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.text = f.loader_text || 'Loading...';
|
this.text = defaultsStr(f.text, 'Loading...');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom HTML injected in Loader's container element
|
* Custom HTML injected in Loader's container element
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.html = f.loader_html || null;
|
this.html = defaultsStr(f.html, null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for Loader's container element
|
* Css class for Loader's container element
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.cssClass = f.loader_css_class || 'loader';
|
this.cssClass = defaultsStr(f.css_class, 'loader');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close delay in milliseconds
|
* Close delay in milliseconds
|
||||||
|
@ -75,14 +88,13 @@ export class Loader extends Feature {
|
||||||
* Callback fired when loader is displayed
|
* Callback fired when loader is displayed
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onShow = isFn(f.on_show_loader) ?
|
this.onShow = defaultsFn(f.on_show_loader, EMPTY_FN);
|
||||||
f.on_show_loader : EMPTY_FN;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired when loader is closed
|
* Callback fired when loader is closed
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onHide = isFn(f.on_hide_loader) ? f.on_hide_loader : EMPTY_FN;
|
this.onHide = defaultsFn(f.on_hide_loader, EMPTY_FN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -100,9 +112,9 @@ export class Loader extends Feature {
|
||||||
containerDiv.className = this.cssClass;
|
containerDiv.className = this.cssClass;
|
||||||
|
|
||||||
let targetEl = !this.targetId ?
|
let targetEl = !this.targetId ?
|
||||||
tf.tbl.parentNode : elm(this.targetId);
|
tf.dom().parentNode : elm(this.targetId);
|
||||||
if (!this.targetId) {
|
if (!this.targetId) {
|
||||||
targetEl.insertBefore(containerDiv, tf.tbl);
|
targetEl.insertBefore(containerDiv, tf.dom());
|
||||||
} else {
|
} else {
|
||||||
targetEl.appendChild(containerDiv);
|
targetEl.appendChild(containerDiv);
|
||||||
}
|
}
|
||||||
|
@ -116,12 +128,10 @@ export class Loader extends Feature {
|
||||||
this.show(NONE);
|
this.show(NONE);
|
||||||
|
|
||||||
// Subscribe to events
|
// Subscribe to events
|
||||||
emitter.on(EVENTS, () => this.show(''));
|
emitter.on(BEFORE_ACTION_EVENTS, () => this.show(''));
|
||||||
emitter.on(EVENTS, () => this.show(NONE));
|
emitter.on(AFTER_ACTION_EVENTS, () => this.show(NONE));
|
||||||
|
|
||||||
/**
|
/** @inherited */
|
||||||
* @inherited
|
|
||||||
*/
|
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +144,7 @@ export class Loader extends Feature {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let displayLoader = () => {
|
function displayLoader() {
|
||||||
if (!this.cont) {
|
if (!this.cont) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -148,7 +158,7 @@ export class Loader extends Feature {
|
||||||
};
|
};
|
||||||
|
|
||||||
let t = p === NONE ? this.closeDelay : 1;
|
let t = p === NONE ? this.closeDelay : 1;
|
||||||
root.setTimeout(displayLoader, t);
|
root.setTimeout(displayLoader.bind(this), t);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -165,8 +175,8 @@ export class Loader extends Feature {
|
||||||
this.cont = null;
|
this.cont = null;
|
||||||
|
|
||||||
// Unsubscribe to events
|
// Unsubscribe to events
|
||||||
emitter.off(EVENTS, () => this.show(''));
|
emitter.off(BEFORE_ACTION_EVENTS, () => this.show(''));
|
||||||
emitter.off(EVENTS, () => this.show(NONE));
|
emitter.off(AFTER_ACTION_EVENTS, () => this.show(NONE));
|
||||||
|
|
||||||
this.initialized = false;
|
this.initialized = false;
|
||||||
}
|
}
|
||||||
|
|
146
src/modules/markActiveColumns.js
Normal file
146
src/modules/markActiveColumns.js
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
import {Feature} from '../feature';
|
||||||
|
import {addClass, removeClass, hasClass} from '../dom';
|
||||||
|
import {EMPTY_FN} from '../types';
|
||||||
|
import {defaultsStr, defaultsFn} from '../settings';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visual indicator for filtered columns
|
||||||
|
* @export
|
||||||
|
* @class MarkActiveColumns
|
||||||
|
* @extends {Feature}
|
||||||
|
*/
|
||||||
|
export class MarkActiveColumns extends Feature {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an instance of MarkActiveColumns
|
||||||
|
* @param {TableFilter} tf TableFilter instance
|
||||||
|
*/
|
||||||
|
constructor(tf) {
|
||||||
|
super(tf, MarkActiveColumns);
|
||||||
|
|
||||||
|
let config = this.config.mark_active_columns || {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Css class for filtered (active) columns
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
this.headerCssClass = defaultsStr(config.header_css_class,
|
||||||
|
'activeHeader');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Css class for filtered (active) column cells
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
this.cellCssClass = defaultsStr(config.cell_css_class,
|
||||||
|
'activeCell');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable/disable column highlighting
|
||||||
|
* @type {Boolean}
|
||||||
|
*/
|
||||||
|
this.highlightColumn = Boolean(config.highlight_column);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback fired before a column is marked as filtered
|
||||||
|
* @type {Function}
|
||||||
|
*/
|
||||||
|
this.onBeforeActiveColumn = defaultsFn(config.on_before_active_column,
|
||||||
|
EMPTY_FN);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback fired after a column is marked as filtered
|
||||||
|
* @type {Function}
|
||||||
|
*/
|
||||||
|
this.onAfterActiveColumn = defaultsFn(config.on_after_active_column,
|
||||||
|
EMPTY_FN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise MarkActiveColumns instance
|
||||||
|
*/
|
||||||
|
init() {
|
||||||
|
if (this.initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.emitter.on(['before-filtering'], () => this.clearActiveColumns());
|
||||||
|
this.emitter.on(
|
||||||
|
['cell-processed'],
|
||||||
|
(tf, colIndex) => this.markActiveColumn(colIndex)
|
||||||
|
);
|
||||||
|
|
||||||
|
/** @inherited */
|
||||||
|
this.initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear filtered columns visual indicator (background color)
|
||||||
|
*/
|
||||||
|
clearActiveColumns() {
|
||||||
|
let tf = this.tf;
|
||||||
|
tf.eachCol((idx) => {
|
||||||
|
removeClass(tf.getHeaderElement(idx), this.headerCssClass);
|
||||||
|
|
||||||
|
if (this.highlightColumn) {
|
||||||
|
this.eachColumnCell(idx,
|
||||||
|
(cell) => removeClass(cell, this.cellCssClass));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark currently filtered column
|
||||||
|
* @param {Number} colIndex Column index
|
||||||
|
*/
|
||||||
|
markActiveColumn(colIndex) {
|
||||||
|
let tf = this.tf;
|
||||||
|
let header = tf.getHeaderElement(colIndex);
|
||||||
|
if (hasClass(header, this.headerCssClass)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.onBeforeActiveColumn(this, colIndex);
|
||||||
|
|
||||||
|
addClass(header, this.headerCssClass);
|
||||||
|
|
||||||
|
if (this.highlightColumn) {
|
||||||
|
this.eachColumnCell(colIndex,
|
||||||
|
(cell) => addClass(cell, this.cellCssClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.onAfterActiveColumn(this, colIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Column cells iterator
|
||||||
|
* TODO: make public and move into TableFilter if used elsewhere
|
||||||
|
* @param {Number} colIndex
|
||||||
|
* @param {Function} fn
|
||||||
|
* @param {DOMElement} tbl
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
eachColumnCell(colIndex, fn = EMPTY_FN, tbl = this.tf.dom()) {
|
||||||
|
// TODO: remove [].forEach when polyfill for PhanthomJs is available
|
||||||
|
[].forEach.call(
|
||||||
|
tbl.querySelectorAll(`tbody td:nth-child(${colIndex + 1})`), fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove feature
|
||||||
|
*/
|
||||||
|
destroy() {
|
||||||
|
if (!this.initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.clearActiveColumns();
|
||||||
|
this.emitter.off(['before-filtering'], () => this.clearActiveColumns());
|
||||||
|
this.emitter.off(
|
||||||
|
['cell-processed'],
|
||||||
|
(tf, colIndex) => this.markActiveColumn(colIndex)
|
||||||
|
);
|
||||||
|
|
||||||
|
/** @inherited */
|
||||||
|
this.initialized = false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,8 @@
|
||||||
import {Feature} from '../feature';
|
import {Feature} from '../feature';
|
||||||
import {createElm, elm, removeElm} from '../dom';
|
import {createElm, elm, removeElm} from '../dom';
|
||||||
import {isEmpty, isFn, EMPTY_FN} from '../types';
|
import {isEmpty, EMPTY_FN} from '../types';
|
||||||
import {NONE} from '../const';
|
import {NONE} from '../const';
|
||||||
|
import {defaultsStr, defaultsFn} from '../settings';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UI when filtering yields no matches
|
* UI when filtering yields no matches
|
||||||
|
@ -16,28 +17,28 @@ export class NoResults extends Feature {
|
||||||
* @param {TableFilter} tf TableFilter instance
|
* @param {TableFilter} tf TableFilter instance
|
||||||
*/
|
*/
|
||||||
constructor(tf) {
|
constructor(tf) {
|
||||||
super(tf, 'noResults');
|
super(tf, NoResults);
|
||||||
|
|
||||||
//configuration object
|
//configuration object
|
||||||
let f = this.config.no_results_message;
|
let f = this.config.no_results_message || {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Text (accepts HTML)
|
* Text (accepts HTML)
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.content = f.content || 'No results';
|
this.content = defaultsStr(f.content, 'No results');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom container DOM element
|
* Custom container DOM element
|
||||||
* @type {DOMElement}
|
* @type {DOMElement}
|
||||||
*/
|
*/
|
||||||
this.customContainer = f.custom_container || null;
|
this.customContainer = defaultsStr(f.custom_container, null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID of custom container element
|
* ID of custom container element
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.customContainerId = f.custom_container_id || null;
|
this.customContainerId = defaultsStr(f.custom_container_id, null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates if UI is contained in a external element
|
* Indicates if UI is contained in a external element
|
||||||
|
@ -51,7 +52,7 @@ export class NoResults extends Feature {
|
||||||
* Css class assigned to container element
|
* Css class assigned to container element
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.cssClass = f.css_class || 'no-results';
|
this.cssClass = defaultsStr(f.css_class, 'no-results');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores container DOM element
|
* Stores container DOM element
|
||||||
|
@ -63,29 +64,25 @@ export class NoResults extends Feature {
|
||||||
* Callback fired before the message is displayed
|
* Callback fired before the message is displayed
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onBeforeShow = isFn(f.on_before_show_msg) ?
|
this.onBeforeShow = defaultsFn(f.on_before_show_msg, EMPTY_FN);
|
||||||
f.on_before_show_msg : EMPTY_FN;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired after the message is displayed
|
* Callback fired after the message is displayed
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onAfterShow = isFn(f.on_after_show_msg) ?
|
this.onAfterShow = defaultsFn(f.on_after_show_msg, EMPTY_FN);
|
||||||
f.on_after_show_msg : EMPTY_FN;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired before the message is hidden
|
* Callback fired before the message is hidden
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onBeforeHide = isFn(f.on_before_hide_msg) ?
|
this.onBeforeHide = defaultsFn(f.on_before_hide_msg, EMPTY_FN);
|
||||||
f.on_before_hide_msg : EMPTY_FN;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired after the message is hidden
|
* Callback fired after the message is hidden
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onAfterHide = isFn(f.on_after_hide_msg) ?
|
this.onAfterHide = defaultsFn(f.on_after_hide_msg, EMPTY_FN);
|
||||||
f.on_after_hide_msg : EMPTY_FN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -97,7 +94,7 @@ export class NoResults extends Feature {
|
||||||
}
|
}
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
let target = this.customContainer || elm(this.customContainerId) ||
|
let target = this.customContainer || elm(this.customContainerId) ||
|
||||||
tf.tbl;
|
tf.dom();
|
||||||
|
|
||||||
//container
|
//container
|
||||||
let cont = createElm('div');
|
let cont = createElm('div');
|
||||||
|
@ -113,14 +110,13 @@ export class NoResults extends Feature {
|
||||||
this.cont = cont;
|
this.cont = cont;
|
||||||
|
|
||||||
// subscribe to after-filtering event
|
// subscribe to after-filtering event
|
||||||
this.emitter.on(['after-filtering'], () => this.toggle());
|
this.emitter.on(
|
||||||
|
['initialized', 'after-filtering'],
|
||||||
|
() => this.toggle()
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/** @inherited */
|
||||||
* @inherited
|
|
||||||
*/
|
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
|
|
||||||
this.hide();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -174,16 +170,15 @@ export class NoResults extends Feature {
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
if (tf.gridLayout) {
|
if (tf.gridLayout) {
|
||||||
let gridLayout = tf.feature('gridLayout');
|
let gridLayout = tf.feature('gridLayout');
|
||||||
this.cont.style.width = gridLayout.tblCont.clientWidth + 'px';
|
this.cont.style.width = gridLayout.headTbl.clientWidth + 'px';
|
||||||
} else {
|
} else {
|
||||||
this.cont.style.width = (tf.tbl.tHead ? tf.tbl.tHead.clientWidth :
|
this.cont.style.width = (tf.dom().tHead ?
|
||||||
tf.tbl.tBodies[0].clientWidth) + 'px';
|
tf.dom().tHead.clientWidth :
|
||||||
|
tf.dom().tBodies[0].clientWidth) + 'px';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Remove feature */
|
||||||
* Remove feature
|
|
||||||
*/
|
|
||||||
destroy() {
|
destroy() {
|
||||||
if (!this.initialized) {
|
if (!this.initialized) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
import {Feature} from '../feature';
|
import {Feature} from '../feature';
|
||||||
import {createElm, createOpt, createText, elm, removeElm} from '../dom';
|
import {createElm, createOpt, createText, elm, removeElm} from '../dom';
|
||||||
import {isArray, isFn, isNull, EMPTY_FN} from '../types';
|
import {isArray, isNull, EMPTY_FN} from '../types';
|
||||||
import {addEvt, keyCode, removeEvt} from '../event';
|
import {addEvt, removeEvt, isKeyPressed, bound} from '../event';
|
||||||
import {INPUT, SELECT, NONE, ENTER_KEY} from '../const';
|
import {INPUT, SELECT, NONE, ENTER_KEY} from '../const';
|
||||||
|
import {
|
||||||
|
defaultsStr, defaultsNb, defaultsBool, defaultsArr, defaultsFn
|
||||||
|
} from '../settings';
|
||||||
|
import {CENTER, RIGHT} from './toolbar';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Paging UI component
|
* Paging UI component
|
||||||
|
@ -17,65 +21,65 @@ export class Paging extends Feature {
|
||||||
* @param {TableFilter} tf TableFilter instance
|
* @param {TableFilter} tf TableFilter instance
|
||||||
*/
|
*/
|
||||||
constructor(tf) {
|
constructor(tf) {
|
||||||
super(tf, 'paging');
|
super(tf, Paging);
|
||||||
|
|
||||||
// Configuration object
|
// Configuration object
|
||||||
var f = this.config;
|
let f = this.config.paging || {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for the paging buttons (previous, next, etc.)
|
* Css class for the paging buttons (previous, next, etc.)
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.btnPageCssClass = f.paging_btn_css_class || 'pgInp';
|
this.btnCssClass = defaultsStr(f.btn_css_class, 'pgInp');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main select DOM element
|
* Main select DOM element
|
||||||
* @type {DOMElement}
|
* @type {DOMElement}
|
||||||
*/
|
*/
|
||||||
this.pagingSlc = null;
|
this.pageSlc = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Results per page select DOM element
|
* Results per page select DOM element
|
||||||
* @type {DOMElement}
|
* @type {DOMElement}
|
||||||
*/
|
*/
|
||||||
this.resultsPerPageSlc = null;
|
this.pageLengthSlc = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID of custom container element
|
* ID of custom container element
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.pagingTgtId = f.paging_target_id || null;
|
this.tgtId = defaultsStr(f.target_id, null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of rows contained in a page
|
* Number of rows contained in a page
|
||||||
* @type {Number}
|
* @type {Number}
|
||||||
*/
|
*/
|
||||||
this.pagingLength = !isNaN(f.paging_length) ? f.paging_length : 10;
|
this.pageLength = defaultsNb(f.length, 10);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID of custom container element for the results per page selector
|
* ID of custom container element for the results per page selector
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.resultsPerPageTgtId = f.results_per_page_target_id || null;
|
this.pageLengthTgtId = defaultsStr(f.results_per_page_target_id, null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for the paging select element
|
* Css class for the paging select element
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.pgSlcCssClass = f.paging_slc_css_class || 'pgSlc';
|
this.pgSlcCssClass = defaultsStr(f.slc_css_class, 'pgSlc');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for the paging input element
|
* Css class for the paging input element
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.pgInpCssClass = f.paging_inp_css_class || 'pgNbInp';
|
this.pgInpCssClass = defaultsStr(f.inp_css_class, 'pgNbInp');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Label and values for the results per page select, example of usage:
|
* Label and values for the results per page select, example of usage:
|
||||||
* ['Records: ', [10,25,50,100]]
|
* ['Records: ', [10,25,50,100]]
|
||||||
* @type {Array}
|
* @type {Array}
|
||||||
*/
|
*/
|
||||||
this.resultsPerPage = f.results_per_page || null;
|
this.resultsPerPage = defaultsArr(f.results_per_page, null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if results per page is configured
|
* Determines if results per page is configured
|
||||||
|
@ -87,13 +91,14 @@ export class Paging extends Feature {
|
||||||
* Css class for the results per page select
|
* Css class for the results per page select
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.resultsSlcCssClass = f.results_slc_css_class || 'rspg';
|
this.resultsSlcCssClass = defaultsStr(f.results_slc_css_class, 'rspg');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for the label preceding results per page select
|
* Css class for the label preceding results per page select
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.resultsSpanCssClass = f.results_span_css_class || 'rspgSpan';
|
this.resultsSpanCssClass = defaultsStr(f.results_span_css_class,
|
||||||
|
'rspgSpan');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Index of the first row of current page
|
* Index of the first row of current page
|
||||||
|
@ -120,105 +125,109 @@ export class Paging extends Feature {
|
||||||
* Next page button text
|
* Next page button text
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.btnNextPageText = f.btn_next_page_text || '>';
|
this.btnNextPageText = defaultsStr(f.btn_next_page_text, '>');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Previous page button text
|
* Previous page button text
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.btnPrevPageText = f.btn_prev_page_text || '<';
|
this.btnPrevPageText = defaultsStr(f.btn_prev_page_text, '<');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Last page button text
|
* Last page button text
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.btnLastPageText = f.btn_last_page_text || '>|';
|
this.btnLastPageText = defaultsStr(f.btn_last_page_text, '>|');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* First page button text
|
* First page button text
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.btnFirstPageText = f.btn_first_page_text || '|<';
|
this.btnFirstPageText = defaultsStr(f.btn_first_page_text, '|<');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Next page button HTML
|
* Next page button HTML
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.btnNextPageHtml = f.btn_next_page_html ||
|
this.btnNextPageHtml = defaultsStr(f.btn_next_page_html,
|
||||||
(!tf.enableIcons ? null :
|
(!tf.enableIcons ? null :
|
||||||
'<input type="button" value="" class="' + this.btnPageCssClass +
|
'<input type="button" value="" class="' + this.btnCssClass +
|
||||||
' nextPage" title="Next page" />');
|
' nextPage" title="Next page" />'));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Previous page button HTML
|
* Previous page button HTML
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.btnPrevPageHtml = f.btn_prev_page_html ||
|
this.btnPrevPageHtml = defaultsStr(f.btn_prev_page_html,
|
||||||
(!tf.enableIcons ? null :
|
(!tf.enableIcons ? null :
|
||||||
'<input type="button" value="" class="' + this.btnPageCssClass +
|
'<input type="button" value="" class="' + this.btnCssClass +
|
||||||
' previousPage" title="Previous page" />');
|
' previousPage" title="Previous page" />'));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* First page button HTML
|
* First page button HTML
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.btnFirstPageHtml = f.btn_first_page_html ||
|
this.btnFirstPageHtml = defaultsStr(f.btn_first_page_html,
|
||||||
(!tf.enableIcons ? null :
|
(!tf.enableIcons ? null :
|
||||||
'<input type="button" value="" class="' + this.btnPageCssClass +
|
'<input type="button" value="" class="' + this.btnCssClass +
|
||||||
' firstPage" title="First page" />');
|
' firstPage" title="First page" />'));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Last page button HTML
|
* Last page button HTML
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.btnLastPageHtml = f.btn_last_page_html ||
|
this.btnLastPageHtml = defaultsStr(f.btn_last_page_html,
|
||||||
(!tf.enableIcons ? null :
|
(!tf.enableIcons ? null :
|
||||||
'<input type="button" value="" class="' + this.btnPageCssClass +
|
'<input type="button" value="" class="' + this.btnCssClass +
|
||||||
' lastPage" title="Last page" />');
|
' lastPage" title="Last page" />'));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Text preceeding page selector drop-down
|
* Text preceeding page selector drop-down
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.pageText = f.page_text || ' Page ';
|
this.pageText = defaultsStr(f.page_text, ' Page ');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Text after page selector drop-down
|
* Text after page selector drop-down
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.ofText = f.of_text || ' of ';
|
this.ofText = defaultsStr(f.of_text, ' of ');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for the span containing total number of pages
|
* Css class for the span containing total number of pages
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.nbPgSpanCssClass = f.nb_pages_css_class || 'nbpg';
|
this.nbPgSpanCssClass = defaultsStr(f.nb_pages_css_class, 'nbpg');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if paging buttons are enabled (default: true)
|
* Determines if paging buttons are enabled (default: true)
|
||||||
* @type {Boolean}
|
* @type {Boolean}
|
||||||
*/
|
*/
|
||||||
this.hasPagingBtns = f.paging_btns === false ? false : true;
|
this.hasBtns = defaultsBool(f.btns, true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines page selector type, two possible values: 'select', 'input'
|
* Defines page selector type, two possible values: 'select', 'input'
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.pageSelectorType = f.page_selector_type || SELECT;
|
this.pageSelectorType = defaultsStr(f.page_selector_type, SELECT);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default position in toolbar ('left'|'center'|'right')
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
this.toolbarPosition = defaultsStr(f.toolbar_position, CENTER);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired before the page is changed
|
* Callback fired before the page is changed
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onBeforeChangePage = isFn(f.on_before_change_page) ?
|
this.onBeforeChangePage = defaultsFn(f.on_before_change_page, EMPTY_FN);
|
||||||
f.on_before_change_page : EMPTY_FN;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired after the page is changed
|
* Callback fired after the page is changed
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onAfterChangePage = isFn(f.on_after_change_page) ?
|
this.onAfterChangePage = defaultsFn(f.on_after_change_page, EMPTY_FN);
|
||||||
f.on_after_change_page : EMPTY_FN;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Label preciding results per page select
|
* Label preciding results per page select
|
||||||
|
@ -269,12 +278,12 @@ export class Paging extends Feature {
|
||||||
*/
|
*/
|
||||||
this.pgAfter = null;
|
this.pgAfter = null;
|
||||||
|
|
||||||
var start_row = tf.refRow;
|
let startRow = tf.refRow;
|
||||||
var nrows = tf.getRowsNb(true);
|
let nrows = tf.getRowsNb(true);
|
||||||
//calculates page nb
|
//calculates page nb
|
||||||
this.nbPages = Math.ceil((nrows - start_row) / this.pagingLength);
|
this.nbPages = Math.ceil((nrows - startRow) / this.pageLength);
|
||||||
|
|
||||||
var o = this;
|
let o = this;
|
||||||
/**
|
/**
|
||||||
* Paging DOM events handlers
|
* Paging DOM events handlers
|
||||||
* @type {String}
|
* @type {String}
|
||||||
|
@ -283,21 +292,21 @@ export class Paging extends Feature {
|
||||||
this.evt = {
|
this.evt = {
|
||||||
slcIndex() {
|
slcIndex() {
|
||||||
return (o.pageSelectorType === SELECT) ?
|
return (o.pageSelectorType === SELECT) ?
|
||||||
o.pagingSlc.options.selectedIndex :
|
o.pageSlc.options.selectedIndex :
|
||||||
parseInt(o.pagingSlc.value, 10) - 1;
|
parseInt(o.pageSlc.value, 10) - 1;
|
||||||
},
|
},
|
||||||
nbOpts() {
|
nbOpts() {
|
||||||
return (o.pageSelectorType === SELECT) ?
|
return (o.pageSelectorType === SELECT) ?
|
||||||
parseInt(o.pagingSlc.options.length, 10) - 1 :
|
parseInt(o.pageSlc.options.length, 10) - 1 :
|
||||||
(o.nbPages - 1);
|
(o.nbPages - 1);
|
||||||
},
|
},
|
||||||
next() {
|
next() {
|
||||||
var nextIndex = o.evt.slcIndex() < o.evt.nbOpts() ?
|
let nextIndex = o.evt.slcIndex() < o.evt.nbOpts() ?
|
||||||
o.evt.slcIndex() + 1 : 0;
|
o.evt.slcIndex() + 1 : 0;
|
||||||
o.changePage(nextIndex);
|
o.changePage(nextIndex);
|
||||||
},
|
},
|
||||||
prev() {
|
prev() {
|
||||||
var prevIndex = o.evt.slcIndex() > 0 ?
|
let prevIndex = o.evt.slcIndex() > 0 ?
|
||||||
o.evt.slcIndex() - 1 : o.evt.nbOpts();
|
o.evt.slcIndex() - 1 : o.evt.nbOpts();
|
||||||
o.changePage(prevIndex);
|
o.changePage(prevIndex);
|
||||||
},
|
},
|
||||||
|
@ -308,8 +317,7 @@ export class Paging extends Feature {
|
||||||
o.changePage(0);
|
o.changePage(0);
|
||||||
},
|
},
|
||||||
_detectKey(e) {
|
_detectKey(e) {
|
||||||
var key = keyCode(e);
|
if (isKeyPressed(e, [ENTER_KEY])) {
|
||||||
if (key === ENTER_KEY) {
|
|
||||||
if (tf.sorted) {
|
if (tf.sorted) {
|
||||||
tf.filter();
|
tf.filter();
|
||||||
o.changePage(o.evt.slcIndex());
|
o.changePage(o.evt.slcIndex());
|
||||||
|
@ -331,27 +339,29 @@ export class Paging extends Feature {
|
||||||
* Initialize DOM elements
|
* Initialize DOM elements
|
||||||
*/
|
*/
|
||||||
init() {
|
init() {
|
||||||
var slcPages;
|
let slcPages;
|
||||||
var tf = this.tf;
|
let tf = this.tf;
|
||||||
var evt = this.evt;
|
let evt = this.evt;
|
||||||
|
|
||||||
if (this.initialized) {
|
if (this.initialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.emitter.emit('initializing-feature', this, !isNull(this.tgtId));
|
||||||
|
|
||||||
// Check resultsPerPage is in expected format and initialise the
|
// Check resultsPerPage is in expected format and initialise the
|
||||||
// results per page component
|
// results per page component
|
||||||
if (this.hasResultsPerPage) {
|
if (this.hasResultsPerPage) {
|
||||||
if (this.resultsPerPage.length < 2) {
|
if (this.resultsPerPage.length < 2) {
|
||||||
this.hasResultsPerPage = false;
|
this.hasResultsPerPage = false;
|
||||||
} else {
|
} else {
|
||||||
this.pagingLength = this.resultsPerPage[1][0];
|
this.pageLength = this.resultsPerPage[1][0];
|
||||||
this.setResultsPerPage();
|
this.setResultsPerPage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
evt.slcPagesChange = (event) => {
|
evt.slcPagesChange = (event) => {
|
||||||
var slc = event.target;
|
let slc = event.target;
|
||||||
this.changePage(slc.selectedIndex);
|
this.changePage(slc.selectedIndex);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -370,20 +380,20 @@ export class Paging extends Feature {
|
||||||
}
|
}
|
||||||
|
|
||||||
// btns containers
|
// btns containers
|
||||||
var btnNextSpan = createElm('span');
|
let btnNextSpan = createElm('span');
|
||||||
var btnPrevSpan = createElm('span');
|
let btnPrevSpan = createElm('span');
|
||||||
var btnLastSpan = createElm('span');
|
let btnLastSpan = createElm('span');
|
||||||
var btnFirstSpan = createElm('span');
|
let btnFirstSpan = createElm('span');
|
||||||
|
|
||||||
if (this.hasPagingBtns) {
|
if (this.hasBtns) {
|
||||||
// Next button
|
// Next button
|
||||||
if (!this.btnNextPageHtml) {
|
if (!this.btnNextPageHtml) {
|
||||||
var btnNext = createElm(INPUT,
|
let btnNext = createElm(INPUT,
|
||||||
['type', 'button'],
|
['type', 'button'],
|
||||||
['value', this.btnNextPageText],
|
['value', this.btnNextPageText],
|
||||||
['title', 'Next']
|
['title', 'Next']
|
||||||
);
|
);
|
||||||
btnNext.className = this.btnPageCssClass;
|
btnNext.className = this.btnCssClass;
|
||||||
addEvt(btnNext, 'click', evt.next);
|
addEvt(btnNext, 'click', evt.next);
|
||||||
btnNextSpan.appendChild(btnNext);
|
btnNextSpan.appendChild(btnNext);
|
||||||
} else {
|
} else {
|
||||||
|
@ -392,12 +402,12 @@ export class Paging extends Feature {
|
||||||
}
|
}
|
||||||
// Previous button
|
// Previous button
|
||||||
if (!this.btnPrevPageHtml) {
|
if (!this.btnPrevPageHtml) {
|
||||||
var btnPrev = createElm(INPUT,
|
let btnPrev = createElm(INPUT,
|
||||||
['type', 'button'],
|
['type', 'button'],
|
||||||
['value', this.btnPrevPageText],
|
['value', this.btnPrevPageText],
|
||||||
['title', 'Previous']
|
['title', 'Previous']
|
||||||
);
|
);
|
||||||
btnPrev.className = this.btnPageCssClass;
|
btnPrev.className = this.btnCssClass;
|
||||||
addEvt(btnPrev, 'click', evt.prev);
|
addEvt(btnPrev, 'click', evt.prev);
|
||||||
btnPrevSpan.appendChild(btnPrev);
|
btnPrevSpan.appendChild(btnPrev);
|
||||||
} else {
|
} else {
|
||||||
|
@ -406,12 +416,12 @@ export class Paging extends Feature {
|
||||||
}
|
}
|
||||||
// Last button
|
// Last button
|
||||||
if (!this.btnLastPageHtml) {
|
if (!this.btnLastPageHtml) {
|
||||||
var btnLast = createElm(INPUT,
|
let btnLast = createElm(INPUT,
|
||||||
['type', 'button'],
|
['type', 'button'],
|
||||||
['value', this.btnLastPageText],
|
['value', this.btnLastPageText],
|
||||||
['title', 'Last']
|
['title', 'Last']
|
||||||
);
|
);
|
||||||
btnLast.className = this.btnPageCssClass;
|
btnLast.className = this.btnCssClass;
|
||||||
addEvt(btnLast, 'click', evt.last);
|
addEvt(btnLast, 'click', evt.last);
|
||||||
btnLastSpan.appendChild(btnLast);
|
btnLastSpan.appendChild(btnLast);
|
||||||
} else {
|
} else {
|
||||||
|
@ -420,12 +430,12 @@ export class Paging extends Feature {
|
||||||
}
|
}
|
||||||
// First button
|
// First button
|
||||||
if (!this.btnFirstPageHtml) {
|
if (!this.btnFirstPageHtml) {
|
||||||
var btnFirst = createElm(INPUT,
|
let btnFirst = createElm(INPUT,
|
||||||
['type', 'button'],
|
['type', 'button'],
|
||||||
['value', this.btnFirstPageText],
|
['value', this.btnFirstPageText],
|
||||||
['title', 'First']
|
['title', 'First']
|
||||||
);
|
);
|
||||||
btnFirst.className = this.btnPageCssClass;
|
btnFirst.className = this.btnCssClass;
|
||||||
addEvt(btnFirst, 'click', evt.first);
|
addEvt(btnFirst, 'click', evt.first);
|
||||||
btnFirstSpan.appendChild(btnFirst);
|
btnFirstSpan.appendChild(btnFirst);
|
||||||
} else {
|
} else {
|
||||||
|
@ -435,23 +445,22 @@ export class Paging extends Feature {
|
||||||
}
|
}
|
||||||
|
|
||||||
// paging elements (buttons+drop-down list) are added to defined element
|
// paging elements (buttons+drop-down list) are added to defined element
|
||||||
if (!this.pagingTgtId) {
|
let targetEl = !this.tgtId ?
|
||||||
tf.setToolbar();
|
tf.feature('toolbar').container(this.toolbarPosition) :
|
||||||
}
|
elm(this.tgtId);
|
||||||
var targetEl = !this.pagingTgtId ? tf.mDiv : elm(this.pagingTgtId);
|
|
||||||
targetEl.appendChild(btnFirstSpan);
|
targetEl.appendChild(btnFirstSpan);
|
||||||
targetEl.appendChild(btnPrevSpan);
|
targetEl.appendChild(btnPrevSpan);
|
||||||
|
|
||||||
var pgBeforeSpan = createElm('span');
|
let pgBeforeSpan = createElm('span');
|
||||||
pgBeforeSpan.appendChild(createText(this.pageText));
|
pgBeforeSpan.appendChild(createText(this.pageText));
|
||||||
pgBeforeSpan.className = this.nbPgSpanCssClass;
|
pgBeforeSpan.className = this.nbPgSpanCssClass;
|
||||||
targetEl.appendChild(pgBeforeSpan);
|
targetEl.appendChild(pgBeforeSpan);
|
||||||
targetEl.appendChild(slcPages);
|
targetEl.appendChild(slcPages);
|
||||||
var pgAfterSpan = createElm('span');
|
let pgAfterSpan = createElm('span');
|
||||||
pgAfterSpan.appendChild(createText(this.ofText));
|
pgAfterSpan.appendChild(createText(this.ofText));
|
||||||
pgAfterSpan.className = this.nbPgSpanCssClass;
|
pgAfterSpan.className = this.nbPgSpanCssClass;
|
||||||
targetEl.appendChild(pgAfterSpan);
|
targetEl.appendChild(pgAfterSpan);
|
||||||
var pgSpan = createElm('span');
|
let pgSpan = createElm('span');
|
||||||
pgSpan.className = this.nbPgSpanCssClass;
|
pgSpan.className = this.nbPgSpanCssClass;
|
||||||
pgSpan.appendChild(createText(' ' + this.nbPages + ' '));
|
pgSpan.appendChild(createText(' ' + this.nbPages + ' '));
|
||||||
targetEl.appendChild(pgSpan);
|
targetEl.appendChild(pgSpan);
|
||||||
|
@ -465,7 +474,7 @@ export class Paging extends Feature {
|
||||||
this.pgCont = pgSpan;
|
this.pgCont = pgSpan;
|
||||||
this.pgBefore = pgBeforeSpan;
|
this.pgBefore = pgBeforeSpan;
|
||||||
this.pgAfter = pgAfterSpan;
|
this.pgAfter = pgAfterSpan;
|
||||||
this.pagingSlc = slcPages;
|
this.pageSlc = slcPages;
|
||||||
|
|
||||||
this.setPagingInfo();
|
this.setPagingInfo();
|
||||||
|
|
||||||
|
@ -474,14 +483,15 @@ export class Paging extends Feature {
|
||||||
this.setPagingInfo(tf.validRowsIndex);
|
this.setPagingInfo(tf.validRowsIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.emitter.on(['after-filtering'], () => this.resetPagingInfo());
|
this.emitter.on(['after-filtering'], bound(this.resetPagingInfo, this));
|
||||||
this.emitter.on(['change-page'],
|
this.emitter.on(['change-page'], bound(this.changePageHandler, this));
|
||||||
(tf, pageNumber) => this.setPage(pageNumber));
|
|
||||||
this.emitter.on(['change-page-results'],
|
this.emitter.on(['change-page-results'],
|
||||||
(tf, pageLength) => this.changeResultsPerPage(pageLength));
|
bound(this.changePageResultsHandler, this));
|
||||||
|
|
||||||
/** @inherited */
|
/** @inherited */
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
|
|
||||||
|
this.emitter.emit('feature-initialized', this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -489,15 +499,11 @@ export class Paging extends Feature {
|
||||||
* @param {Boolean} filterTable Execute filtering once paging instanciated
|
* @param {Boolean} filterTable Execute filtering once paging instanciated
|
||||||
*/
|
*/
|
||||||
reset(filterTable = false) {
|
reset(filterTable = false) {
|
||||||
var tf = this.tf;
|
|
||||||
if (this.isEnabled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.enable();
|
this.enable();
|
||||||
this.init();
|
this.init();
|
||||||
|
|
||||||
if (filterTable) {
|
if (filterTable) {
|
||||||
tf.filter();
|
this.tf.filter();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -516,36 +522,38 @@ export class Paging extends Feature {
|
||||||
* @param {Array} validRows Collection of valid rows
|
* @param {Array} validRows Collection of valid rows
|
||||||
*/
|
*/
|
||||||
setPagingInfo(validRows) {
|
setPagingInfo(validRows) {
|
||||||
var tf = this.tf;
|
let tf = this.tf;
|
||||||
var mdiv = !this.pagingTgtId ? tf.mDiv : elm(this.pagingTgtId);
|
let cont = !this.tgtId ?
|
||||||
|
tf.feature('toolbar').container(this.toolbarPosition) :
|
||||||
|
elm(this.tgtId);
|
||||||
|
|
||||||
//store valid rows indexes
|
//store valid rows indexes
|
||||||
tf.validRowsIndex = validRows || tf.getValidRows(true);
|
tf.validRowsIndex = validRows || tf.getValidRows(true);
|
||||||
|
|
||||||
//calculate nb of pages
|
//calculate nb of pages
|
||||||
this.nbPages = Math.ceil(tf.validRowsIndex.length / this.pagingLength);
|
this.nbPages = Math.ceil(tf.validRowsIndex.length / this.pageLength);
|
||||||
//refresh page nb span
|
//refresh page nb span
|
||||||
this.pgCont.innerHTML = this.nbPages;
|
this.pgCont.innerHTML = this.nbPages;
|
||||||
//select clearing shortcut
|
//select clearing shortcut
|
||||||
if (this.pageSelectorType === SELECT) {
|
if (this.pageSelectorType === SELECT) {
|
||||||
this.pagingSlc.innerHTML = '';
|
this.pageSlc.innerHTML = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.nbPages > 0) {
|
if (this.nbPages > 0) {
|
||||||
mdiv.style.visibility = 'visible';
|
cont.style.visibility = 'visible';
|
||||||
if (this.pageSelectorType === SELECT) {
|
if (this.pageSelectorType === SELECT) {
|
||||||
for (var z = 0; z < this.nbPages; z++) {
|
for (let z = 0; z < this.nbPages; z++) {
|
||||||
var opt = createOpt(z + 1, z * this.pagingLength, false);
|
let opt = createOpt(z + 1, z * this.pageLength, false);
|
||||||
this.pagingSlc.options[z] = opt;
|
this.pageSlc.options[z] = opt;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//input type
|
//input type
|
||||||
this.pagingSlc.value = this.currentPageNb;
|
this.pageSlc.value = this.currentPageNb;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/*** if no results paging select and buttons are hidden ***/
|
/*** if no results paging select and buttons are hidden ***/
|
||||||
mdiv.style.visibility = 'hidden';
|
cont.style.visibility = 'hidden';
|
||||||
}
|
}
|
||||||
this.groupByPage(tf.validRowsIndex);
|
this.groupByPage(tf.validRowsIndex);
|
||||||
}
|
}
|
||||||
|
@ -555,10 +563,10 @@ export class Paging extends Feature {
|
||||||
* @param {Array} validRows Collection of valid rows
|
* @param {Array} validRows Collection of valid rows
|
||||||
*/
|
*/
|
||||||
groupByPage(validRows) {
|
groupByPage(validRows) {
|
||||||
var tf = this.tf;
|
let tf = this.tf;
|
||||||
var rows = tf.tbl.rows;
|
let rows = tf.dom().rows;
|
||||||
var startPagingRow = parseInt(this.startPagingRow, 10);
|
let startPagingRow = parseInt(this.startPagingRow, 10);
|
||||||
var endPagingRow = startPagingRow + parseInt(this.pagingLength, 10);
|
let endPagingRow = startPagingRow + parseInt(this.pageLength, 10);
|
||||||
|
|
||||||
//store valid rows indexes
|
//store valid rows indexes
|
||||||
if (validRows) {
|
if (validRows) {
|
||||||
|
@ -566,11 +574,11 @@ export class Paging extends Feature {
|
||||||
}
|
}
|
||||||
|
|
||||||
//this loop shows valid rows of current page
|
//this loop shows valid rows of current page
|
||||||
for (var h = 0, len = tf.getValidRowsNb(true); h < len; h++) {
|
for (let h = 0, len = tf.getValidRowsNb(true); h < len; h++) {
|
||||||
var validRowIdx = tf.validRowsIndex[h];
|
let validRowIdx = tf.validRowsIndex[h];
|
||||||
var r = rows[validRowIdx];
|
let r = rows[validRowIdx];
|
||||||
var isRowValid = r.getAttribute('validRow');
|
let isRowValid = r.getAttribute('validRow');
|
||||||
var rowDisplayed = false;
|
let rowDisplayed = false;
|
||||||
|
|
||||||
if (h >= startPagingRow && h < endPagingRow) {
|
if (h >= startPagingRow && h < endPagingRow) {
|
||||||
if (isNull(isRowValid) || Boolean(isRowValid === 'true')) {
|
if (isNull(isRowValid) || Boolean(isRowValid === 'true')) {
|
||||||
|
@ -601,11 +609,11 @@ export class Paging extends Feature {
|
||||||
* 'previous', 'last', 'first' or page number as per param
|
* 'previous', 'last', 'first' or page number as per param
|
||||||
*/
|
*/
|
||||||
setPage(cmd) {
|
setPage(cmd) {
|
||||||
var tf = this.tf;
|
let tf = this.tf;
|
||||||
if (!tf.isInitialized() || !this.isEnabled()) {
|
if (!tf.isInitialized() || !this.isEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var btnEvt = this.evt,
|
let btnEvt = this.evt,
|
||||||
cmdtype = typeof cmd;
|
cmdtype = typeof cmd;
|
||||||
if (cmdtype === 'string') {
|
if (cmdtype === 'string') {
|
||||||
switch (cmd.toLowerCase()) {
|
switch (cmd.toLowerCase()) {
|
||||||
|
@ -635,10 +643,10 @@ export class Paging extends Feature {
|
||||||
* Generates UI elements for the number of results per page drop-down
|
* Generates UI elements for the number of results per page drop-down
|
||||||
*/
|
*/
|
||||||
setResultsPerPage() {
|
setResultsPerPage() {
|
||||||
var tf = this.tf;
|
let tf = this.tf;
|
||||||
var evt = this.evt;
|
let evt = this.evt;
|
||||||
|
|
||||||
if (this.resultsPerPageSlc || !this.resultsPerPage) {
|
if (this.pageLengthSlc || !this.resultsPerPage) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -647,22 +655,20 @@ export class Paging extends Feature {
|
||||||
ev.target.blur();
|
ev.target.blur();
|
||||||
};
|
};
|
||||||
|
|
||||||
var slcR = createElm(SELECT);
|
let slcR = createElm(SELECT);
|
||||||
slcR.className = this.resultsSlcCssClass;
|
slcR.className = this.resultsSlcCssClass;
|
||||||
var slcRText = this.resultsPerPage[0],
|
let slcRText = this.resultsPerPage[0],
|
||||||
slcROpts = this.resultsPerPage[1];
|
slcROpts = this.resultsPerPage[1];
|
||||||
var slcRSpan = createElm('span');
|
let slcRSpan = createElm('span');
|
||||||
slcRSpan.className = this.resultsSpanCssClass;
|
slcRSpan.className = this.resultsSpanCssClass;
|
||||||
|
|
||||||
// results per page select is added to external element
|
// results per page select is added to external element
|
||||||
if (!this.resultsPerPageTgtId) {
|
let targetEl = !this.pageLengthTgtId ?
|
||||||
tf.setToolbar();
|
tf.feature('toolbar').container(RIGHT) :
|
||||||
}
|
elm(this.pageLengthTgtId);
|
||||||
var targetEl = !this.resultsPerPageTgtId ?
|
|
||||||
tf.rDiv : elm(this.resultsPerPageTgtId);
|
|
||||||
slcRSpan.appendChild(createText(slcRText));
|
slcRSpan.appendChild(createText(slcRText));
|
||||||
|
|
||||||
var help = tf.feature('help');
|
let help = tf.feature('help');
|
||||||
if (help && help.btn) {
|
if (help && help.btn) {
|
||||||
help.btn.parentNode.insertBefore(slcRSpan, help.btn);
|
help.btn.parentNode.insertBefore(slcRSpan, help.btn);
|
||||||
help.btn.parentNode.insertBefore(slcR, help.btn);
|
help.btn.parentNode.insertBefore(slcR, help.btn);
|
||||||
|
@ -671,31 +677,31 @@ export class Paging extends Feature {
|
||||||
targetEl.appendChild(slcR);
|
targetEl.appendChild(slcR);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var r = 0; r < slcROpts.length; r++) {
|
for (let r = 0; r < slcROpts.length; r++) {
|
||||||
var currOpt = new Option(slcROpts[r], slcROpts[r], false, false);
|
let currOpt = new Option(slcROpts[r], slcROpts[r], false, false);
|
||||||
slcR.options[r] = currOpt;
|
slcR.options[r] = currOpt;
|
||||||
}
|
}
|
||||||
addEvt(slcR, 'change', evt.slcResultsChange);
|
addEvt(slcR, 'change', evt.slcResultsChange);
|
||||||
this.slcResultsTxt = slcRSpan;
|
this.slcResultsTxt = slcRSpan;
|
||||||
this.resultsPerPageSlc = slcR;
|
this.pageLengthSlc = slcR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove number of results per page UI elements
|
* Remove number of results per page UI elements
|
||||||
*/
|
*/
|
||||||
removeResultsPerPage() {
|
removeResultsPerPage() {
|
||||||
var tf = this.tf;
|
let tf = this.tf;
|
||||||
if (!tf.isInitialized() || !this.resultsPerPageSlc ||
|
if (!tf.isInitialized() || !this.pageLengthSlc ||
|
||||||
!this.resultsPerPage) {
|
!this.resultsPerPage) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.resultsPerPageSlc) {
|
if (this.pageLengthSlc) {
|
||||||
removeElm(this.resultsPerPageSlc);
|
removeElm(this.pageLengthSlc);
|
||||||
}
|
}
|
||||||
if (this.slcResultsTxt) {
|
if (this.slcResultsTxt) {
|
||||||
removeElm(this.slcResultsTxt);
|
removeElm(this.slcResultsTxt);
|
||||||
}
|
}
|
||||||
this.resultsPerPageSlc = null;
|
this.pageLengthSlc = null;
|
||||||
this.slcResultsTxt = null;
|
this.slcResultsTxt = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -704,7 +710,7 @@ export class Paging extends Feature {
|
||||||
* @param {Number} index Index of the page (0-n)
|
* @param {Number} index Index of the page (0-n)
|
||||||
*/
|
*/
|
||||||
changePage(index) {
|
changePage(index) {
|
||||||
var tf = this.tf;
|
let tf = this.tf;
|
||||||
|
|
||||||
if (!this.isEnabled()) {
|
if (!this.isEnabled()) {
|
||||||
return;
|
return;
|
||||||
|
@ -714,20 +720,20 @@ export class Paging extends Feature {
|
||||||
|
|
||||||
if (index === null) {
|
if (index === null) {
|
||||||
index = this.pageSelectorType === SELECT ?
|
index = this.pageSelectorType === SELECT ?
|
||||||
this.pagingSlc.options.selectedIndex : this.pagingSlc.value - 1;
|
this.pageSlc.options.selectedIndex : this.pageSlc.value - 1;
|
||||||
}
|
}
|
||||||
if (index >= 0 && index <= (this.nbPages - 1)) {
|
if (index >= 0 && index <= (this.nbPages - 1)) {
|
||||||
this.onBeforeChangePage(this, (index + 1));
|
this.onBeforeChangePage(this, (index + 1));
|
||||||
|
|
||||||
this.currentPageNb = parseInt(index, 10) + 1;
|
this.currentPageNb = parseInt(index, 10) + 1;
|
||||||
if (this.pageSelectorType === SELECT) {
|
if (this.pageSelectorType === SELECT) {
|
||||||
this.pagingSlc.options[index].selected = true;
|
this.pageSlc.options[index].selected = true;
|
||||||
} else {
|
} else {
|
||||||
this.pagingSlc.value = this.currentPageNb;
|
this.pageSlc.value = this.currentPageNb;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.startPagingRow = (this.pageSelectorType === SELECT) ?
|
this.startPagingRow = (this.pageSelectorType === SELECT) ?
|
||||||
this.pagingSlc.value : (index * this.pagingLength);
|
this.pageSlc.value : (index * this.pageLength);
|
||||||
|
|
||||||
this.groupByPage();
|
this.groupByPage();
|
||||||
|
|
||||||
|
@ -746,7 +752,7 @@ export class Paging extends Feature {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.resultsPerPageSlc.value = val;
|
this.pageLengthSlc.value = val;
|
||||||
this.onChangeResultsPerPage();
|
this.onChangeResultsPerPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -754,49 +760,51 @@ export class Paging extends Feature {
|
||||||
* Change rows according to page results drop-down
|
* Change rows according to page results drop-down
|
||||||
*/
|
*/
|
||||||
onChangeResultsPerPage() {
|
onChangeResultsPerPage() {
|
||||||
var tf = this.tf;
|
let tf = this.tf;
|
||||||
|
|
||||||
if (!this.isEnabled()) {
|
if (!this.isEnabled() || tf.getValidRowsNb() === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.emitter.emit('before-page-length-change', tf);
|
let {
|
||||||
|
pageLengthSlc: slcR, pageSelectorType, pageSlc, emitter
|
||||||
|
} = this;
|
||||||
|
|
||||||
var slcR = this.resultsPerPageSlc;
|
emitter.emit('before-page-length-change', tf);
|
||||||
var slcIndex = slcR.selectedIndex;
|
|
||||||
var slcPagesSelIndex = (this.pageSelectorType === SELECT) ?
|
|
||||||
this.pagingSlc.selectedIndex :
|
|
||||||
parseInt(this.pagingSlc.value - 1, 10);
|
|
||||||
this.pagingLength = parseInt(slcR.options[slcIndex].value, 10);
|
|
||||||
this.startPagingRow = this.pagingLength * slcPagesSelIndex;
|
|
||||||
|
|
||||||
if (!isNaN(this.pagingLength)) {
|
let slcIndex = slcR.selectedIndex;
|
||||||
|
let slcPagesSelIndex = (pageSelectorType === SELECT) ?
|
||||||
|
pageSlc.selectedIndex : parseInt(pageSlc.value - 1, 10);
|
||||||
|
this.pageLength = parseInt(slcR.options[slcIndex].value, 10);
|
||||||
|
this.startPagingRow = this.pageLength * slcPagesSelIndex;
|
||||||
|
|
||||||
|
if (!isNaN(this.pageLength)) {
|
||||||
if (this.startPagingRow >= tf.nbFilterableRows) {
|
if (this.startPagingRow >= tf.nbFilterableRows) {
|
||||||
this.startPagingRow = (tf.nbFilterableRows - this.pagingLength);
|
this.startPagingRow = (tf.nbFilterableRows - this.pageLength);
|
||||||
}
|
}
|
||||||
this.setPagingInfo();
|
this.setPagingInfo();
|
||||||
|
|
||||||
if (this.pageSelectorType === SELECT) {
|
if (pageSelectorType === SELECT) {
|
||||||
var slcIdx =
|
let slcIdx = (pageSlc.options.length - 1 <= slcPagesSelIndex) ?
|
||||||
(this.pagingSlc.options.length - 1 <= slcPagesSelIndex) ?
|
(pageSlc.options.length - 1) :
|
||||||
(this.pagingSlc.options.length - 1) : slcPagesSelIndex;
|
slcPagesSelIndex;
|
||||||
this.pagingSlc.options[slcIdx].selected = true;
|
pageSlc.options[slcIdx].selected = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.emitter.emit('after-page-length-change', tf, this.pagingLength);
|
emitter.emit('after-page-length-change', tf, this.pageLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Re-set page nb at page re-load
|
* Re-set page nb at page re-load
|
||||||
*/
|
*/
|
||||||
resetPage() {
|
resetPage() {
|
||||||
var tf = this.tf;
|
let tf = this.tf;
|
||||||
if (!this.isEnabled()) {
|
if (!this.isEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.emitter.emit('before-reset-page', tf);
|
this.emitter.emit('before-reset-page', tf);
|
||||||
var pgNb = tf.feature('store').getPageNb();
|
let pgNb = tf.feature('store').getPageNb();
|
||||||
if (pgNb !== '') {
|
if (pgNb !== '') {
|
||||||
this.changePage((pgNb - 1));
|
this.changePage((pgNb - 1));
|
||||||
}
|
}
|
||||||
|
@ -807,20 +815,30 @@ export class Paging extends Feature {
|
||||||
* Re-set page length value at page re-load
|
* Re-set page length value at page re-load
|
||||||
*/
|
*/
|
||||||
resetPageLength() {
|
resetPageLength() {
|
||||||
var tf = this.tf;
|
let tf = this.tf;
|
||||||
if (!this.isEnabled()) {
|
if (!this.isEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.emitter.emit('before-reset-page-length', tf);
|
this.emitter.emit('before-reset-page-length', tf);
|
||||||
var pglenIndex = tf.feature('store').getPageLength();
|
let pglenIndex = tf.feature('store').getPageLength();
|
||||||
|
|
||||||
if (pglenIndex !== '') {
|
if (pglenIndex !== '') {
|
||||||
this.resultsPerPageSlc.options[pglenIndex].selected = true;
|
this.pageLengthSlc.options[pglenIndex].selected = true;
|
||||||
this.changeResultsPerPage();
|
this.changeResultsPerPage();
|
||||||
}
|
}
|
||||||
this.emitter.emit('after-reset-page-length', tf, pglenIndex);
|
this.emitter.emit('after-reset-page-length', tf, pglenIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @private */
|
||||||
|
changePageHandler(tf, pageNumber) {
|
||||||
|
this.setPage(pageNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @private */
|
||||||
|
changePageResultsHandler(tf, pageLength) {
|
||||||
|
this.changeResultsPerPage(pageLength);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove paging feature
|
* Remove paging feature
|
||||||
*/
|
*/
|
||||||
|
@ -829,16 +847,16 @@ export class Paging extends Feature {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var evt = this.evt;
|
let evt = this.evt;
|
||||||
|
|
||||||
if (this.pagingSlc) {
|
if (this.pageSlc) {
|
||||||
if (this.pageSelectorType === SELECT) {
|
if (this.pageSelectorType === SELECT) {
|
||||||
removeEvt(this.pagingSlc, 'change', evt.slcPagesChange);
|
removeEvt(this.pageSlc, 'change', evt.slcPagesChange);
|
||||||
}
|
}
|
||||||
else if (this.pageSelectorType === INPUT) {
|
else if (this.pageSelectorType === INPUT) {
|
||||||
removeEvt(this.pagingSlc, 'keypress', evt._detectKey);
|
removeEvt(this.pageSlc, 'keypress', evt._detectKey);
|
||||||
}
|
}
|
||||||
removeElm(this.pagingSlc);
|
removeElm(this.pageSlc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.btnNextCont) {
|
if (this.btnNextCont) {
|
||||||
|
@ -884,15 +902,15 @@ export class Paging extends Feature {
|
||||||
this.removeResultsPerPage();
|
this.removeResultsPerPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.emitter.off(['after-filtering'], () => this.resetPagingInfo());
|
this.emitter.off(['after-filtering'],
|
||||||
this.emitter.off(['change-page'],
|
bound(this.resetPagingInfo, this));
|
||||||
(tf, pageNumber) => this.setPage(pageNumber));
|
this.emitter.off(['change-page'], bound(this.changePageHandler, this));
|
||||||
this.emitter.off(['change-page-results'],
|
this.emitter.off(['change-page-results'],
|
||||||
(tf, pageLength) => this.changeResultsPerPage(pageLength));
|
bound(this.changePageResultsHandler, this));
|
||||||
|
|
||||||
this.pagingSlc = null;
|
this.pageSlc = null;
|
||||||
this.nbPages = 0;
|
this.nbPages = 0;
|
||||||
this.disable();
|
|
||||||
this.initialized = false;
|
this.initialized = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import {Feature} from '../feature';
|
import {Feature} from '../feature';
|
||||||
import {isFn, isUndef, EMPTY_FN} from '../types';
|
import {isUndef, EMPTY_FN} from '../types';
|
||||||
import {createElm, removeElm} from '../dom';
|
import {createElm, removeElm} from '../dom';
|
||||||
import {addEvt, cancelEvt, stopEvt, targetEvt, removeEvt} from '../event';
|
import {addEvt, cancelEvt, stopEvt, targetEvt, removeEvt} from '../event';
|
||||||
import {INPUT, NONE, CHECKLIST, MULTIPLE} from '../const';
|
import {INPUT, NONE, CHECKLIST, MULTIPLE} from '../const';
|
||||||
import {root} from '../root';
|
import {root} from '../root';
|
||||||
|
import {defaultsStr, defaultsBool, defaultsArr, defaultsFn} from '../settings';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pop-up filter component
|
* Pop-up filter component
|
||||||
|
@ -18,84 +19,81 @@ export class PopupFilter extends Feature {
|
||||||
* @param {TableFilter} tf TableFilter instance
|
* @param {TableFilter} tf TableFilter instance
|
||||||
*/
|
*/
|
||||||
constructor(tf) {
|
constructor(tf) {
|
||||||
super(tf, 'popupFilters');
|
super(tf, PopupFilter);
|
||||||
|
|
||||||
// Configuration object
|
// Configuration object
|
||||||
let f = this.config;
|
let f = this.config.popup_filters || {};
|
||||||
|
|
||||||
// Enable external filters
|
|
||||||
tf.isExternalFlt = true;
|
|
||||||
tf.externalFltTgtIds = [];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close active popup filter upon filtering, enabled by default
|
* Close active popup filter upon filtering, enabled by default
|
||||||
* @type {Boolean}
|
* @type {Boolean}
|
||||||
*/
|
*/
|
||||||
this.closeOnFiltering = f.popup_filters_close_on_filtering === false ?
|
this.closeOnFiltering = defaultsBool(f.close_on_filtering, true);
|
||||||
false : true;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter icon path
|
* Filter icon path
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.iconPath = f.popup_filters_image ||
|
this.iconPath = defaultsStr(f.image, tf.themesPath + 'icn_filter.gif');
|
||||||
tf.themesPath + 'icn_filter.gif';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Active filter icon path
|
* Active filter icon path
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
this.activeIconPath = f.popup_filters_image_active ||
|
this.activeIconPath = defaultsStr(f.image_active,
|
||||||
tf.themesPath + 'icn_filterActive.gif';
|
tf.themesPath + 'icn_filterActive.gif');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTML for the filter icon
|
* HTML for the filter icon
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
this.iconHtml = f.popup_filters_image_html ||
|
this.iconHtml = defaultsStr(f.image_html,
|
||||||
'<img src="' + this.iconPath + '" alt="Column filter" />';
|
'<img src="' + this.iconPath + '" alt="Column filter" />');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Css class assigned to the popup container element
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
this.placeholderCssClass = defaultsStr(f.placeholder_css_class,
|
||||||
|
'popUpPlaceholder');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class assigned to filter container element
|
* Css class assigned to filter container element
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.containerCssClass = f.popup_div_css_class || 'popUpFilter';
|
this.containerCssClass = defaultsStr(f.div_css_class, 'popUpFilter');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure filter's container element width matches column width, enabled
|
* Ensure filter's container element width matches column width, enabled
|
||||||
* by default
|
* by default
|
||||||
* @type {Boolean}
|
* @type {Boolean}
|
||||||
*/
|
*/
|
||||||
this.adjustToContainer =
|
this.adjustToContainer = defaultsBool(f.adjust_to_container, true);
|
||||||
f.popup_filters_adjust_to_container === false ? false : true;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired before a popup filter is opened
|
* Callback fired before a popup filter is opened
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onBeforeOpen = isFn(f.on_before_popup_filter_open) ?
|
this.onBeforeOpen = defaultsFn(f.on_before_popup_filter_open, EMPTY_FN);
|
||||||
f.on_before_popup_filter_open : EMPTY_FN;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired after a popup filter is opened
|
* Callback fired after a popup filter is opened
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onAfterOpen = isFn(f.on_after_popup_filter_open) ?
|
this.onAfterOpen = defaultsFn(f.on_after_popup_filter_open, EMPTY_FN);
|
||||||
f.on_after_popup_filter_open : EMPTY_FN;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired before a popup filter is closed
|
* Callback fired before a popup filter is closed
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onBeforeClose = isFn(f.on_before_popup_filter_close) ?
|
this.onBeforeClose = defaultsFn(f.on_before_popup_filter_close,
|
||||||
f.on_before_popup_filter_close : EMPTY_FN;
|
EMPTY_FN);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired after a popup filter is closed
|
* Callback fired after a popup filter is closed
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onAfterClose = isFn(f.on_after_popup_filter_close) ?
|
this.onAfterClose = defaultsFn(f.on_after_popup_filter_close, EMPTY_FN);
|
||||||
f.on_after_popup_filter_close : EMPTY_FN;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collection of filters spans
|
* Collection of filters spans
|
||||||
|
@ -123,7 +121,7 @@ export class PopupFilter extends Feature {
|
||||||
* @type {Array}
|
* @type {Array}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.fltElms = this.filtersCache || [];
|
this.fltElms = defaultsArr(this.filtersCache, []);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prefix for pop-up filter container ID
|
* Prefix for pop-up filter container ID
|
||||||
|
@ -198,6 +196,12 @@ export class PopupFilter extends Feature {
|
||||||
|
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
|
|
||||||
|
// Enable external filters
|
||||||
|
tf.externalFltIds = [''];
|
||||||
|
|
||||||
|
// Override filters row index supplied by configuration
|
||||||
|
tf.filtersRowIndex = 0;
|
||||||
|
|
||||||
// Override headers row index if no grouped headers
|
// Override headers row index if no grouped headers
|
||||||
// TODO: Because of the filters row generation, headers row index needs
|
// TODO: Because of the filters row generation, headers row index needs
|
||||||
// adjusting: prevent useless row generation
|
// adjusting: prevent useless row generation
|
||||||
|
@ -246,10 +250,8 @@ export class PopupFilter extends Feature {
|
||||||
// adjusting: prevent useless row generation
|
// adjusting: prevent useless row generation
|
||||||
tf.headersRow++;
|
tf.headersRow++;
|
||||||
|
|
||||||
for (let i = 0; i < tf.nbCells; i++) {
|
tf.eachCol(
|
||||||
if (tf.getFilterType(i) === NONE) {
|
(i) => {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let icon = createElm('span', ['ci', i]);
|
let icon = createElm('span', ['ci', i]);
|
||||||
icon.innerHTML = this.iconHtml;
|
icon.innerHTML = this.iconHtml;
|
||||||
let header = tf.getHeaderElement(i);
|
let header = tf.getHeaderElement(i);
|
||||||
|
@ -257,7 +259,10 @@ export class PopupFilter extends Feature {
|
||||||
addEvt(icon, 'click', (evt) => this.onClick(evt));
|
addEvt(icon, 'click', (evt) => this.onClick(evt));
|
||||||
this.fltSpans[i] = icon;
|
this.fltSpans[i] = icon;
|
||||||
this.fltIcons[i] = icon.firstChild;
|
this.fltIcons[i] = icon.firstChild;
|
||||||
}
|
},
|
||||||
|
// continue condition function
|
||||||
|
(i) => tf.getFilterType(i) === NONE
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -277,12 +282,14 @@ export class PopupFilter extends Feature {
|
||||||
build(colIndex, div) {
|
build(colIndex, div) {
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
let contId = `${this.prfxDiv}${tf.id}_${colIndex}`;
|
let contId = `${this.prfxDiv}${tf.id}_${colIndex}`;
|
||||||
let cont = div || createElm('div', ['id', contId]);
|
let placeholder = createElm('div', ['class', this.placeholderCssClass]);
|
||||||
cont.className = this.containerCssClass;
|
let cont = div ||
|
||||||
tf.externalFltTgtIds.push(cont.id);
|
createElm('div', ['id', contId], ['class', this.containerCssClass]);
|
||||||
|
tf.externalFltIds[colIndex] = cont.id;
|
||||||
|
placeholder.appendChild(cont);
|
||||||
|
|
||||||
let header = tf.getHeaderElement(colIndex);
|
let header = tf.getHeaderElement(colIndex);
|
||||||
header.insertBefore(cont, header.firstChild);
|
header.insertBefore(placeholder, header.firstChild);
|
||||||
addEvt(cont, 'click', (evt) => stopEvt(evt));
|
addEvt(cont, 'click', (evt) => stopEvt(evt));
|
||||||
this.fltElms[colIndex] = cont;
|
this.fltElms[colIndex] = cont;
|
||||||
}
|
}
|
||||||
|
@ -364,7 +371,7 @@ export class PopupFilter extends Feature {
|
||||||
if (i === exceptIdx) {
|
if (i === exceptIdx) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let fltType = tf.getFilterType(i);
|
let fltType = this.tf.getFilterType(i);
|
||||||
let isMultipleFilter =
|
let isMultipleFilter =
|
||||||
(fltType === CHECKLIST || fltType === MULTIPLE);
|
(fltType === CHECKLIST || fltType === MULTIPLE);
|
||||||
|
|
||||||
|
@ -408,6 +415,7 @@ export class PopupFilter extends Feature {
|
||||||
this.filtersCache = [];
|
this.filtersCache = [];
|
||||||
for (let i = 0; i < this.fltElms.length; i++) {
|
for (let i = 0; i < this.fltElms.length; i++) {
|
||||||
let container = this.fltElms[i],
|
let container = this.fltElms[i],
|
||||||
|
placeholder = container.parentNode,
|
||||||
icon = this.fltSpans[i],
|
icon = this.fltSpans[i],
|
||||||
iconImg = this.fltIcons[i];
|
iconImg = this.fltIcons[i];
|
||||||
if (container) {
|
if (container) {
|
||||||
|
@ -415,6 +423,10 @@ export class PopupFilter extends Feature {
|
||||||
this.filtersCache[i] = container;
|
this.filtersCache[i] = container;
|
||||||
}
|
}
|
||||||
container = null;
|
container = null;
|
||||||
|
if (placeholder) {
|
||||||
|
removeElm(placeholder);
|
||||||
|
}
|
||||||
|
placeholder = null;
|
||||||
if (icon) {
|
if (icon) {
|
||||||
removeElm(icon);
|
removeElm(icon);
|
||||||
}
|
}
|
||||||
|
@ -429,7 +441,7 @@ export class PopupFilter extends Feature {
|
||||||
this.fltIcons = [];
|
this.fltIcons = [];
|
||||||
|
|
||||||
// TODO: expose an API to handle external filter IDs
|
// TODO: expose an API to handle external filter IDs
|
||||||
tf.externalFltTgtIds = [];
|
this.tf.externalFltIds = [];
|
||||||
|
|
||||||
// unsubscribe to events
|
// unsubscribe to events
|
||||||
this.emitter.off(['before-filtering'], () => this.setIconsState());
|
this.emitter.off(['before-filtering'], () => this.setIconsState());
|
||||||
|
@ -444,3 +456,6 @@ export class PopupFilter extends Feature {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: remove as soon as feature name is fixed
|
||||||
|
PopupFilter.meta = {altName: 'popupFilters'};
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import {Feature} from '../feature';
|
import {Feature} from '../feature';
|
||||||
import {createElm, createText, elm, removeElm} from '../dom';
|
import {createElm, createText, elm, removeElm} from '../dom';
|
||||||
import {isFn, EMPTY_FN} from '../types';
|
import {EMPTY_FN, isNull} from '../types';
|
||||||
|
import {defaultsStr, defaultsFn} from '../settings';
|
||||||
|
import {LEFT} from './toolbar';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rows counter UI component
|
* Rows counter UI component
|
||||||
|
@ -15,16 +17,16 @@ export class RowsCounter extends Feature {
|
||||||
* @param {TableFilter} tf TableFilter instance
|
* @param {TableFilter} tf TableFilter instance
|
||||||
*/
|
*/
|
||||||
constructor(tf) {
|
constructor(tf) {
|
||||||
super(tf, 'rowsCounter');
|
super(tf, RowsCounter);
|
||||||
|
|
||||||
// TableFilter configuration
|
// TableFilter configuration
|
||||||
let f = this.config;
|
let f = this.config.rows_counter || {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID of custom container element
|
* ID of custom container element
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.targetId = f.rows_counter_target_id || null;
|
this.targetId = defaultsStr(f.target_id, null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Container DOM element
|
* Container DOM element
|
||||||
|
@ -44,14 +46,14 @@ export class RowsCounter extends Feature {
|
||||||
* Text preceding the total number of rows
|
* Text preceding the total number of rows
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.text = f.rows_counter_text || 'Rows: ';
|
this.text = defaultsStr(f.text, 'Rows: ');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Separator symbol appearing between the first and last visible rows of
|
* Separator symbol appearing between the first and last visible rows of
|
||||||
* current page when paging is enabled. ie: Rows: 31-40 / 70
|
* current page when paging is enabled. ie: Rows: 31-40 / 70
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.fromToTextSeparator = f.from_to_text_separator || '-';
|
this.fromToTextSeparator = defaultsStr(f.separator, '-');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Separator symbol appearing between the first and last visible rows of
|
* Separator symbol appearing between the first and last visible rows of
|
||||||
|
@ -59,27 +61,33 @@ export class RowsCounter extends Feature {
|
||||||
* enabled. ie: Rows: 31-40 / 70
|
* enabled. ie: Rows: 31-40 / 70
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.overText = f.over_text || ' / ';
|
this.overText = defaultsStr(f.over_text, ' / ');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for container element
|
* Css class for container element
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.cssClass = f.tot_rows_css_class || 'tot';
|
this.cssClass = defaultsStr(f.css_class, 'tot');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default position in toolbar ('left'|'center'|'right')
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
this.toolbarPosition = defaultsStr(f.toolbar_position, LEFT);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired before the counter is refreshed
|
* Callback fired before the counter is refreshed
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onBeforeRefreshCounter = isFn(f.on_before_refresh_counter) ?
|
this.onBeforeRefreshCounter = defaultsFn(f.on_before_refresh_counter,
|
||||||
f.on_before_refresh_counter : EMPTY_FN;
|
EMPTY_FN);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired after the counter is refreshed
|
* Callback fired after the counter is refreshed
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onAfterRefreshCounter = isFn(f.on_after_refresh_counter) ?
|
this.onAfterRefreshCounter = defaultsFn(f.on_after_refresh_counter,
|
||||||
f.on_after_refresh_counter : EMPTY_FN;
|
EMPTY_FN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -90,6 +98,8 @@ export class RowsCounter extends Feature {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.emitter.emit('initializing-feature', this, !isNull(this.targetId));
|
||||||
|
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
|
|
||||||
//rows counter container
|
//rows counter container
|
||||||
|
@ -101,18 +111,16 @@ export class RowsCounter extends Feature {
|
||||||
countText.appendChild(createText(this.text));
|
countText.appendChild(createText(this.text));
|
||||||
|
|
||||||
// counter is added to defined element
|
// counter is added to defined element
|
||||||
if (!this.targetId) {
|
let targetEl = !this.targetId ?
|
||||||
tf.setToolbar();
|
tf.feature('toolbar').container(this.toolbarPosition) :
|
||||||
}
|
elm(this.targetId);
|
||||||
let targetEl = !this.targetId ? tf.lDiv : elm(this.targetId);
|
|
||||||
|
|
||||||
//default container: 'lDiv'
|
//default container: 'lDiv'
|
||||||
if (!this.targetId) {
|
if (!this.targetId) {
|
||||||
countDiv.appendChild(countText);
|
countDiv.appendChild(countText);
|
||||||
countDiv.appendChild(countSpan);
|
countDiv.appendChild(countSpan);
|
||||||
targetEl.appendChild(countDiv);
|
targetEl.appendChild(countDiv);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
//custom container, no need to append statusDiv
|
//custom container, no need to append statusDiv
|
||||||
targetEl.appendChild(countText);
|
targetEl.appendChild(countText);
|
||||||
targetEl.appendChild(countSpan);
|
targetEl.appendChild(countSpan);
|
||||||
|
@ -128,12 +136,13 @@ export class RowsCounter extends Feature {
|
||||||
/** @inherited */
|
/** @inherited */
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
this.refresh();
|
this.refresh();
|
||||||
|
|
||||||
|
this.emitter.emit('feature-initialized', this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refreshes the rows counter
|
* Refreshes the rows counter
|
||||||
* @param {Number} p Optional parameter the total number of rows to display
|
* @param {Number} p Optional parameter the total number of rows to display
|
||||||
* @returns
|
|
||||||
*/
|
*/
|
||||||
refresh(p) {
|
refresh(p) {
|
||||||
if (!this.initialized || !this.isEnabled()) {
|
if (!this.initialized || !this.isEnabled()) {
|
||||||
|
@ -154,16 +163,17 @@ export class RowsCounter extends Feature {
|
||||||
} else {
|
} else {
|
||||||
let paging = tf.feature('paging');
|
let paging = tf.feature('paging');
|
||||||
if (paging) {
|
if (paging) {
|
||||||
|
let nbValidRows = tf.getValidRowsNb();
|
||||||
//paging start row
|
//paging start row
|
||||||
let pagingStartRow = parseInt(paging.startPagingRow, 10) +
|
let pagingStartRow = parseInt(paging.startPagingRow, 10) +
|
||||||
((tf.getValidRowsNb() > 0) ? 1 : 0);
|
((nbValidRows > 0) ? 1 : 0);
|
||||||
let pagingEndRow =
|
let pagingEndRow =
|
||||||
(pagingStartRow + paging.pagingLength) - 1 <=
|
(pagingStartRow + paging.pageLength) - 1 <=
|
||||||
tf.getValidRowsNb() ?
|
nbValidRows ?
|
||||||
pagingStartRow + paging.pagingLength - 1 :
|
pagingStartRow + paging.pageLength - 1 :
|
||||||
tf.getValidRowsNb();
|
nbValidRows;
|
||||||
totTxt = pagingStartRow + this.fromToTextSeparator +
|
totTxt = pagingStartRow + this.fromToTextSeparator +
|
||||||
pagingEndRow + this.overText + tf.getValidRowsNb();
|
pagingEndRow + this.overText + nbValidRows;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ import {Hash} from './hash';
|
||||||
import {Storage} from './storage';
|
import {Storage} from './storage';
|
||||||
import {isEmpty} from '../string';
|
import {isEmpty} from '../string';
|
||||||
import {isArray, isNull, isString, isUndef} from '../types';
|
import {isArray, isNull, isString, isUndef} from '../types';
|
||||||
|
import {defaultsBool, defaultsNb} from '../settings';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Features state object persistable with localStorage, cookie or URL hash
|
* Features state object persistable with localStorage, cookie or URL hash
|
||||||
|
@ -18,9 +19,9 @@ export class State extends Feature {
|
||||||
* @param {TableFilter} tf TableFilter instance
|
* @param {TableFilter} tf TableFilter instance
|
||||||
*/
|
*/
|
||||||
constructor(tf) {
|
constructor(tf) {
|
||||||
super(tf, 'state');
|
super(tf, State);
|
||||||
|
|
||||||
let cfg = this.config.state;
|
let cfg = this.config.state || {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether state is persisted with URL hash
|
* Determines whether state is persisted with URL hash
|
||||||
|
@ -47,7 +48,7 @@ export class State extends Feature {
|
||||||
* Persist filters values, enabled by default
|
* Persist filters values, enabled by default
|
||||||
* @type {Boolean}
|
* @type {Boolean}
|
||||||
*/
|
*/
|
||||||
this.persistFilters = cfg.filters === false ? false : true;
|
this.persistFilters = defaultsBool(cfg.filters, true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Persist current page number when paging is enabled
|
* Persist current page number when paging is enabled
|
||||||
|
@ -83,8 +84,8 @@ export class State extends Feature {
|
||||||
* Cookie duration in hours
|
* Cookie duration in hours
|
||||||
* @type {Boolean}
|
* @type {Boolean}
|
||||||
*/
|
*/
|
||||||
this.cookieDuration = !isNaN(cfg.cookie_duration) ?
|
this.cookieDuration = defaultsNb(parseInt(cfg.cookie_duration, 10),
|
||||||
parseInt(cfg.cookie_duration, 10) : 87600;
|
87600);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable Storage if localStorage or cookie is required
|
* Enable Storage if localStorage or cookie is required
|
||||||
|
@ -212,9 +213,7 @@ export class State extends Feature {
|
||||||
this.storage.init();
|
this.storage.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @inherited */
|
||||||
* @inherited
|
|
||||||
*/
|
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,6 +365,7 @@ export class State extends Feature {
|
||||||
*/
|
*/
|
||||||
override(state) {
|
override(state) {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
|
this.emitter.emit('state-changed', this.tf, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -421,6 +421,10 @@ export class State extends Feature {
|
||||||
let state = this.state;
|
let state = this.state;
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
|
|
||||||
|
// clear all filters
|
||||||
|
// TODO: use tf.clearFilters() once it allows to not filter the table
|
||||||
|
tf.eachCol((colIdx) => tf.setFilterValue(colIdx, ''));
|
||||||
|
|
||||||
Object.keys(state).forEach((key) => {
|
Object.keys(state).forEach((key) => {
|
||||||
if (key.indexOf(this.prfxCol) !== -1) {
|
if (key.indexOf(this.prfxCol) !== -1) {
|
||||||
let colIdx = parseInt(key.replace(this.prfxCol, ''), 10);
|
let colIdx = parseInt(key.replace(this.prfxCol, ''), 10);
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import {Feature} from '../feature';
|
import {Feature} from '../feature';
|
||||||
import {root} from '../root';
|
import {root} from '../root';
|
||||||
import {createElm, createText, elm, removeElm} from '../dom';
|
import {createElm, createText, elm, removeElm} from '../dom';
|
||||||
import {isFn, EMPTY_FN} from '../types';
|
import {EMPTY_FN, isNull} from '../types';
|
||||||
|
import {defaultsStr, defaultsFn} from '../settings';
|
||||||
|
import {LEFT} from './toolbar';
|
||||||
|
|
||||||
const EVENTS = [
|
const EVENTS = [
|
||||||
'after-filtering',
|
'after-filtering',
|
||||||
|
@ -28,16 +30,16 @@ export class StatusBar extends Feature {
|
||||||
* @param {TableFilter} tf TableFilter instance
|
* @param {TableFilter} tf TableFilter instance
|
||||||
*/
|
*/
|
||||||
constructor(tf) {
|
constructor(tf) {
|
||||||
super(tf, 'statusBar');
|
super(tf, StatusBar);
|
||||||
|
|
||||||
// Configuration object
|
// Configuration object
|
||||||
let f = this.config;
|
let f = this.config.status_bar || {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID of custom container element
|
* ID of custom container element
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.targetId = f.status_bar_target_id || null;
|
this.targetId = defaultsStr(f.target_id, null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Container DOM element
|
* Container DOM element
|
||||||
|
@ -64,13 +66,13 @@ export class StatusBar extends Feature {
|
||||||
* Text preceding status message
|
* Text preceding status message
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.text = f.status_bar_text || '';
|
this.text = defaultsStr(f.text, '');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class for container element
|
* Css class for container element
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.cssClass = f.status_bar_css_class || 'status';
|
this.cssClass = defaultsStr(f.css_class, 'status');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message visibility duration in milliseconds
|
* Message visibility duration in milliseconds
|
||||||
|
@ -83,85 +85,91 @@ export class StatusBar extends Feature {
|
||||||
* Callback fired before the message is displayed
|
* Callback fired before the message is displayed
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onBeforeShowMsg = isFn(f.on_before_show_msg) ?
|
this.onBeforeShowMsg = defaultsFn(f.on_before_show_msg, EMPTY_FN);
|
||||||
f.on_before_show_msg : EMPTY_FN;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired after the message is displayed
|
* Callback fired after the message is displayed
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
this.onAfterShowMsg = isFn(f.on_after_show_msg) ?
|
this.onAfterShowMsg = defaultsFn(f.on_after_show_msg, EMPTY_FN);
|
||||||
f.on_after_show_msg : EMPTY_FN;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message appearing upon filtering
|
* Message appearing upon filtering
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.msgFilter = f.msg_filter || 'Filtering data...';
|
this.msgFilter = defaultsStr(f.msg_filter, 'Filtering data...');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message appearing when a drop-down filter is populated
|
* Message appearing when a drop-down filter is populated
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.msgPopulate = f.msg_populate || 'Populating filter...';
|
this.msgPopulate = defaultsStr(f.msg_populate, 'Populating filter...');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message appearing when a checklist filter is populated
|
* Message appearing when a checklist filter is populated
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.msgPopulateCheckList = f.msg_populate_checklist ||
|
this.msgPopulateCheckList = defaultsStr(f.msg_populate_checklist,
|
||||||
'Populating list...';
|
'Populating list...');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message appearing when a pagination page is changed
|
* Message appearing when a pagination page is changed
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.msgChangePage = f.msg_change_page || 'Collecting paging data...';
|
this.msgChangePage = defaultsStr(f.msg_change_page,
|
||||||
|
'Collecting paging data...');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message appearing when filters are cleared
|
* Message appearing when filters are cleared
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.msgClear = f.msg_clear || 'Clearing filters...';
|
this.msgClear = defaultsStr(f.msg_clear, 'Clearing filters...');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message appearing when the page length is changed
|
* Message appearing when the page length is changed
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.msgChangeResults = f.msg_change_results ||
|
this.msgChangeResults = defaultsStr(f.msg_change_results,
|
||||||
'Changing results per page...';
|
'Changing results per page...');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message appearing when the page is re-set
|
* Message appearing when the page is re-set
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.msgResetPage = f.msg_reset_page || 'Re-setting page...';
|
this.msgResetPage = defaultsStr(f.msg_reset_page, 'Re-setting page...');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message appearing when the page length is re-set
|
* Message appearing when the page length is re-set
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.msgResetPageLength = f.msg_reset_page_length ||
|
this.msgResetPageLength = defaultsStr(f.msg_reset_page_length,
|
||||||
'Re-setting page length...';
|
'Re-setting page length...');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message appearing upon column sorting
|
* Message appearing upon column sorting
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.msgSort = f.msg_sort || 'Sorting data...';
|
this.msgSort = defaultsStr(f.msg_sort, 'Sorting data...');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message appearing when extensions are loading
|
* Message appearing when extensions are loading
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.msgLoadExtensions = f.msg_load_extensions ||
|
this.msgLoadExtensions = defaultsStr(f.msg_load_extensions,
|
||||||
'Loading extensions...';
|
'Loading extensions...');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message appearing when themes are loading
|
* Message appearing when themes are loading
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.msgLoadThemes = f.msg_load_themes || 'Loading theme(s)...';
|
this.msgLoadThemes = defaultsStr(f.msg_load_themes,
|
||||||
|
'Loading theme(s)...');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default position in toolbar ('left'|'center'|'right')
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
this.toolbarPosition = defaultsStr(f.toolbar_position, LEFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -175,23 +183,24 @@ export class StatusBar extends Feature {
|
||||||
let tf = this.tf;
|
let tf = this.tf;
|
||||||
let emitter = this.emitter;
|
let emitter = this.emitter;
|
||||||
|
|
||||||
//status bar container
|
emitter.emit('initializing-feature', this, !isNull(this.targetId));
|
||||||
|
|
||||||
|
// status bar container
|
||||||
let statusDiv = createElm('div');
|
let statusDiv = createElm('div');
|
||||||
statusDiv.className = this.cssClass;
|
statusDiv.className = this.cssClass;
|
||||||
|
|
||||||
//status bar label
|
// status bar label
|
||||||
let statusSpan = createElm('span');
|
let statusSpan = createElm('span');
|
||||||
//preceding text
|
// preceding text
|
||||||
let statusSpanText = createElm('span');
|
let statusSpanText = createElm('span');
|
||||||
statusSpanText.appendChild(createText(this.text));
|
statusSpanText.appendChild(createText(this.text));
|
||||||
|
|
||||||
// target element container
|
// target element container
|
||||||
if (!this.targetId) {
|
let targetEl = (!this.targetId) ?
|
||||||
tf.setToolbar();
|
tf.feature('toolbar').container(this.toolbarPosition) :
|
||||||
}
|
elm(this.targetId);
|
||||||
let targetEl = (!this.targetId) ? tf.lDiv : elm(this.targetId);
|
|
||||||
|
|
||||||
//default container: 'lDiv'
|
// default container
|
||||||
if (!this.targetId) {
|
if (!this.targetId) {
|
||||||
statusDiv.appendChild(statusSpanText);
|
statusDiv.appendChild(statusSpanText);
|
||||||
statusDiv.appendChild(statusSpan);
|
statusDiv.appendChild(statusSpan);
|
||||||
|
@ -206,7 +215,7 @@ export class StatusBar extends Feature {
|
||||||
this.msgContainer = statusSpan;
|
this.msgContainer = statusSpan;
|
||||||
this.labelContainer = statusSpanText;
|
this.labelContainer = statusSpanText;
|
||||||
|
|
||||||
// Subscribe to events
|
// subscribe to events
|
||||||
emitter.on(['before-filtering'], () => this.message(this.msgFilter));
|
emitter.on(['before-filtering'], () => this.message(this.msgFilter));
|
||||||
emitter.on(['before-populating-filter'],
|
emitter.on(['before-populating-filter'],
|
||||||
() => this.message(this.msgPopulate));
|
() => this.message(this.msgPopulate));
|
||||||
|
@ -227,10 +236,10 @@ export class StatusBar extends Feature {
|
||||||
|
|
||||||
emitter.on(EVENTS, () => this.message(''));
|
emitter.on(EVENTS, () => this.message(''));
|
||||||
|
|
||||||
/**
|
/** @inherited */
|
||||||
* @inherited
|
|
||||||
*/
|
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
|
|
||||||
|
emitter.emit('feature-initialized', this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
import Cookie from '../cookie';
|
import Cookie from '../cookie';
|
||||||
import {root} from '../root';
|
import {root} from '../root';
|
||||||
|
|
||||||
|
|
224
src/modules/toolbar.js
Normal file
224
src/modules/toolbar.js
Normal file
|
@ -0,0 +1,224 @@
|
||||||
|
import {Feature} from '../feature';
|
||||||
|
import {createElm, removeElm, elm, tag} from '../dom';
|
||||||
|
import {defaultsStr} from '../settings';
|
||||||
|
import {isUndef} from '../types';
|
||||||
|
|
||||||
|
const EVENTS = [
|
||||||
|
'initializing-feature',
|
||||||
|
'initializing-extension'
|
||||||
|
];
|
||||||
|
|
||||||
|
/** Left position in toolbar */
|
||||||
|
export const LEFT = 'left';
|
||||||
|
/** Right position in toolbar */
|
||||||
|
export const RIGHT = 'right';
|
||||||
|
/** Center position in toolbar */
|
||||||
|
export const CENTER = 'center';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toolbar UI component
|
||||||
|
* @export
|
||||||
|
* @class Toolbar
|
||||||
|
* @extends {Feature}
|
||||||
|
*/
|
||||||
|
export class Toolbar extends Feature {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an instance of Toolbar
|
||||||
|
* @param {TableFilter} tf TableFilter instance
|
||||||
|
* @memberof Toolbar
|
||||||
|
*/
|
||||||
|
constructor(tf) {
|
||||||
|
super(tf, Toolbar);
|
||||||
|
|
||||||
|
// Configuration object
|
||||||
|
let f = this.config.toolbar || {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Css class for toolbar's container DOM element
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
this.contCssClass = defaultsStr(f.container_css_class, 'inf');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Css class for left-side inner container DOM element
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
this.lContCssClass = defaultsStr(f.left_cont_css_class, 'ldiv');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Css class for right-side inner container DOM element
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
this.rContCssClass = defaultsStr(f.right_cont_css_class, 'rdiv');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Css class for middle inner container DOM element
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
this.cContCssClass = defaultsStr(f.center_cont_css_class, 'mdiv');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toolbar's custom container ID
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
this.tgtId = defaultsStr(f.target_id, null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toolbar's container DOM element
|
||||||
|
* @type {DOMElement}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.cont = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Left-side inner container DOM element (rows counter in toolbar)
|
||||||
|
* @type {DOMElement}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.lCont = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Right-side inner container DOM element (reset button,
|
||||||
|
* page length selector in toolbar)
|
||||||
|
* @type {DOMElement}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.rCont = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Middle inner container DOM element (paging elements in toolbar)
|
||||||
|
* @type {DOMElement}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.cCont = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Container elements inside toolbar
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.innerCont = {
|
||||||
|
left: null,
|
||||||
|
center: null,
|
||||||
|
right: null
|
||||||
|
};
|
||||||
|
|
||||||
|
this.emitter.on(EVENTS,
|
||||||
|
(feature, isExternal) => this.init(isExternal));
|
||||||
|
|
||||||
|
/** @inherited */
|
||||||
|
this.enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize toolbar components
|
||||||
|
* @param {Boolean} isExternal initialize only if component belongs
|
||||||
|
* to toolbar
|
||||||
|
*/
|
||||||
|
init(isExternal) {
|
||||||
|
if (this.initialized || isExternal) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let tf = this.tf;
|
||||||
|
|
||||||
|
// default container
|
||||||
|
let container = createElm('div');
|
||||||
|
container.className = this.contCssClass;
|
||||||
|
|
||||||
|
// custom container
|
||||||
|
if (this.tgtId) {
|
||||||
|
elm(this.tgtId).appendChild(container);
|
||||||
|
}
|
||||||
|
// grid-layout
|
||||||
|
else if (tf.gridLayout) {
|
||||||
|
let gridLayout = tf.Mod.gridLayout;
|
||||||
|
gridLayout.tblMainCont.appendChild(container);
|
||||||
|
container.className = gridLayout.infDivCssClass;
|
||||||
|
}
|
||||||
|
// default location: just above the table
|
||||||
|
else {
|
||||||
|
let cont = createElm('caption');
|
||||||
|
cont.appendChild(container);
|
||||||
|
tf.dom().insertBefore(cont, tf.dom().firstChild);
|
||||||
|
}
|
||||||
|
this.cont = container;
|
||||||
|
|
||||||
|
// left container
|
||||||
|
this.lCont = this.createContainer(container, this.lContCssClass);
|
||||||
|
|
||||||
|
// right container
|
||||||
|
this.rCont = this.createContainer(container, this.rContCssClass);
|
||||||
|
|
||||||
|
// middle container
|
||||||
|
this.cCont = this.createContainer(container, this.cContCssClass);
|
||||||
|
|
||||||
|
this.innerCont = {
|
||||||
|
left: this.lCont,
|
||||||
|
center: this.cCont,
|
||||||
|
right: this.rCont
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @inherited */
|
||||||
|
this.initialized = true;
|
||||||
|
|
||||||
|
// emit help initialisation only if undefined
|
||||||
|
if (isUndef(tf.help)) {
|
||||||
|
// explicitily enable help to initialise feature by
|
||||||
|
// default, only if setting is undefined
|
||||||
|
tf.Mod.help.enable();
|
||||||
|
this.emitter.emit('init-help', tf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the container based on requested position inside the toolbar
|
||||||
|
* @param {String} [position=RIGHT] 3 possible positions: 'left', 'center',
|
||||||
|
* 'right'
|
||||||
|
* @param {DOMElement} el optional DOM element to be inserter in container
|
||||||
|
* @returns {DOMElement}
|
||||||
|
*/
|
||||||
|
container(position = RIGHT, el) {
|
||||||
|
let cont = this.innerCont[position];
|
||||||
|
if (el) {
|
||||||
|
cont.appendChild(el);
|
||||||
|
}
|
||||||
|
return cont;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create DOM element inside passed container
|
||||||
|
* @param {DOMElement} container
|
||||||
|
* @param {String} css
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
createContainer(container, css) {
|
||||||
|
let div = createElm('div', ['class', css]);
|
||||||
|
container.appendChild(div);
|
||||||
|
return div;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy Toolbar instance
|
||||||
|
*/
|
||||||
|
destroy() {
|
||||||
|
if (!this.initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let tf = this.tf;
|
||||||
|
|
||||||
|
removeElm(this.cont);
|
||||||
|
this.cont = null;
|
||||||
|
|
||||||
|
let tbl = tf.dom();
|
||||||
|
let captions = tag(tbl, 'caption');
|
||||||
|
[].forEach.call(captions, (el) => removeElm(el));
|
||||||
|
|
||||||
|
/** @inherited */
|
||||||
|
this.initialized = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: remove as soon as feature name is fixed
|
||||||
|
Toolbar.meta = {alwaysInstantiate: true};
|
|
@ -19,11 +19,14 @@ export const parse = (value, decimal = '.') => {
|
||||||
let regex = new RegExp('[^0-9-' + decimal + ']', ['g']);
|
let regex = new RegExp('[^0-9-' + decimal + ']', ['g']);
|
||||||
let unformatted = parseFloat(
|
let unformatted = parseFloat(
|
||||||
('' + value)
|
('' + value)
|
||||||
.replace(/\((.*)\)/, '-$1') // replace bracketed values with negatives
|
// replace bracketed values with negatives
|
||||||
.replace(regex, '') // strip out any cruft
|
.replace(/\((.*)\)/, '-$1')
|
||||||
.replace(decimal, '.') // make sure decimal point is standard
|
// strip out any cruft
|
||||||
|
.replace(regex, '')
|
||||||
|
// make sure decimal point is standard
|
||||||
|
.replace(decimal, '.')
|
||||||
);
|
);
|
||||||
|
|
||||||
// This will fail silently
|
// This will fail silently
|
||||||
return !isNaN(unformatted) ? unformatted : 0;
|
return !isNaN(unformatted) ? unformatted : 0;
|
||||||
}
|
};
|
||||||
|
|
53
src/settings.js
Normal file
53
src/settings.js
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
import {isBoolean, isString, isFn, isArray} from './types';
|
||||||
|
|
||||||
|
/** Configuration settings helpers */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If passed value is not of boolean type return the default value
|
||||||
|
* otherwise return the value itself
|
||||||
|
* @param {Boolean|Any} value
|
||||||
|
* @param {Boolean} default value
|
||||||
|
* @return {Boolean|Any}
|
||||||
|
*/
|
||||||
|
export const defaultsBool =
|
||||||
|
(val, defaultVal) => isBoolean(val) ? val : defaultVal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If passed value is not of string type return the default value
|
||||||
|
* otherwise return the value itself
|
||||||
|
* @param {String|Any} value
|
||||||
|
* @param {String} default value
|
||||||
|
* @return {String|Any}
|
||||||
|
*/
|
||||||
|
export const defaultsStr =
|
||||||
|
(val, defaultVal) => isString(val) ? val : defaultVal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If passed value is not of number type return the default value
|
||||||
|
* otherwise return the value itself
|
||||||
|
* @param {Number|Any} value
|
||||||
|
* @param {Number} default value
|
||||||
|
* @return {Number|Any}
|
||||||
|
*/
|
||||||
|
export const defaultsNb =
|
||||||
|
(val, defaultVal) => isNaN(val) ? defaultVal : val;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If passed value is not of array type return the default value
|
||||||
|
* otherwise return the value itself
|
||||||
|
* @param {Array|Any} value
|
||||||
|
* @param {Array} default value
|
||||||
|
* @return {Array|Any}
|
||||||
|
*/
|
||||||
|
export const defaultsArr =
|
||||||
|
(val, defaultVal) => isArray(val) ? val : defaultVal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If passed value is not of function type return the default value
|
||||||
|
* otherwise return the value itself
|
||||||
|
* @param {Function|Any} value
|
||||||
|
* @param {Function} default value
|
||||||
|
* @return {Function|Any}
|
||||||
|
*/
|
||||||
|
export const defaultsFn =
|
||||||
|
(val, defaultVal) => isFn(val) ? val : defaultVal;
|
67
src/sort.js
67
src/sort.js
|
@ -1,6 +1,7 @@
|
||||||
/**
|
import {parse as parseNb} from './number';
|
||||||
* Sorting utilities
|
import {Date as SugarDate} from 'sugar-date';
|
||||||
*/
|
|
||||||
|
/** Sorting utilities */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Case insensitive compare function for passed strings
|
* Case insensitive compare function for passed strings
|
||||||
|
@ -13,21 +14,69 @@
|
||||||
export const ignoreCase = (a, b) => {
|
export const ignoreCase = (a, b) => {
|
||||||
let x = a.toLowerCase();
|
let x = a.toLowerCase();
|
||||||
let y = b.toLowerCase();
|
let y = b.toLowerCase();
|
||||||
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
|
return x < y ? -1 : (x > y ? 1 : 0);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sorts passed numbers in a ascending manner
|
* Compare function for sorting passed numbers in ascending manner
|
||||||
* @param {Number} First number
|
* @param {Number} First number
|
||||||
* @param {Number} Second number
|
* @param {Number} Second number
|
||||||
* @param {Number} Negative, zero or positive number
|
* @return {Number} Negative, zero or positive number
|
||||||
*/
|
*/
|
||||||
export const numSortAsc = (a, b) => (a - b);
|
export const numSortAsc = (a, b) => (a - b);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sorts passed numbers in a descending manner
|
* Compare function for sorting passed numbers in descending manner
|
||||||
* @param {Number} First number
|
* @param {Number} First number
|
||||||
* @param {Number} Second number
|
* @param {Number} Second number
|
||||||
* @param {Number} Negative, zero or positive number
|
* @return {Number} Negative, zero or positive number
|
||||||
*/
|
*/
|
||||||
export const numSortDesc = (a, b) => (b - a);
|
export const numSortDesc = (a, b) => (b - a);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare function for sorting passed dates in ascending manner according to
|
||||||
|
* the corresponding UTC numeric value (returned by getTime)
|
||||||
|
* @param {Date} First date object
|
||||||
|
* @param {Date} Second date object
|
||||||
|
* @return {Number} Negative, zero or positive number
|
||||||
|
*/
|
||||||
|
export const dateSortAsc = (date1, date2) => date1.getTime() - date2.getTime();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare function for sorting passed dates in descending manner according to
|
||||||
|
* the corresponding UTC numeric value (returned by getTime)
|
||||||
|
* @param {Date} First date object
|
||||||
|
* @param {Date} Second date object
|
||||||
|
* @return {Number} Negative, zero or positive number
|
||||||
|
*/
|
||||||
|
export const dateSortDesc = (date1, date2) => date2.getTime() - date1.getTime();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Curried compare function for sorting passed formatted numbers in desired
|
||||||
|
* fashion according to supplied compare function and decimal separator
|
||||||
|
* @param {Function} Compare function
|
||||||
|
* @param {String} [decimal=','] Decimal separator
|
||||||
|
* @return {Function} Compare function receiving parsed numeric arguments
|
||||||
|
*/
|
||||||
|
export const sortNumberStr = (compareFn, decimal = ',') => {
|
||||||
|
return (numStr1, numStr2) => {
|
||||||
|
let num1 = parseNb(numStr1, decimal);
|
||||||
|
let num2 = parseNb(numStr2, decimal);
|
||||||
|
return compareFn(num1, num2);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Curried compare function for sorting passed formatted dates in desired
|
||||||
|
* fashion according to supplied compare function and locale
|
||||||
|
* @param {Function} Compare function
|
||||||
|
* @param {String} [locale='en-us'] Locale code
|
||||||
|
* @return {Function} Compare function receiving parsed date arguments
|
||||||
|
*/
|
||||||
|
export const sortDateStr = (compareFn, locale = 'en-us') => {
|
||||||
|
return (dateStr1, dateStr2) => {
|
||||||
|
let date1 = SugarDate.create(dateStr1, locale);
|
||||||
|
let date2 = SugarDate.create(dateStr2, locale);
|
||||||
|
return compareFn(date1, date2);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -14,7 +14,7 @@ export const trim = (text) => {
|
||||||
return text.trim();
|
return text.trim();
|
||||||
}
|
}
|
||||||
return text.replace(/^\s*|\s*$/g, '');
|
return text.replace(/^\s*|\s*$/g, '');
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if passed string is empty
|
* Checks if passed string is empty
|
||||||
|
@ -32,7 +32,7 @@ export const rgxEsc = (text) => {
|
||||||
let chars = /[-\/\\^$*+?.()|[\]{}]/g;
|
let chars = /[-\/\\^$*+?.()|[\]{}]/g;
|
||||||
let escMatch = '\\$&';
|
let escMatch = '\\$&';
|
||||||
return String(text).replace(chars, escMatch);
|
return String(text).replace(chars, escMatch);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns passed string as lowercase if caseSensitive flag set false. By
|
* Returns passed string as lowercase if caseSensitive flag set false. By
|
||||||
|
@ -45,7 +45,7 @@ export const matchCase = (text, caseSensitive = false) => {
|
||||||
return text.toLowerCase();
|
return text.toLowerCase();
|
||||||
}
|
}
|
||||||
return text;
|
return text;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if passed data contains the searched term
|
* Checks if passed data contains the searched term
|
||||||
|
@ -73,4 +73,40 @@ export const contains = (term, data, exactMatch = false, caseSensitive = false,
|
||||||
regexp = new RegExp(rgxEsc(term), modifier);
|
regexp = new RegExp(rgxEsc(term), modifier);
|
||||||
}
|
}
|
||||||
return regexp.test(data);
|
return regexp.test(data);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Camelize a string, cutting the string by multiple separators like
|
||||||
|
* hyphens, underscores and spaces.
|
||||||
|
* @param {String} text text to camelize
|
||||||
|
* @return {String} camelized text
|
||||||
|
*/
|
||||||
|
export const toCamelCase = (text = '') => {
|
||||||
|
return text.replace(/^([A-Z])|[\s-_]+(\w)/g, (match, p1, p2) => {
|
||||||
|
if (p2) {
|
||||||
|
return p2.toUpperCase();
|
||||||
|
}
|
||||||
|
return p1.toLowerCase();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a string in the format of a UUID (Universally Unique IDentifier).
|
||||||
|
* NOTE: This format of 8 chars, followed by 3 groups of 4 chars, followed by 12
|
||||||
|
* chars is known as a UUID and is defined in RFC4122 and is a standard for
|
||||||
|
* generating unique IDs. This function DOES NOT implement this standard.
|
||||||
|
* It simply outputs a string that looks similar. The standard is found here:
|
||||||
|
* https://www.ietf.org/rfc/rfc4122.txt
|
||||||
|
* source: https://gist.github.com/gordonbrander/2230317
|
||||||
|
* @return {String}
|
||||||
|
*/
|
||||||
|
export const uuid = () => {
|
||||||
|
const chr4 = () => Math.random().toString(16).slice(-4);
|
||||||
|
|
||||||
|
return chr4() + chr4()
|
||||||
|
+ '-' + chr4()
|
||||||
|
+ '-' + chr4()
|
||||||
|
+ '-' + chr4()
|
||||||
|
+ '-' + chr4()
|
||||||
|
+ chr4() + chr4();
|
||||||
|
};
|
||||||
|
|
1682
src/tablefilter.js
1682
src/tablefilter.js
File diff suppressed because it is too large
Load diff
10
src/types.js
10
src/types.js
|
@ -37,7 +37,7 @@ export const isArray =
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check passed argument is a string
|
* Check passed argument is a string
|
||||||
* @param {String} obj objue
|
* @param {String} obj obj
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
export const isString =
|
export const isString =
|
||||||
|
@ -51,6 +51,14 @@ export const isString =
|
||||||
export const isNumber =
|
export const isNumber =
|
||||||
(obj) => Object.prototype.toString.call(obj) === '[object Number]';
|
(obj) => Object.prototype.toString.call(obj) === '[object Number]';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check passed argument is a boolean
|
||||||
|
* @param {Boolean} obj
|
||||||
|
* @returns {Boolean}
|
||||||
|
*/
|
||||||
|
export const isBoolean =
|
||||||
|
(obj) => Object.prototype.toString.call(obj) === '[object Boolean]';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check passed argument is undefined
|
* Check passed argument is undefined
|
||||||
* @param {Any} obj
|
* @param {Any} obj
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -5,3 +5,6 @@
|
||||||
.activeHeader
|
.activeHeader
|
||||||
background-color #66AFE9 !important
|
background-color #66AFE9 !important
|
||||||
color #fff !important
|
color #fff !important
|
||||||
|
|
||||||
|
.activeCell
|
||||||
|
background-color rgba(0,0,0,0.075)
|
||||||
|
|
|
@ -34,7 +34,7 @@ div.colVisCont
|
||||||
z-index 10000
|
z-index 10000
|
||||||
padding 10px 10px 10px 10px
|
padding 10px 10px 10px 10px
|
||||||
text-align left
|
text-align left
|
||||||
font-size 12px
|
font-size inherit
|
||||||
|
|
||||||
p
|
p
|
||||||
margin 6px auto 6px auto
|
margin 6px auto 6px auto
|
||||||
|
@ -47,7 +47,7 @@ div.colVisCont
|
||||||
ul.cols_checklist
|
ul.cols_checklist
|
||||||
padding 0
|
padding 0
|
||||||
margin 0
|
margin 0
|
||||||
list-style none
|
list-style-type none
|
||||||
|
|
||||||
label
|
label
|
||||||
display block
|
display block
|
||||||
|
|
|
@ -11,7 +11,7 @@ $item-font-color = #fff
|
||||||
.div_checklist
|
.div_checklist
|
||||||
width 100%
|
width 100%
|
||||||
height 90px
|
height 90px
|
||||||
line-height 24px
|
line-height 30px
|
||||||
border 1px solid $filter-border-color
|
border 1px solid $filter-border-color
|
||||||
overflow auto
|
overflow auto
|
||||||
text-align left
|
text-align left
|
||||||
|
@ -27,19 +27,20 @@ $item-font-color = #fff
|
||||||
li.flt_checklist_item
|
li.flt_checklist_item
|
||||||
padding 1px !important
|
padding 1px !important
|
||||||
margin 0 !important
|
margin 0 !important
|
||||||
font-size 10px !important
|
font-size inherit
|
||||||
border-bottom 1px solid $filter-border-color !important
|
border-bottom 1px solid $filter-border-color !important
|
||||||
|
|
||||||
&:hover
|
&:hover
|
||||||
background-color $item-bg-color !important
|
background-color $item-bg-color !important
|
||||||
color $item-font-color !important;
|
color $item-font-color !important
|
||||||
|
|
||||||
label
|
label
|
||||||
display block !important;
|
display block !important
|
||||||
|
font-weight inherit !important
|
||||||
|
|
||||||
input
|
input
|
||||||
vertical-align middle !important;
|
vertical-align middle !important
|
||||||
margin 2px 5px 2px 1px !important;
|
margin 2px 5px 3px 1px !important
|
||||||
|
|
||||||
// disabled checklist item
|
// disabled checklist item
|
||||||
.flt_checklist_item_disabled
|
.flt_checklist_item_disabled
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
// input and select filter type
|
// input and select filter type
|
||||||
.flt
|
.flt
|
||||||
font-family inherit
|
font-family inherit
|
||||||
|
font-size inherit
|
||||||
display block
|
display block
|
||||||
color $filter-font-color
|
color $filter-font-color
|
||||||
background-color $filter-bg-color
|
background-color $filter-bg-color
|
||||||
|
@ -64,6 +65,7 @@
|
||||||
// multiple select type filter
|
// multiple select type filter
|
||||||
select.flt_multi
|
select.flt_multi
|
||||||
font-family inherit
|
font-family inherit
|
||||||
|
font-size inherit
|
||||||
color $filter-font-color
|
color $filter-font-color
|
||||||
background-color $filter-bg-color
|
background-color $filter-bg-color
|
||||||
border 1px solid $filter-border-color
|
border 1px solid $filter-border-color
|
||||||
|
@ -92,7 +94,7 @@ select.flt_multi
|
||||||
box-sizing initial
|
box-sizing initial
|
||||||
display initial
|
display initial
|
||||||
|
|
||||||
// Pop-up filters elements
|
// pop-up filters elements
|
||||||
div.popUpFilter
|
div.popUpFilter
|
||||||
arrow(top, 10px white, 2px $th-bg-color)
|
arrow(top, 10px white, 2px $th-bg-color)
|
||||||
box-shadow(3px 3px 2px #888)
|
box-shadow(3px 3px 2px #888)
|
||||||
|
@ -103,3 +105,7 @@ div.popUpFilter
|
||||||
background-color $th-bg-color
|
background-color $th-bg-color
|
||||||
border 1px solid $filter-row-bg-color
|
border 1px solid $filter-row-bg-color
|
||||||
padding 0
|
padding 0
|
||||||
|
|
||||||
|
// pop-up container
|
||||||
|
.popUpPlaceholder
|
||||||
|
position relative
|
||||||
|
|
|
@ -11,7 +11,6 @@ div.grd_Cont
|
||||||
width 800px
|
width 800px
|
||||||
height auto
|
height auto
|
||||||
overflow hidden
|
overflow hidden
|
||||||
padding 3px 3px 3px 3px
|
|
||||||
background-color $grid-layout-bg-color
|
background-color $grid-layout-bg-color
|
||||||
border 1px solid $grid-layout-border-color
|
border 1px solid $grid-layout-border-color
|
||||||
|
|
||||||
|
@ -50,8 +49,9 @@ div.grd_tblCont
|
||||||
|
|
||||||
// headers' table container
|
// headers' table container
|
||||||
div.grd_headTblCont
|
div.grd_headTblCont
|
||||||
|
display block
|
||||||
|
margin-right 20px
|
||||||
height auto
|
height auto
|
||||||
width 800px
|
|
||||||
overflow hidden
|
overflow hidden
|
||||||
border-bottom 1px solid $grid-layout-border-color
|
border-bottom 1px solid $grid-layout-border-color
|
||||||
background-color $grid-layout-bg-color
|
background-color $grid-layout-bg-color
|
||||||
|
@ -63,10 +63,6 @@ div.grd_headTblCont table
|
||||||
table-layout fixed
|
table-layout fixed
|
||||||
box-sizing initial
|
box-sizing initial
|
||||||
|
|
||||||
div.grd_tblCont table
|
|
||||||
border-right 1px solid $grid-layout-border-color
|
|
||||||
box-sizing initial
|
|
||||||
|
|
||||||
// headers
|
// headers
|
||||||
div.grd_tblCont table th
|
div.grd_tblCont table th
|
||||||
div.grd_headTblCont table th
|
div.grd_headTblCont table th
|
||||||
|
|
|
@ -32,6 +32,7 @@ div.helpCont
|
||||||
color #333
|
color #333
|
||||||
background #fff
|
background #fff
|
||||||
text-align left
|
text-align left
|
||||||
|
z-index 1000
|
||||||
|
|
||||||
a
|
a
|
||||||
color #cc0000
|
color #cc0000
|
||||||
|
|
7
static/style/mixins/empty-content.styl
Normal file
7
static/style/mixins/empty-content.styl
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
/**
|
||||||
|
* Empty content mixin
|
||||||
|
*/
|
||||||
|
|
||||||
|
empty-content()
|
||||||
|
&:empty:after
|
||||||
|
content "\00A0"
|
|
@ -14,3 +14,8 @@ input.reset
|
||||||
|
|
||||||
&:hover
|
&:hover
|
||||||
background-color $toolbar-hover-color
|
background-color $toolbar-hover-color
|
||||||
|
|
||||||
|
a.reset
|
||||||
|
font-weight normal !important
|
||||||
|
line-height $min-height
|
||||||
|
padding 5px 5px
|
||||||
|
|
|
@ -26,11 +26,19 @@ table.TF
|
||||||
margin 0
|
margin 0
|
||||||
padding $padding
|
padding $padding
|
||||||
border-bottom 1px solid $td-border-color
|
border-bottom 1px solid $td-border-color
|
||||||
|
text-overflow ellipsis
|
||||||
|
|
||||||
// responsiveness
|
// responsive
|
||||||
&.resp
|
&.resp
|
||||||
display block
|
display block
|
||||||
overflow-x auto
|
overflow-x auto
|
||||||
|
overflow-y hidden
|
||||||
|
|
||||||
.sort-arrow
|
.sort-arrow
|
||||||
position initial
|
position initial
|
||||||
|
|
||||||
|
// stick headers
|
||||||
|
&.sticky
|
||||||
|
th
|
||||||
|
position sticky
|
||||||
|
top -1px
|
||||||
|
|
18
static/style/tablefilter.styl
Normal file
18
static/style/tablefilter.styl
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
/** Main stylesheet */
|
||||||
|
@import 'active-header'
|
||||||
|
@import 'alternating-rows'
|
||||||
|
@import 'ezedittable'
|
||||||
|
@import 'filter-checklist'
|
||||||
|
@import 'filters'
|
||||||
|
@import 'grid-layout'
|
||||||
|
@import 'help'
|
||||||
|
@import 'keyword'
|
||||||
|
@import 'loader'
|
||||||
|
@import 'noresults'
|
||||||
|
@import 'paging'
|
||||||
|
@import 'reset-button'
|
||||||
|
@import 'rows-counter'
|
||||||
|
@import 'sort'
|
||||||
|
@import 'status-bar'
|
||||||
|
@import 'table'
|
||||||
|
@import 'toolbar'
|
|
@ -3,12 +3,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@import 'config'
|
@import 'config'
|
||||||
|
@import 'mixins/empty-content'
|
||||||
|
|
||||||
// left, middle and right divs container (toolbar)
|
// left, middle and right divs container (toolbar)
|
||||||
.inf
|
.inf
|
||||||
clear both
|
clear both
|
||||||
width auto
|
width auto
|
||||||
height $min-height
|
height $min-height
|
||||||
|
min-width 400px
|
||||||
background-color $toolbar-bg-color
|
background-color $toolbar-bg-color
|
||||||
font-size $toolbar-font-size
|
font-size $toolbar-font-size
|
||||||
margin 0
|
margin 0
|
||||||
|
@ -32,25 +34,25 @@
|
||||||
|
|
||||||
// left div
|
// left div
|
||||||
.ldiv
|
.ldiv
|
||||||
|
empty-content()
|
||||||
float left
|
float left
|
||||||
width 30%
|
width 30%
|
||||||
// height 100%
|
|
||||||
position inherit
|
position inherit
|
||||||
text-align left
|
text-align left
|
||||||
|
|
||||||
// middle div
|
// middle div
|
||||||
.mdiv
|
.mdiv
|
||||||
|
empty-content()
|
||||||
float left
|
float left
|
||||||
width 38%
|
width 38%
|
||||||
// height 100%
|
|
||||||
position inherit
|
position inherit
|
||||||
text-align center
|
text-align center
|
||||||
padding 0
|
padding 0
|
||||||
|
|
||||||
// right div
|
// right div
|
||||||
.rdiv
|
.rdiv
|
||||||
|
empty-content()
|
||||||
float right
|
float right
|
||||||
width 30%
|
width 30%
|
||||||
// height 100%
|
|
||||||
position inherit
|
position inherit
|
||||||
text-align right
|
text-align right
|
||||||
|
|
|
@ -49,8 +49,9 @@
|
||||||
<script data-config>
|
<script data-config>
|
||||||
var filtersConfig = {
|
var filtersConfig = {
|
||||||
base_path: '../dist/tablefilter/',
|
base_path: '../dist/tablefilter/',
|
||||||
grid_layout: true,
|
grid_layout: {
|
||||||
grid_width: '900px',
|
width: '900px'
|
||||||
|
},
|
||||||
alternate_rows: true,
|
alternate_rows: true,
|
||||||
btn_reset: true,
|
btn_reset: true,
|
||||||
rows_counter: true,
|
rows_counter: true,
|
||||||
|
|
|
@ -19,15 +19,18 @@
|
||||||
<script data-config>
|
<script data-config>
|
||||||
var filtersConfig = {
|
var filtersConfig = {
|
||||||
base_path: '../dist/tablefilter/',
|
base_path: '../dist/tablefilter/',
|
||||||
auto_filter: true,
|
auto_filter: {
|
||||||
auto_filter_delay: 750, //milliseconds
|
delay: 750 // milliseconds
|
||||||
|
},
|
||||||
filters_row_index: 1,
|
filters_row_index: 1,
|
||||||
state: true,
|
state: true,
|
||||||
alternate_rows: true,
|
alternate_rows: true,
|
||||||
rows_counter: true,
|
rows_counter: {
|
||||||
rows_counter_text: 'Rows: ',
|
text: 'Rows: '
|
||||||
|
},
|
||||||
btn_reset: true,
|
btn_reset: true,
|
||||||
status_bar: true,
|
status_bar: true,
|
||||||
|
sticky_headers: true,
|
||||||
msg_filter: 'Filtering...'
|
msg_filter: 'Filtering...'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -39,8 +39,9 @@ var tfConfig = {
|
||||||
},
|
},
|
||||||
alternate_rows: true,
|
alternate_rows: true,
|
||||||
rows_counter: true,
|
rows_counter: true,
|
||||||
btn_reset: true,
|
btn_reset: {
|
||||||
btn_reset_text: 'Clear',
|
text: 'Clear'
|
||||||
|
},
|
||||||
status_bar: true,
|
status_bar: true,
|
||||||
col_1: 'select',
|
col_1: 'select',
|
||||||
col_2: 'select',
|
col_2: 'select',
|
||||||
|
|
|
@ -32,40 +32,6 @@ var id = function (id){
|
||||||
var table = id('demo-tot');
|
var table = id('demo-tot');
|
||||||
var totRowIndex = table.getElementsByTagName('tr').length;
|
var totRowIndex = table.getElementsByTagName('tr').length;
|
||||||
|
|
||||||
function addCommas(nStr){
|
|
||||||
nStr += '';
|
|
||||||
var x = nStr.split('.');
|
|
||||||
var x1 = x[0];
|
|
||||||
var x2 = x.length > 1 ? '.' + x[1] : '';
|
|
||||||
var rgx = /(\d+)(\d{3})/;
|
|
||||||
while (rgx.test(x1)) {
|
|
||||||
x1 = x1.replace(rgx, '$1' + ',' + '$2');
|
|
||||||
}
|
|
||||||
return x1 + x2;
|
|
||||||
}
|
|
||||||
|
|
||||||
function addDots(nStr){
|
|
||||||
nStr += '';
|
|
||||||
var x = nStr.split('.');
|
|
||||||
var x1 = x[0];
|
|
||||||
var x2 = x.length > 1 ? ',' + x[1] : '';
|
|
||||||
var rgx = /(\d+)(\d{3})/;
|
|
||||||
while (rgx.test(x1)) {
|
|
||||||
x1 = x1.replace(rgx, '$1' + '.' + '$2');
|
|
||||||
}
|
|
||||||
return x1 + x2;
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatTotals(){
|
|
||||||
var tot1 = id('sum1').innerHTML;
|
|
||||||
tot1 = addDots(tot1);
|
|
||||||
id('sum1').innerHTML = tot1;
|
|
||||||
|
|
||||||
var tot2 = id('sum2').innerHTML;
|
|
||||||
tot2 = addCommas(tot2);
|
|
||||||
id('sum2').innerHTML = tot2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EXAMPLE 1
|
/* EXAMPLE 1
|
||||||
*********************** */
|
*********************** */
|
||||||
var tfConfig = {
|
var tfConfig = {
|
||||||
|
@ -107,7 +73,10 @@ var tfConfig = {
|
||||||
exclude_row: [totRowIndex],
|
exclude_row: [totRowIndex],
|
||||||
decimal_precision: [2, 2],
|
decimal_precision: [2, 2],
|
||||||
tot_row_index: [totRowIndex],
|
tot_row_index: [totRowIndex],
|
||||||
on_after_operation: formatTotals
|
format_result: [
|
||||||
|
{ prefix: '€ ' },
|
||||||
|
{ prefix: '$ ' }
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,9 +23,10 @@
|
||||||
btn_reset: true,
|
btn_reset: true,
|
||||||
loader: true,
|
loader: true,
|
||||||
status_bar: true,
|
status_bar: true,
|
||||||
mark_active_columns: true,
|
mark_active_columns: {
|
||||||
|
highlight_column: true
|
||||||
|
},
|
||||||
no_results_message: true,
|
no_results_message: true,
|
||||||
responsive: true,
|
|
||||||
custom_options: {
|
custom_options: {
|
||||||
cols:[3],
|
cols:[3],
|
||||||
texts: [
|
texts: [
|
||||||
|
@ -46,8 +47,8 @@
|
||||||
},
|
},
|
||||||
col_widths: [
|
col_widths: [
|
||||||
'150px', '100px', '100px',
|
'150px', '100px', '100px',
|
||||||
'70px', '70px', '70px',
|
'90px', '90px', '90px',
|
||||||
'70px', '60px', '60px'
|
'90px', '70px', '70px'
|
||||||
],
|
],
|
||||||
extensions:[{ name: 'sort' }]
|
extensions:[{ name: 'sort' }]
|
||||||
};
|
};
|
||||||
|
|
|
@ -82,8 +82,9 @@
|
||||||
var tfConfig = {
|
var tfConfig = {
|
||||||
base_path: '../dist/tablefilter/',
|
base_path: '../dist/tablefilter/',
|
||||||
alternate_rows: true,
|
alternate_rows: true,
|
||||||
rows_counter: true,
|
rows_counter: {
|
||||||
rows_counter_text: "Displayed rows: ",
|
text: 'Displayed rows: '
|
||||||
|
},
|
||||||
loader: true,
|
loader: true,
|
||||||
status: true,
|
status: true,
|
||||||
status_bar: true,
|
status_bar: true,
|
||||||
|
@ -105,8 +106,7 @@ var tfConfig = {
|
||||||
col_8: "none",
|
col_8: "none",
|
||||||
|
|
||||||
/* external filters */
|
/* external filters */
|
||||||
external_flt_grid: true,
|
external_flt_ids: [
|
||||||
external_flt_grid_ids: [
|
|
||||||
'slcCountry',
|
'slcCountry',
|
||||||
'slcCode',
|
'slcCode',
|
||||||
'slcYear',
|
'slcYear',
|
||||||
|
|
|
@ -26,8 +26,9 @@ var tfConfig = {
|
||||||
'string', 'string', 'string',
|
'string', 'string', 'string',
|
||||||
'number', 'string', 'string', 'date'
|
'number', 'string', 'string', 'date'
|
||||||
],
|
],
|
||||||
rows_counter: true,
|
rows_counter: {
|
||||||
rows_counter_text: 'Books: ',
|
text: 'Books: '
|
||||||
|
},
|
||||||
alternate_rows: true,
|
alternate_rows: true,
|
||||||
btn_reset: true,
|
btn_reset: true,
|
||||||
|
|
||||||
|
@ -36,10 +37,10 @@ var tfConfig = {
|
||||||
col_4: 'select',
|
col_4: 'select',
|
||||||
col_5: 'select',
|
col_5: 'select',
|
||||||
|
|
||||||
/* custom_cell_data delegate used for filtering
|
/* cell parser for filtering images in a column */
|
||||||
images in a column */
|
cell_parser: {
|
||||||
custom_cell_data_cols: [0, 4],
|
cols: [0, 4],
|
||||||
custom_cell_data: function(o, cell, colIndex){
|
parse: function(o, cell, colIndex){
|
||||||
if(colIndex === 0){
|
if(colIndex === 0){
|
||||||
var img = cell.getElementsByTagName('img')[0];
|
var img = cell.getElementsByTagName('img')[0];
|
||||||
if(!img){
|
if(!img){
|
||||||
|
@ -54,6 +55,7 @@ var tfConfig = {
|
||||||
return 'no';
|
return 'no';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/* Custom options for 'Shipping' column */
|
/* Custom options for 'Shipping' column */
|
||||||
|
|
|
@ -22,7 +22,7 @@ var tfConfig = {
|
||||||
col_2: 'checklist',
|
col_2: 'checklist',
|
||||||
col_widths: [
|
col_widths: [
|
||||||
'75px', '200px', '200px',
|
'75px', '200px', '200px',
|
||||||
'100px', '75px', ''
|
'100px', '75px', '400px'
|
||||||
],
|
],
|
||||||
paging: true,
|
paging: true,
|
||||||
alternate_rows: true,
|
alternate_rows: true,
|
||||||
|
|
|
@ -22,6 +22,9 @@
|
||||||
loader: true,
|
loader: true,
|
||||||
status_bar: true,
|
status_bar: true,
|
||||||
no_results_message: true,
|
no_results_message: true,
|
||||||
|
mark_active_columns: {
|
||||||
|
highlight_column: true
|
||||||
|
},
|
||||||
col_1: 'select',
|
col_1: 'select',
|
||||||
col_2: 'select',
|
col_2: 'select',
|
||||||
col_widths: [
|
col_widths: [
|
||||||
|
|
|
@ -58,8 +58,9 @@ var tfConfig = {
|
||||||
rows_counter: true,
|
rows_counter: true,
|
||||||
btn_reset: true,
|
btn_reset: true,
|
||||||
status_bar: true,
|
status_bar: true,
|
||||||
paging: true,
|
paging: {
|
||||||
paging_length: 15,
|
length: 15
|
||||||
|
},
|
||||||
enable_empty_option: true,
|
enable_empty_option: true,
|
||||||
enable_non_empty_option: true,
|
enable_non_empty_option: true,
|
||||||
enable_default_theme: true,
|
enable_default_theme: true,
|
||||||
|
|
|
@ -20,14 +20,15 @@ var tfConfig = {
|
||||||
base_path: '../dist/tablefilter/',
|
base_path: '../dist/tablefilter/',
|
||||||
col_widths: [
|
col_widths: [
|
||||||
'150px', '100px', '100px',
|
'150px', '100px', '100px',
|
||||||
'70px', '70px', '70px',
|
'100px', '100px', '100px',
|
||||||
'70px', '60px', '60px'
|
'90px', '90px', '90px'
|
||||||
],
|
],
|
||||||
alternate_rows: true,
|
alternate_rows: true,
|
||||||
rows_counter: true,
|
rows_counter: true,
|
||||||
btn_reset: true,
|
btn_reset: true,
|
||||||
status_bar: true,
|
status_bar: true,
|
||||||
load_filters_on_demand: true,
|
load_filters_on_demand: true,
|
||||||
|
sticky_headers: true,
|
||||||
col_0: 'multiple',
|
col_0: 'multiple',
|
||||||
col_1: 'select',
|
col_1: 'select',
|
||||||
col_2: 'checklist'
|
col_2: 'checklist'
|
||||||
|
|
|
@ -30,8 +30,9 @@
|
||||||
<script data-config>
|
<script data-config>
|
||||||
var filtersConfig = {
|
var filtersConfig = {
|
||||||
base_path: '../dist/tablefilter/',
|
base_path: '../dist/tablefilter/',
|
||||||
paging: true,
|
paging: {
|
||||||
results_per_page: ['Records: ', [10,25,50,100]],
|
results_per_page: ['Records: ', [10, 25, 50, 100]]
|
||||||
|
},
|
||||||
state: {
|
state: {
|
||||||
types: ['local_storage'],
|
types: ['local_storage'],
|
||||||
filters: true,
|
filters: true,
|
||||||
|
@ -39,15 +40,21 @@
|
||||||
page_length: true,
|
page_length: true,
|
||||||
sort: true
|
sort: true
|
||||||
},
|
},
|
||||||
|
responsive: true,
|
||||||
|
help_instructions: {
|
||||||
|
container_adjust_left_position: 30
|
||||||
|
},
|
||||||
alternate_rows: true,
|
alternate_rows: true,
|
||||||
btn_reset: true,
|
btn_reset: true,
|
||||||
rows_counter: true,
|
rows_counter: true,
|
||||||
loader: true,
|
loader: {
|
||||||
loader_html: '<div id="lblMsg"></div>',
|
html: '<div id="lblMsg"></div>',
|
||||||
loader_css_class: 'myLoader',
|
css_class: 'myLoader'
|
||||||
status_bar: true,
|
},
|
||||||
status_bar_target_id: 'lblMsg',
|
status_bar: {
|
||||||
status_bar_css_class: 'myStatus',
|
target_id: 'lblMsg',
|
||||||
|
css_class: 'myStatus'
|
||||||
|
},
|
||||||
no_results_message: true,
|
no_results_message: true,
|
||||||
col_0: 'select',
|
col_0: 'select',
|
||||||
col_1: 'select',
|
col_1: 'select',
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<title>{NAME} v{VERSION} - Development workflow with RequireJs</title>
|
|
||||||
<!-- @import partials/style.html -->
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>{NAME} v{VERSION}</h1>
|
|
||||||
<h2>Development workflow with RequireJs</h2>
|
|
||||||
<p>
|
|
||||||
To take advantage of the RequireJs development workflow use the
|
|
||||||
<code>grunt dev-modules</code> command.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
If you use extensions, you will need to specify the extensions path as per
|
|
||||||
configuration example. Sorting feature also requires the third-party
|
|
||||||
<code>../libs/sortabletable</code> dependency to be imported.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<!-- @import partials/pre.html -->
|
|
||||||
|
|
||||||
<!-- @import partials/countries-by-continent.html -->
|
|
||||||
|
|
||||||
<script src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.17/require.min.js"></script>
|
|
||||||
<script data-config>
|
|
||||||
requirejs(
|
|
||||||
['../dist/tablefilter/tablefilter', '../libs/sortabletable'],
|
|
||||||
function(mod){
|
|
||||||
var TableFilter = mod.TableFilter;
|
|
||||||
var tfConfig = {
|
|
||||||
base_path: '../dist/tablefilter/',
|
|
||||||
col_1: 'multiple',
|
|
||||||
col_2: 'checklist',
|
|
||||||
alternate_rows: true,
|
|
||||||
rows_counter: true,
|
|
||||||
enable_default_theme: true,
|
|
||||||
col_widths: [
|
|
||||||
'70px', '170px', '170px',
|
|
||||||
'110px', '90px', '250px'
|
|
||||||
],
|
|
||||||
extensions:[
|
|
||||||
{
|
|
||||||
name: 'sort',
|
|
||||||
path: '../dist/tablefilter/extensions/sort/',
|
|
||||||
types: [
|
|
||||||
'number', 'string', 'string',
|
|
||||||
'US', 'none', 'string'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'colsVisibility',
|
|
||||||
path: '../dist/tablefilter/extensions/colsVisibility/'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'filtersVisibility',
|
|
||||||
path: '../dist/tablefilter/extensions/filtersVisibility/'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
tf = new TableFilter('demo', tfConfig);
|
|
||||||
tf.init();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- @import partials/pre-inline-script.html -->
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -43,7 +43,7 @@
|
||||||
},
|
},
|
||||||
col_widths: [
|
col_widths: [
|
||||||
'150px', '100px', '100px',
|
'150px', '100px', '100px',
|
||||||
'70px', '70px', '70px',
|
'100px', '100px', '100px',
|
||||||
'70px', '60px', '60px'
|
'70px', '60px', '60px'
|
||||||
],
|
],
|
||||||
extensions:[{ name: 'sort' }]
|
extensions:[{ name: 'sort' }]
|
||||||
|
|
|
@ -35,19 +35,23 @@ var tfConfig = {
|
||||||
'string', 'string', 'number',
|
'string', 'string', 'number',
|
||||||
'string', 'string', 'date'
|
'string', 'string', 'date'
|
||||||
],
|
],
|
||||||
rows_counter: true,
|
rows_counter: {
|
||||||
rows_counter_text: 'Books: ',
|
text: 'Books: '
|
||||||
|
},
|
||||||
alternate_rows: true,
|
alternate_rows: true,
|
||||||
btn_reset: true,
|
btn_reset: true,
|
||||||
mark_active_columns: true,
|
mark_active_columns: {
|
||||||
|
highlight_column: true
|
||||||
|
},
|
||||||
|
|
||||||
/* Filter types*/
|
/* Filter types*/
|
||||||
col_3: 'select',
|
col_3: 'select',
|
||||||
col_4: 'select',
|
col_4: 'select',
|
||||||
|
|
||||||
/* delegate for filtering 'In store' column */
|
/* cell parser for 'In store' column */
|
||||||
custom_cell_data_cols: [3],
|
cell_parser: {
|
||||||
custom_cell_data: function(o, cell, colIndex){
|
cols: [3],
|
||||||
|
parse: function(o, cell, colIndex){
|
||||||
if(colIndex === 3){
|
if(colIndex === 3){
|
||||||
var chk = cell.getElementsByTagName('input')[0];
|
var chk = cell.getElementsByTagName('input')[0];
|
||||||
if(!chk){
|
if(!chk){
|
||||||
|
@ -59,6 +63,7 @@ var tfConfig = {
|
||||||
return 'no';
|
return 'no';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/* Custom options for 'Shipping' column */
|
/* Custom options for 'Shipping' column */
|
||||||
|
|
|
@ -6,12 +6,72 @@
|
||||||
mark_active_columns: true
|
mark_active_columns: true
|
||||||
});
|
});
|
||||||
tf.init();
|
tf.init();
|
||||||
|
var markActiveColumns = tf.feature('markActiveColumns');
|
||||||
|
|
||||||
module('Sanity checks');
|
module('Sanity checks');
|
||||||
test('Active columns', function() {
|
test('Active columns', function() {
|
||||||
deepEqual(tf instanceof TableFilter, true, 'TableFilter instanciated');
|
deepEqual(tf instanceof TableFilter, true, 'TableFilter instanciated');
|
||||||
|
notEqual(markActiveColumns, null, 'markActiveColumns instanciated');
|
||||||
|
deepEqual(tf.markActiveColumns, true, 'markActiveColumns property');
|
||||||
|
equal(markActiveColumns.emitter.events['before-filtering'].length, 1,
|
||||||
|
'subscribed to `before-filtering` event');
|
||||||
|
equal(markActiveColumns.emitter.events['cell-processed'].length, 1,
|
||||||
|
'subscribed to `cell-processed` event');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
module('Feature interface');
|
||||||
|
test('Properties', function() {
|
||||||
|
deepEqual(markActiveColumns.tf instanceof TableFilter, true,
|
||||||
|
'TableFilter instance');
|
||||||
|
deepEqual(markActiveColumns.feature, 'markActiveColumns',
|
||||||
|
'Feature name');
|
||||||
|
deepEqual(markActiveColumns.enabled, true, 'Feature enabled');
|
||||||
|
deepEqual(markActiveColumns.initialized, true, 'Feature initialized');
|
||||||
|
deepEqual(typeof markActiveColumns.emitter, 'object',
|
||||||
|
'Feature has emitter instance');
|
||||||
|
deepEqual(typeof markActiveColumns.config, 'object',
|
||||||
|
'TF configuration object');
|
||||||
|
deepEqual(typeof markActiveColumns.init, 'function',
|
||||||
|
'Feature init method');
|
||||||
|
deepEqual(typeof markActiveColumns.destroy, 'function',
|
||||||
|
'Feature destroy method');
|
||||||
|
deepEqual(typeof markActiveColumns.reset, 'function',
|
||||||
|
'Feature reset method');
|
||||||
|
deepEqual(typeof markActiveColumns.enable, 'function',
|
||||||
|
'Feature enable method');
|
||||||
|
deepEqual(typeof markActiveColumns.disable, 'function',
|
||||||
|
'Feature enable method');
|
||||||
|
deepEqual(typeof markActiveColumns.isEnabled, 'function',
|
||||||
|
'Feature enable method');
|
||||||
|
});
|
||||||
|
test('Can destroy', function() {
|
||||||
|
markActiveColumns.destroy();
|
||||||
|
deepEqual(markActiveColumns.initialized, false, 'not initialised');
|
||||||
|
});
|
||||||
|
test('Can reset', function() {
|
||||||
|
markActiveColumns.reset();
|
||||||
|
deepEqual(markActiveColumns.enabled, true, 'enabled');
|
||||||
|
});
|
||||||
|
test('Can disable', function() {
|
||||||
|
markActiveColumns.disable();
|
||||||
|
deepEqual(markActiveColumns.enabled, false, 'disabled');
|
||||||
|
});
|
||||||
|
test('Can enable', function() {
|
||||||
|
markActiveColumns.enable();
|
||||||
|
deepEqual(markActiveColumns.enabled, true, 'enabled');
|
||||||
|
});
|
||||||
|
test('Can init', function() {
|
||||||
|
markActiveColumns.destroy();
|
||||||
|
markActiveColumns.enable();
|
||||||
|
markActiveColumns.init();
|
||||||
|
deepEqual(markActiveColumns.enabled, true, 'enabled');
|
||||||
|
});
|
||||||
|
test('Can check is enabled', function() {
|
||||||
|
markActiveColumns.isEnabled();
|
||||||
|
deepEqual(markActiveColumns.enabled, true, 'enabled');
|
||||||
|
});
|
||||||
|
|
||||||
|
module('Behaviour');
|
||||||
test('Active columns', function() {
|
test('Active columns', function() {
|
||||||
tf.setFilterValue(1, 'Bri');
|
tf.setFilterValue(1, 'Bri');
|
||||||
tf.setFilterValue(3, '>2');
|
tf.setFilterValue(3, '>2');
|
||||||
|
@ -28,6 +88,59 @@
|
||||||
'Active filter indicator');
|
'Active filter indicator');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('can highlight column cells', function() {
|
||||||
|
// setup
|
||||||
|
tf.clearFilters();
|
||||||
|
var markActiveColumns = tf.feature('markActiveColumns');
|
||||||
|
markActiveColumns.highlightColumn = true;
|
||||||
|
|
||||||
|
// act
|
||||||
|
tf.setFilterValue(3, '>2');
|
||||||
|
tf.filter();
|
||||||
|
|
||||||
|
// assert
|
||||||
|
deepEqual(tf.dom().rows[6].cells[3].className,
|
||||||
|
markActiveColumns.cellCssClass, 'cell has expected css class');
|
||||||
|
deepEqual(
|
||||||
|
tf.dom()
|
||||||
|
.querySelectorAll('.' + markActiveColumns.cellCssClass).length,
|
||||||
|
7,
|
||||||
|
'number of highlighted column cells'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('can unhighlight column cells', function() {
|
||||||
|
// act
|
||||||
|
tf.clearFilters();
|
||||||
|
|
||||||
|
// assert
|
||||||
|
deepEqual(
|
||||||
|
tf.dom()
|
||||||
|
.querySelectorAll('.' + markActiveColumns.cellCssClass).length,
|
||||||
|
0,
|
||||||
|
'number of highlighted column cells'
|
||||||
|
);
|
||||||
|
|
||||||
|
markActiveColumns.highlightColumn = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
test('cannot initialiase if already initialised', function() {
|
||||||
|
// setup
|
||||||
|
var hit = 0;
|
||||||
|
var emitterOn = markActiveColumns.emitter.on;
|
||||||
|
markActiveColumns.emitter.on = function() {
|
||||||
|
hit++;
|
||||||
|
};
|
||||||
|
|
||||||
|
// act
|
||||||
|
markActiveColumns.init();
|
||||||
|
|
||||||
|
// assert
|
||||||
|
deepEqual(hit, 0, 'init exited');
|
||||||
|
|
||||||
|
markActiveColumns.emitter.on = emitterOn;
|
||||||
|
});
|
||||||
|
|
||||||
test('Active columns with paging', function() {
|
test('Active columns with paging', function() {
|
||||||
tf.destroy();
|
tf.destroy();
|
||||||
tf = null;
|
tf = null;
|
||||||
|
@ -76,8 +189,130 @@
|
||||||
header3.className.indexOf('activeHeader') !== -1,
|
header3.className.indexOf('activeHeader') !== -1,
|
||||||
true,
|
true,
|
||||||
'Active filter indicator');
|
'Active filter indicator');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Cannot destroy if not initialised', function() {
|
||||||
|
// setup
|
||||||
|
var clearActiveColumns = markActiveColumns.clearActiveColumns;
|
||||||
|
var hit = 0;
|
||||||
|
markActiveColumns.clearActiveColumns = function() { hit++; };
|
||||||
|
markActiveColumns.initialized = false;
|
||||||
|
|
||||||
|
// act
|
||||||
|
markActiveColumns.destroy();
|
||||||
|
|
||||||
|
// assert
|
||||||
|
deepEqual(hit, 0, 'clearActiveColumns not called');
|
||||||
|
|
||||||
|
markActiveColumns.clearActiveColumns = clearActiveColumns;
|
||||||
|
});
|
||||||
|
|
||||||
|
module('Callbacks');
|
||||||
|
test('Can trigger onBeforeActiveColumn callback', function() {
|
||||||
|
// setup
|
||||||
|
var colIndex;
|
||||||
|
markActiveColumns.onBeforeActiveColumn = function(feature, colIdx) {
|
||||||
|
colIndex = colIdx;
|
||||||
|
};
|
||||||
|
|
||||||
|
// act
|
||||||
|
markActiveColumns.markActiveColumn(2);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
deepEqual(colIndex, 2,
|
||||||
|
'expected column index passed to onBeforeActiveColumn');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Can trigger onAfterActiveColumn callback', function() {
|
||||||
|
// setup
|
||||||
|
var colIndex;
|
||||||
|
markActiveColumns.onAfterActiveColumn = function(feature, colIdx) {
|
||||||
|
colIndex = colIdx;
|
||||||
|
};
|
||||||
|
|
||||||
|
// act
|
||||||
|
markActiveColumns.markActiveColumn(3);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
deepEqual(colIndex, 3,
|
||||||
|
'expected column index passed to onAfterActiveColumn');
|
||||||
|
});
|
||||||
|
|
||||||
|
module('mark_active_columns as configuration object');
|
||||||
|
test('Sanity checks', function() {
|
||||||
tf.destroy();
|
tf.destroy();
|
||||||
|
var hit = 0;
|
||||||
|
tf = new TableFilter('demo', {
|
||||||
|
base_path: '../dist/tablefilter/',
|
||||||
|
mark_active_columns: {
|
||||||
|
header_css_class: 'myCssClass',
|
||||||
|
on_before_active_column: function(feature, colIndex) {
|
||||||
|
hit = colIndex;
|
||||||
|
},
|
||||||
|
on_after_active_column: function(feature, colIndex) {
|
||||||
|
hit = colIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
tf.init();
|
||||||
|
var markActiveColumns = tf.feature('markActiveColumns');
|
||||||
|
|
||||||
|
deepEqual(tf instanceof TableFilter, true, 'TableFilter instanciated');
|
||||||
|
notEqual(markActiveColumns, null, 'markActiveColumns instanciated');
|
||||||
|
deepEqual(tf.markActiveColumns, true, 'markActiveColumns property');
|
||||||
|
|
||||||
|
test('Custom header CSS class', function() {
|
||||||
|
// setup
|
||||||
|
tf.setFilterValue(1, 'Bri');
|
||||||
|
tf.setFilterValue(3, '>2');
|
||||||
|
var header1 = tf.getHeaderElement(1);
|
||||||
|
var header3 = tf.getHeaderElement(3);
|
||||||
|
|
||||||
|
// act
|
||||||
|
tf.filter();
|
||||||
|
|
||||||
|
// assert
|
||||||
|
deepEqual(
|
||||||
|
header1.className.indexOf('myCssClass') !== -1,
|
||||||
|
true,
|
||||||
|
'Active filter indicator');
|
||||||
|
deepEqual(
|
||||||
|
header3.className.indexOf('myCssClass') !== -1,
|
||||||
|
true,
|
||||||
|
'Active filter indicator');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('on_before_active_column callback', function() {
|
||||||
|
// setup
|
||||||
|
tf.clearFilters();
|
||||||
|
tf.setFilterValue(1, 'Bri');
|
||||||
|
|
||||||
|
// act
|
||||||
|
tf.filter();
|
||||||
|
|
||||||
|
// assert
|
||||||
|
deepEqual(hit, 1,
|
||||||
|
'expected column index passed to on_before_active_column');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('on_after_active_column callback', function() {
|
||||||
|
// setup
|
||||||
|
tf.clearFilters();
|
||||||
|
tf.setFilterValue(3, '>2');
|
||||||
|
|
||||||
|
// act
|
||||||
|
tf.filter();
|
||||||
|
|
||||||
|
// assert
|
||||||
|
deepEqual(hit, 3,
|
||||||
|
'expected column index passed to on_after_active_column');
|
||||||
|
});
|
||||||
|
|
||||||
|
module('Tear-down');
|
||||||
|
test('can destroy', function() {
|
||||||
|
tf.destroy();
|
||||||
|
deepEqual(tf.isInitialized(), false, 'Filters removed');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
})(window, TableFilter);
|
})(window, TableFilter);
|
||||||
|
|
|
@ -4,7 +4,7 @@ var tf = new TableFilter('demo', {
|
||||||
alternate_rows: true
|
alternate_rows: true
|
||||||
});
|
});
|
||||||
tf.init();
|
tf.init();
|
||||||
var tbl = tf.tbl;
|
var tbl = tf.dom();
|
||||||
var altRows = tf.feature('alternateRows');
|
var altRows = tf.feature('alternateRows');
|
||||||
|
|
||||||
module('Sanity checks');
|
module('Sanity checks');
|
||||||
|
@ -91,8 +91,8 @@ test('Clear filters', function() {
|
||||||
tf.clearFilters();
|
tf.clearFilters();
|
||||||
tf.filter();
|
tf.filter();
|
||||||
|
|
||||||
deepEqual(tbl.querySelectorAll('tr.odd').length, 3, 'Odd bgs removed');
|
deepEqual(tbl.querySelectorAll('tr.odd').length, 4, 'Odd bgs removed');
|
||||||
deepEqual(tbl.querySelectorAll('tr.even').length, 4, 'Even bg removed');
|
deepEqual(tbl.querySelectorAll('tr.even').length, 3, 'Even bg removed');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Set background on a row', function() {
|
test('Set background on a row', function() {
|
||||||
|
@ -110,7 +110,7 @@ test('Cannot init if initialised', function() {
|
||||||
// setup
|
// setup
|
||||||
var processAll = altRows.processAll;
|
var processAll = altRows.processAll;
|
||||||
var hit = 0;
|
var hit = 0;
|
||||||
altRows.processAll = function() { hit++ };
|
altRows.processAll = function() { hit++; };
|
||||||
altRows.initialized = true;
|
altRows.initialized = true;
|
||||||
|
|
||||||
// act
|
// act
|
||||||
|
@ -126,7 +126,7 @@ test('Cannot processAll if not enabled', function() {
|
||||||
// setup
|
// setup
|
||||||
var setRowBg = altRows.setRowBg;
|
var setRowBg = altRows.setRowBg;
|
||||||
var hit = 0;
|
var hit = 0;
|
||||||
altRows.setRowBg = function() { hit++ };
|
altRows.setRowBg = function() { hit++; };
|
||||||
altRows.enabled = false;
|
altRows.enabled = false;
|
||||||
|
|
||||||
// act
|
// act
|
||||||
|
@ -142,7 +142,7 @@ test('Cannot setRowBg if not enabled', function() {
|
||||||
// setup
|
// setup
|
||||||
var removeRowBg = altRows.removeRowBg;
|
var removeRowBg = altRows.removeRowBg;
|
||||||
var hit = 0;
|
var hit = 0;
|
||||||
altRows.removeRowBg = function() { hit++ };
|
altRows.removeRowBg = function() { hit++; };
|
||||||
altRows.enabled = false;
|
altRows.enabled = false;
|
||||||
|
|
||||||
// act
|
// act
|
||||||
|
@ -171,7 +171,7 @@ test('Cannot destroy if not initialised', function() {
|
||||||
// setup
|
// setup
|
||||||
var getRowsNb = altRows.tf.getRowsNb;
|
var getRowsNb = altRows.tf.getRowsNb;
|
||||||
var hit = 0;
|
var hit = 0;
|
||||||
altRows.tf.getRowsNb = function() { hit++ };
|
altRows.tf.getRowsNb = function() { hit++; };
|
||||||
altRows.initialized = false;
|
altRows.initialized = false;
|
||||||
|
|
||||||
// act
|
// act
|
||||||
|
@ -242,42 +242,6 @@ test('Can handle `row-paged` event', function() {
|
||||||
altRows.processRow = processRow;
|
altRows.processRow = processRow;
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Can handle `column-sorted` event', function() {
|
|
||||||
// setup
|
|
||||||
var processAll = altRows.processAll;
|
|
||||||
var hit = 0;
|
|
||||||
altRows.processAll = function() {
|
|
||||||
hit++;
|
|
||||||
};
|
|
||||||
|
|
||||||
// act
|
|
||||||
altRows.init();
|
|
||||||
tf.emitter.emit('column-sorted');
|
|
||||||
|
|
||||||
// assert
|
|
||||||
deepEqual(hit, 1, 'processAll called');
|
|
||||||
|
|
||||||
altRows.processAll = processAll;
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Can handle `rows-changed` event', function() {
|
|
||||||
// setup
|
|
||||||
var processAll = altRows.processAll;
|
|
||||||
var hit = 0;
|
|
||||||
altRows.processAll = function() {
|
|
||||||
hit++;
|
|
||||||
};
|
|
||||||
|
|
||||||
// act
|
|
||||||
altRows.init();
|
|
||||||
tf.emitter.emit('rows-changed');
|
|
||||||
|
|
||||||
// assert
|
|
||||||
deepEqual(hit, 1, 'processAll called');
|
|
||||||
|
|
||||||
altRows.processAll = processAll;
|
|
||||||
});
|
|
||||||
|
|
||||||
module('Grid layout');
|
module('Grid layout');
|
||||||
test('Grid layout: initialising alternating rows', function() {
|
test('Grid layout: initialising alternating rows', function() {
|
||||||
tf.destroy();
|
tf.destroy();
|
||||||
|
@ -288,7 +252,7 @@ test('Grid layout: initialising alternating rows', function() {
|
||||||
alternate_rows: true
|
alternate_rows: true
|
||||||
});
|
});
|
||||||
tf.init();
|
tf.init();
|
||||||
tbl = tf.tbl;
|
tbl = tf.dom();
|
||||||
altRows = tf.feature('alternateRows');
|
altRows = tf.feature('alternateRows');
|
||||||
|
|
||||||
deepEqual(
|
deepEqual(
|
||||||
|
@ -309,8 +273,8 @@ test('Grid layout: clear filters', function() {
|
||||||
tf.clearFilters();
|
tf.clearFilters();
|
||||||
tf.filter();
|
tf.filter();
|
||||||
|
|
||||||
deepEqual(tbl.querySelectorAll('tr.odd').length, 3, 'Odd bgs removed');
|
deepEqual(tbl.querySelectorAll('tr.odd').length, 4, 'Odd bgs removed');
|
||||||
deepEqual(tbl.querySelectorAll('tr.even').length, 4, 'Even bg removed');
|
deepEqual(tbl.querySelectorAll('tr.even').length, 3, 'Even bg removed');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Grid layout: set background on a row', function() {
|
test('Grid layout: set background on a row', function() {
|
||||||
|
@ -352,7 +316,7 @@ test('Sort: alternating rows with column sorted at start', function() {
|
||||||
deepEqual(altRows.oddCss, 'odd', 'Expected odd css class');
|
deepEqual(altRows.oddCss, 'odd', 'Expected odd css class');
|
||||||
|
|
||||||
function checkAlternateRows(tf) {
|
function checkAlternateRows(tf) {
|
||||||
tbl = tf.tbl;
|
tbl = tf.dom();
|
||||||
altRows = tf.feature('alternateRows');
|
altRows = tf.feature('alternateRows');
|
||||||
|
|
||||||
test('Alternate rows with sort column at start option', function() {
|
test('Alternate rows with sort column at start option', function() {
|
||||||
|
|
|
@ -1,115 +0,0 @@
|
||||||
(function(win, TableFilter){
|
|
||||||
var tf = new TableFilter('demo', {
|
|
||||||
base_path: '../dist/tablefilter/',
|
|
||||||
rows_always_visible: [4, 9]
|
|
||||||
});
|
|
||||||
tf.init();
|
|
||||||
|
|
||||||
module('Sanity checks');
|
|
||||||
test('Always visible rows', function() {
|
|
||||||
deepEqual(tf instanceof TableFilter, true, 'TableFilter type');
|
|
||||||
deepEqual(tf.hasVisibleRows, true, 'Contains always visible rows');
|
|
||||||
});
|
|
||||||
|
|
||||||
module('Behaviour');
|
|
||||||
test('for filtered table', function() {
|
|
||||||
tf.setFilterValue(0, 'Hello');
|
|
||||||
tf.filter();
|
|
||||||
var alwaysVisibleRow1 = tf.tbl.rows[4];
|
|
||||||
var alwaysVisibleRow2 = tf.tbl.rows[9];
|
|
||||||
deepEqual(
|
|
||||||
tf.getRowDisplay(alwaysVisibleRow1),
|
|
||||||
'',
|
|
||||||
'Row display for alwaysVisibleRow1'
|
|
||||||
);
|
|
||||||
deepEqual(
|
|
||||||
tf.getRowDisplay(alwaysVisibleRow2),
|
|
||||||
'',
|
|
||||||
'Row display for alwaysVisibleRow2'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('after filters are cleared', function() {
|
|
||||||
tf.clearFilters();
|
|
||||||
var alwaysVisibleRow1 = tf.tbl.rows[4];
|
|
||||||
var alwaysVisibleRow2 = tf.tbl.rows[9];
|
|
||||||
deepEqual(
|
|
||||||
tf.getRowDisplay(alwaysVisibleRow1),
|
|
||||||
'',
|
|
||||||
'Row display for alwaysVisibleRow1'
|
|
||||||
);
|
|
||||||
deepEqual(
|
|
||||||
tf.getRowDisplay(alwaysVisibleRow2),
|
|
||||||
'',
|
|
||||||
'Row display for alwaysVisibleRow2'
|
|
||||||
);
|
|
||||||
|
|
||||||
testPaging();
|
|
||||||
});
|
|
||||||
|
|
||||||
function testPaging(){
|
|
||||||
tf.destroy();
|
|
||||||
tf = new TableFilter('demo', {
|
|
||||||
base_path: '../dist/tablefilter/',
|
|
||||||
rows_always_visible: [4, 9],
|
|
||||||
paging: true,
|
|
||||||
paging_length: 2
|
|
||||||
});
|
|
||||||
tf.init();
|
|
||||||
var paging = tf.feature('paging');
|
|
||||||
|
|
||||||
module('Behaviour with paging');
|
|
||||||
test('for filtered table', function() {
|
|
||||||
tf.setFilterValue(0, 'Hello');
|
|
||||||
tf.filter();
|
|
||||||
var alwaysVisibleRow1 = tf.tbl.rows[4];
|
|
||||||
var alwaysVisibleRow2 = tf.tbl.rows[9];
|
|
||||||
deepEqual(
|
|
||||||
tf.getRowDisplay(alwaysVisibleRow1),
|
|
||||||
'',
|
|
||||||
'Row display for alwaysVisibleRow1'
|
|
||||||
);
|
|
||||||
deepEqual(
|
|
||||||
tf.getRowDisplay(alwaysVisibleRow2),
|
|
||||||
'',
|
|
||||||
'Row display for alwaysVisibleRow2'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('after filters are cleared', function() {
|
|
||||||
tf.clearFilters();
|
|
||||||
var alwaysVisibleRow1 = tf.tbl.rows[4];
|
|
||||||
var alwaysVisibleRow2 = tf.tbl.rows[9];
|
|
||||||
deepEqual(
|
|
||||||
tf.getRowDisplay(alwaysVisibleRow1),
|
|
||||||
'none',
|
|
||||||
'Row display for alwaysVisibleRow1'
|
|
||||||
);
|
|
||||||
deepEqual(
|
|
||||||
tf.getRowDisplay(alwaysVisibleRow2),
|
|
||||||
'none',
|
|
||||||
'Row display for alwaysVisibleRow2'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
test('after changing pagination page', function() {
|
|
||||||
paging.setPage(2);
|
|
||||||
var alwaysVisibleRow1 = tf.tbl.rows[4];
|
|
||||||
var alwaysVisibleRow2 = tf.tbl.rows[9];
|
|
||||||
deepEqual(
|
|
||||||
tf.getRowDisplay(alwaysVisibleRow1),
|
|
||||||
'',
|
|
||||||
'Row display for alwaysVisibleRow1'
|
|
||||||
);
|
|
||||||
deepEqual(
|
|
||||||
tf.getRowDisplay(alwaysVisibleRow2),
|
|
||||||
'none',
|
|
||||||
'Row display for alwaysVisibleRow2'
|
|
||||||
);
|
|
||||||
|
|
||||||
tf.destroy();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
})(window, TableFilter);
|
|
235
test/test-api.js
235
test/test-api.js
|
@ -14,6 +14,14 @@ var tf1 = new TableFilter('demo1', {
|
||||||
on_loaded: colsVisibilityTests
|
on_loaded: colsVisibilityTests
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
tf1.registerExtension(
|
||||||
|
{
|
||||||
|
init: function() {},
|
||||||
|
destroy: function() {}
|
||||||
|
},
|
||||||
|
'myExtension'
|
||||||
|
);
|
||||||
tf1.init();
|
tf1.init();
|
||||||
|
|
||||||
module('Sanity checks');
|
module('Sanity checks');
|
||||||
|
@ -28,6 +36,7 @@ test('TableFilter object', function() {
|
||||||
deepEqual(tf.getFilterId(0), 'flt0_demo', 'Filter DOM element id');
|
deepEqual(tf.getFilterId(0), 'flt0_demo', 'Filter DOM element id');
|
||||||
deepEqual(tf.getStartRowIndex(), 2, 'Start of filterable rows');
|
deepEqual(tf.getStartRowIndex(), 2, 'Start of filterable rows');
|
||||||
deepEqual(tf.getLastRowIndex(), 8, 'Last row index');
|
deepEqual(tf.getLastRowIndex(), 8, 'Last row index');
|
||||||
|
deepEqual(tf.dom().nodeName, 'TABLE', 'Working DOM element type');
|
||||||
deepEqual(
|
deepEqual(
|
||||||
tf.getHeadersText(),
|
tf.getHeadersText(),
|
||||||
[
|
[
|
||||||
|
@ -42,7 +51,7 @@ test('TableFilter object', function() {
|
||||||
);
|
);
|
||||||
deepEqual(tf.getValidRowsNb(), 0, 'Number of valid rows before filtering');
|
deepEqual(tf.getValidRowsNb(), 0, 'Number of valid rows before filtering');
|
||||||
deepEqual(
|
deepEqual(
|
||||||
tf.getCellData(tf.tbl.rows[3].cells[2]),
|
tf.getCellData(tf.dom().rows[3].cells[2]),
|
||||||
982,
|
982,
|
||||||
'getCellData returns typed value'
|
'getCellData returns typed value'
|
||||||
);
|
);
|
||||||
|
@ -128,6 +137,21 @@ test('Activate filter for a specified column', function() {
|
||||||
deepEqual(tf.getActiveFilterId(), filterId, 'Filter active');
|
deepEqual(tf.getActiveFilterId(), filterId, 'Filter active');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Activate filter not called if colIndex not a number', function() {
|
||||||
|
//set
|
||||||
|
var originalSetActiveFilterId = tf.setActiveFilterId;
|
||||||
|
var hit = 0;
|
||||||
|
tf.setActiveFilterId = function() { hit++; };
|
||||||
|
|
||||||
|
//act
|
||||||
|
tf.activateFilter(undefined);
|
||||||
|
|
||||||
|
//assert
|
||||||
|
deepEqual(hit, 0, 'setActiveFilterId never called');
|
||||||
|
|
||||||
|
tf.setActiveFilterId = originalSetActiveFilterId;
|
||||||
|
});
|
||||||
|
|
||||||
test('Clear filters', function() {
|
test('Clear filters', function() {
|
||||||
tf.clearFilters();
|
tf.clearFilters();
|
||||||
deepEqual(tf.getValidRowsNb(), 7, 'Filtered rows number');
|
deepEqual(tf.getValidRowsNb(), 7, 'Filtered rows number');
|
||||||
|
@ -140,6 +164,27 @@ test('Can get feature', function() {
|
||||||
deepEqual(feature.feature, 'help', 'Feature name');
|
deepEqual(feature.feature, 'help', 'Feature name');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('can iterate columns', function() {
|
||||||
|
// setup
|
||||||
|
var counter = [];
|
||||||
|
|
||||||
|
// act
|
||||||
|
tf.eachCol(
|
||||||
|
function(idx) {
|
||||||
|
counter.push(idx);
|
||||||
|
},
|
||||||
|
function(idx) {
|
||||||
|
return idx === 2;
|
||||||
|
},
|
||||||
|
function(idx) {
|
||||||
|
return idx === 4;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
deepEqual(counter, [0, 1, 3], 'column iterator conditions met');
|
||||||
|
});
|
||||||
|
|
||||||
test('Get table data', function() {
|
test('Get table data', function() {
|
||||||
deepEqual(tf.getColValues(0),
|
deepEqual(tf.getColValues(0),
|
||||||
[
|
[
|
||||||
|
@ -204,7 +249,7 @@ test('Get table data', function() {
|
||||||
tf.setFilterValue(0, 'Adelaide');
|
tf.setFilterValue(0, 'Adelaide');
|
||||||
tf.filter();
|
tf.filter();
|
||||||
deepEqual(
|
deepEqual(
|
||||||
tf.getFilteredData(),
|
tf.getFilteredValues(),
|
||||||
[
|
[
|
||||||
[6, ['Adelaide','Perth','2781','3.1','38']],
|
[6, ['Adelaide','Perth','2781','3.1','38']],
|
||||||
[7, ['Adelaide','Alice Springs','1533','2','20.25']],
|
[7, ['Adelaide','Alice Springs','1533','2','20.25']],
|
||||||
|
@ -213,7 +258,7 @@ test('Get table data', function() {
|
||||||
'Get filtered table data'
|
'Get filtered table data'
|
||||||
);
|
);
|
||||||
deepEqual(
|
deepEqual(
|
||||||
tf.getFilteredData(true),
|
tf.getFilteredValues(true),
|
||||||
[
|
[
|
||||||
[1, ['From','Destination','Road Distance (km)',
|
[1, ['From','Destination','Road Distance (km)',
|
||||||
'By Air (hrs)','By Rail (hrs)']],
|
'By Air (hrs)','By Rail (hrs)']],
|
||||||
|
@ -221,10 +266,10 @@ test('Get table data', function() {
|
||||||
[7, ['Adelaide','Alice Springs','1533','2','20.25']],
|
[7, ['Adelaide','Alice Springs','1533','2','20.25']],
|
||||||
[8, ['Adelaide','Brisbane','2045','2.15','40']]
|
[8, ['Adelaide','Brisbane','2045','2.15','40']]
|
||||||
],
|
],
|
||||||
'Get filtered table data including columns headers'
|
'Get filtered table values including columns headers'
|
||||||
);
|
);
|
||||||
deepEqual(
|
deepEqual(
|
||||||
tf.getFilteredData(false, false, true),
|
tf.getFilteredData(),
|
||||||
[
|
[
|
||||||
[6, ['Adelaide','Perth',2781,3.1,38]],
|
[6, ['Adelaide','Perth',2781,3.1,38]],
|
||||||
[7, ['Adelaide','Alice Springs',1533,2,20.25]],
|
[7, ['Adelaide','Alice Springs',1533,2,20.25]],
|
||||||
|
@ -247,6 +292,46 @@ test('Get table data', function() {
|
||||||
[2781,1533,2045],
|
[2781,1533,2045],
|
||||||
'Get specified column filtered typed values'
|
'Get specified column filtered typed values'
|
||||||
);
|
);
|
||||||
|
deepEqual(
|
||||||
|
tf.getFilteredColumnData(2),
|
||||||
|
[2781,1533,2045],
|
||||||
|
'Get filtered column data'
|
||||||
|
);
|
||||||
|
deepEqual(
|
||||||
|
tf.getFilteredColumnData(2, true),
|
||||||
|
['Road Distance (km)',2781,1533,2045],
|
||||||
|
'Get filtered column data with headers'
|
||||||
|
);
|
||||||
|
deepEqual(
|
||||||
|
tf.getVisibleColumnData(2),
|
||||||
|
[2781,1533,2045],
|
||||||
|
'Get visible column data'
|
||||||
|
);
|
||||||
|
deepEqual(
|
||||||
|
tf.getVisibleColumnData(2, true),
|
||||||
|
['Road Distance (km)',2781,1533,2045],
|
||||||
|
'Get visible column data with headers'
|
||||||
|
);
|
||||||
|
deepEqual(
|
||||||
|
tf.getFilteredColumnValues(2),
|
||||||
|
['2781','1533','2045'],
|
||||||
|
'Get filtered column data'
|
||||||
|
);
|
||||||
|
deepEqual(
|
||||||
|
tf.getFilteredColumnValues(2, true),
|
||||||
|
['Road Distance (km)','2781','1533','2045'],
|
||||||
|
'Get filtered column data with headers'
|
||||||
|
);
|
||||||
|
deepEqual(
|
||||||
|
tf.getVisibleColumnValues(2),
|
||||||
|
['2781','1533','2045'],
|
||||||
|
'Get visible column data'
|
||||||
|
);
|
||||||
|
deepEqual(
|
||||||
|
tf.getVisibleColumnValues(2, true),
|
||||||
|
['Road Distance (km)','2781','1533','2045'],
|
||||||
|
'Get visible column data with headers'
|
||||||
|
);
|
||||||
tf.clearFilters();
|
tf.clearFilters();
|
||||||
tf.filter();
|
tf.filter();
|
||||||
});
|
});
|
||||||
|
@ -264,7 +349,8 @@ test('Test filter types', function() {
|
||||||
base_path: '../dist/tablefilter/',
|
base_path: '../dist/tablefilter/',
|
||||||
col_0: 'select',
|
col_0: 'select',
|
||||||
col_1: 'multiple',
|
col_1: 'multiple',
|
||||||
col_2: 'checklist'
|
col_2: 'checklist',
|
||||||
|
col_types: ['string', 'string', 'number', 'number', 'number']
|
||||||
});
|
});
|
||||||
tf.init();
|
tf.init();
|
||||||
|
|
||||||
|
@ -338,17 +424,28 @@ test('Can select checklist options with array', function() {
|
||||||
tf.setFilterValue(2, '');
|
tf.setFilterValue(2, '');
|
||||||
tf.setFilterValue(2, ['1412', '982']);
|
tf.setFilterValue(2, ['1412', '982']);
|
||||||
|
|
||||||
deepEqual(tf.getFilterValue(2), ['1412', '982'],
|
deepEqual(tf.getFilterValue(2), ['982', '1412'],
|
||||||
'Column 2 filter values');
|
'Column 2 filter values');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('get and set filter value can handle out of range column index',
|
||||||
|
function() {
|
||||||
|
// act
|
||||||
|
tf.setFilterValue(11, '');
|
||||||
|
|
||||||
|
// assert
|
||||||
|
deepEqual(tf.getFilterValue(11), '',
|
||||||
|
'return empty string for inexistent filter');
|
||||||
|
});
|
||||||
|
|
||||||
module('TableFilter with pop-up filters');
|
module('TableFilter with pop-up filters');
|
||||||
test('Sanity checks', function() {
|
test('Sanity checks', function() {
|
||||||
tf.destroy();
|
tf.destroy();
|
||||||
tf = null;
|
tf = null;
|
||||||
tf = new TableFilter('demo', {
|
tf = new TableFilter('demo', {
|
||||||
base_path: '../dist/tablefilter/',
|
base_path: '../dist/tablefilter/',
|
||||||
popup_filters: true
|
popup_filters: true,
|
||||||
|
col_types: ['string', 'string', 'number', 'number', 'number']
|
||||||
});
|
});
|
||||||
tf.init();
|
tf.init();
|
||||||
|
|
||||||
|
@ -396,7 +493,8 @@ test('Sanity checks', function() {
|
||||||
grid_layout: true,
|
grid_layout: true,
|
||||||
col_0: 'select',
|
col_0: 'select',
|
||||||
col_1: 'multiple',
|
col_1: 'multiple',
|
||||||
col_2: 'checklist'
|
col_2: 'checklist',
|
||||||
|
col_types: ['string', 'string', 'number', 'number', 'number']
|
||||||
});
|
});
|
||||||
tf.init();
|
tf.init();
|
||||||
|
|
||||||
|
@ -456,6 +554,28 @@ test('Get table data', function() {
|
||||||
],
|
],
|
||||||
'Get specified column values including column header'
|
'Get specified column values including column header'
|
||||||
);
|
);
|
||||||
|
deepEqual(tf.getColumnValues(0),
|
||||||
|
[
|
||||||
|
'Sydney','Sydney','Sydney',
|
||||||
|
'Sydney','Adelaide','Adelaide','Adelaide'
|
||||||
|
],
|
||||||
|
'Get specified column values'
|
||||||
|
);
|
||||||
|
deepEqual(tf.getColumnValues(0, true),
|
||||||
|
[
|
||||||
|
'From','Sydney','Sydney','Sydney',
|
||||||
|
'Sydney','Adelaide','Adelaide','Adelaide'
|
||||||
|
],
|
||||||
|
'Get specified column values including column header'
|
||||||
|
);
|
||||||
|
deepEqual(tf.getColumnData(2),
|
||||||
|
[1412, 982, 286, 872, 2781, 1533, 2045],
|
||||||
|
'Get specified column data'
|
||||||
|
);
|
||||||
|
deepEqual(tf.getColumnData(2, true),
|
||||||
|
['Road Distance (km)', 1412, 982, 286, 872, 2781, 1533, 2045],
|
||||||
|
'Get specified column data including column header'
|
||||||
|
);
|
||||||
deepEqual(
|
deepEqual(
|
||||||
tf.getTableData(),
|
tf.getTableData(),
|
||||||
[
|
[
|
||||||
|
@ -467,22 +587,49 @@ test('Get table data', function() {
|
||||||
[5, ['Adelaide','Alice Springs','1533','2','20.25']],
|
[5, ['Adelaide','Alice Springs','1533','2','20.25']],
|
||||||
[6, ['Adelaide','Brisbane','2045','2.15','40']]
|
[6, ['Adelaide','Brisbane','2045','2.15','40']]
|
||||||
],
|
],
|
||||||
|
'Get table values with getTableData()'
|
||||||
|
);
|
||||||
|
deepEqual(
|
||||||
|
tf.getData(),
|
||||||
|
[
|
||||||
|
[0, ['Sydney','Adelaide',1412,1.4,25.3]],
|
||||||
|
[1, ['Sydney','Brisbane',982,1.5,16]],
|
||||||
|
[2, ['Sydney','Canberra',286,0.6,4.3]],
|
||||||
|
[3, ['Sydney','Melbourne',872,1.1,10.5]],
|
||||||
|
[4, ['Adelaide','Perth',2781,3.1,38]],
|
||||||
|
[5, ['Adelaide','Alice Springs',1533,2,20.25]],
|
||||||
|
[6, ['Adelaide','Brisbane',2045,2.15,40]]
|
||||||
|
],
|
||||||
'Get table data'
|
'Get table data'
|
||||||
);
|
);
|
||||||
|
deepEqual(
|
||||||
|
tf.getValues(),
|
||||||
|
[
|
||||||
|
[0, ['Sydney','Adelaide','1412','1.4','25.3']],
|
||||||
|
[1, ['Sydney','Brisbane','982','1.5','16']],
|
||||||
|
[2, ['Sydney','Canberra','286','.6','4.3']],
|
||||||
|
[3, ['Sydney','Melbourne','872','1.1','10.5']],
|
||||||
|
[4, ['Adelaide','Perth','2781','3.1','38']],
|
||||||
|
[5, ['Adelaide','Alice Springs','1533','2','20.25']],
|
||||||
|
[6, ['Adelaide','Brisbane','2045','2.15','40']]
|
||||||
|
],
|
||||||
|
'Get table values'
|
||||||
|
);
|
||||||
|
|
||||||
tf.clearFilters();
|
tf.clearFilters();
|
||||||
tf.setFilterValue(0, 'Adelaide');
|
tf.setFilterValue(0, 'Adelaide');
|
||||||
tf.filter();
|
tf.filter();
|
||||||
deepEqual(
|
deepEqual(
|
||||||
tf.getFilteredData(),
|
tf.getFilteredValues(),
|
||||||
[
|
[
|
||||||
[4, ['Adelaide','Perth','2781','3.1','38']],
|
[4, ['Adelaide','Perth','2781','3.1','38']],
|
||||||
[5, ['Adelaide','Alice Springs','1533','2','20.25']],
|
[5, ['Adelaide','Alice Springs','1533','2','20.25']],
|
||||||
[6, ['Adelaide','Brisbane','2045','2.15','40']]
|
[6, ['Adelaide','Brisbane','2045','2.15','40']]
|
||||||
],
|
],
|
||||||
'Get filtered table data'
|
'Get filtered table values'
|
||||||
);
|
);
|
||||||
deepEqual(
|
deepEqual(
|
||||||
tf.getFilteredData(true),
|
tf.getFilteredValues(true),
|
||||||
[
|
[
|
||||||
[0, ['From','Destination','Road Distance (km)',
|
[0, ['From','Destination','Road Distance (km)',
|
||||||
'By Air (hrs)','By Rail (hrs)']],
|
'By Air (hrs)','By Rail (hrs)']],
|
||||||
|
@ -490,7 +637,7 @@ test('Get table data', function() {
|
||||||
[5, ['Adelaide','Alice Springs','1533','2','20.25']],
|
[5, ['Adelaide','Alice Springs','1533','2','20.25']],
|
||||||
[6, ['Adelaide','Brisbane','2045','2.15','40']]
|
[6, ['Adelaide','Brisbane','2045','2.15','40']]
|
||||||
],
|
],
|
||||||
'Get filtered table data including columns headers'
|
'Get filtered table values including columns headers'
|
||||||
);
|
);
|
||||||
deepEqual(
|
deepEqual(
|
||||||
tf.getFilteredDataCol(0),
|
tf.getFilteredDataCol(0),
|
||||||
|
@ -502,6 +649,46 @@ test('Get table data', function() {
|
||||||
['From','Adelaide','Adelaide','Adelaide'],
|
['From','Adelaide','Adelaide','Adelaide'],
|
||||||
'Get specified column filtered values including header'
|
'Get specified column filtered values including header'
|
||||||
);
|
);
|
||||||
|
deepEqual(
|
||||||
|
tf.getFilteredColumnData(2),
|
||||||
|
[2781,1533,2045],
|
||||||
|
'Get filtered column data'
|
||||||
|
);
|
||||||
|
deepEqual(
|
||||||
|
tf.getFilteredColumnData(2, true),
|
||||||
|
['Road Distance (km)',2781,1533,2045],
|
||||||
|
'Get filtered column data with headers'
|
||||||
|
);
|
||||||
|
deepEqual(
|
||||||
|
tf.getVisibleColumnData(2),
|
||||||
|
[2781,1533,2045],
|
||||||
|
'Get visible column data'
|
||||||
|
);
|
||||||
|
deepEqual(
|
||||||
|
tf.getVisibleColumnData(2, true),
|
||||||
|
['Road Distance (km)',2781,1533,2045],
|
||||||
|
'Get visible column data with headers'
|
||||||
|
);
|
||||||
|
deepEqual(
|
||||||
|
tf.getFilteredColumnValues(2),
|
||||||
|
['2781','1533','2045'],
|
||||||
|
'Get filtered column data'
|
||||||
|
);
|
||||||
|
deepEqual(
|
||||||
|
tf.getFilteredColumnValues(2, true),
|
||||||
|
['Road Distance (km)','2781','1533','2045'],
|
||||||
|
'Get filtered column data with headers'
|
||||||
|
);
|
||||||
|
deepEqual(
|
||||||
|
tf.getVisibleColumnValues(2),
|
||||||
|
['2781','1533','2045'],
|
||||||
|
'Get visible column data'
|
||||||
|
);
|
||||||
|
deepEqual(
|
||||||
|
tf.getVisibleColumnValues(2, true),
|
||||||
|
['Road Distance (km)','2781','1533','2045'],
|
||||||
|
'Get visible column data with headers'
|
||||||
|
);
|
||||||
tf.clearFilters();
|
tf.clearFilters();
|
||||||
tf.filter();
|
tf.filter();
|
||||||
});
|
});
|
||||||
|
@ -520,24 +707,24 @@ function colsVisibilityTests() { // issue 94
|
||||||
tf1.filter();
|
tf1.filter();
|
||||||
|
|
||||||
deepEqual(
|
deepEqual(
|
||||||
tf1.getFilteredData(false, true),
|
tf1.getFilteredValues(false, true),
|
||||||
[
|
[
|
||||||
[6, ['Adelaide','3.1','38']],
|
[6, ['Adelaide','3.1','38']],
|
||||||
[7, ['Adelaide','2','20.25']],
|
[7, ['Adelaide','2','20.25']],
|
||||||
[8, ['Adelaide','2.15','40']]
|
[8, ['Adelaide','2.15','40']]
|
||||||
],
|
],
|
||||||
'Get filtered table data with excluded columns'
|
'Get filtered table values with excluded columns'
|
||||||
);
|
);
|
||||||
|
|
||||||
deepEqual(
|
deepEqual(
|
||||||
tf1.getFilteredData(true, true),
|
tf1.getFilteredValues(true, true),
|
||||||
[
|
[
|
||||||
[1, ['From','By Air (hrs)','By Rail (hrs)']],
|
[1, ['From','By Air (hrs)','By Rail (hrs)']],
|
||||||
[6, ['Adelaide','3.1','38']],
|
[6, ['Adelaide','3.1','38']],
|
||||||
[7, ['Adelaide','2','20.25']],
|
[7, ['Adelaide','2','20.25']],
|
||||||
[8, ['Adelaide','2.15','40']]
|
[8, ['Adelaide','2.15','40']]
|
||||||
],
|
],
|
||||||
'Get filtered table data with headers and excluded columns'
|
'Get filtered table values with headers and excluded columns'
|
||||||
);
|
);
|
||||||
|
|
||||||
deepEqual(
|
deepEqual(
|
||||||
|
@ -586,6 +773,20 @@ function colsVisibilityTests() { // issue 94
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Extension Sanity checks', function() {
|
||||||
|
deepEqual(
|
||||||
|
tf1.hasExtension('colsVisibility'),
|
||||||
|
true,
|
||||||
|
'ColsVisibility in extensions registry'
|
||||||
|
);
|
||||||
|
|
||||||
|
deepEqual(
|
||||||
|
tf1.hasExtension('myExtension'),
|
||||||
|
true,
|
||||||
|
'myExtension in extensions registry'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test('Destroy', function() {
|
test('Destroy', function() {
|
||||||
tf1.destroy();
|
tf1.destroy();
|
||||||
deepEqual(tf1.isInitialized(), false, 'Filters removed');
|
deepEqual(tf1.isInitialized(), false, 'Filters removed');
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
|
|
||||||
var tf = new TableFilter('demo', {
|
var tf = new TableFilter('demo', {
|
||||||
base_path: '../dist/tablefilter/',
|
base_path: '../dist/tablefilter/',
|
||||||
auto_filter: true,
|
auto_filter: {
|
||||||
auto_filter_delay: 1000
|
delay: 1000
|
||||||
|
}
|
||||||
});
|
});
|
||||||
tf.init();
|
tf.init();
|
||||||
window.tf = tf;
|
window.tf = tf;
|
||||||
|
@ -14,6 +15,18 @@
|
||||||
deepEqual(tf.autoFilter, true, 'Auto filtering enabled');
|
deepEqual(tf.autoFilter, true, 'Auto filtering enabled');
|
||||||
deepEqual(tf.autoFilterDelay, 1000, 'Expected filtering delay');
|
deepEqual(tf.autoFilterDelay, 1000, 'Expected filtering delay');
|
||||||
});
|
});
|
||||||
|
test('Blur input filter', function() {
|
||||||
|
// setup
|
||||||
|
var filter = tf.getFilterElement(0);
|
||||||
|
filter.focus();
|
||||||
|
|
||||||
|
// act
|
||||||
|
filter.blur();
|
||||||
|
|
||||||
|
// assert
|
||||||
|
deepEqual(tf.isUserTyping, false, 'User not typing');
|
||||||
|
deepEqual(tf.autoFilterTimer, null, 'Auto filter timer cleared');
|
||||||
|
});
|
||||||
|
|
||||||
module('Remove feature');
|
module('Remove feature');
|
||||||
test('Auto filter feature disabled', function() {
|
test('Auto filter feature disabled', function() {
|
||||||
|
|
109
test/test-cell-parser.html
Normal file
109
test/test-cell-parser.html
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>TableFilter filter with cell parser</title>
|
||||||
|
<link rel="stylesheet" href="libs/qunit/qunit.css">
|
||||||
|
<script src="libs/qunit/qunit.js"></script>
|
||||||
|
<script src="libs/polyfill.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<table id="demo">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th>From</th>
|
||||||
|
<th>Destination</th>
|
||||||
|
<th>Road Distance (km)</th>
|
||||||
|
<th>By Air (hrs)</th>
|
||||||
|
<th>By Rail (hrs)</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" disabled="disabled"
|
||||||
|
value="" checked="checked">
|
||||||
|
</td>
|
||||||
|
<td><strong>Sydney</strong></td>
|
||||||
|
<td>Adelaide</td>
|
||||||
|
<td>1412</td>
|
||||||
|
<td>1.4</td>
|
||||||
|
<td>25.3</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" disabled="disabled"
|
||||||
|
value="">
|
||||||
|
</td>
|
||||||
|
<td><strong>Sydney</strong></td>
|
||||||
|
<td>Brisbane</td>
|
||||||
|
<td>982</td>
|
||||||
|
<td>1.5</td>
|
||||||
|
<td>16</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" disabled="disabled"
|
||||||
|
value="" checked="checked">
|
||||||
|
</td>
|
||||||
|
<td><strong>Sydney</strong></td>
|
||||||
|
<td>Canberra</td>
|
||||||
|
<td>286</td>
|
||||||
|
<td>.6</td>
|
||||||
|
<td>4.3</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" disabled="disabled"
|
||||||
|
value="" checked="checked">
|
||||||
|
</td>
|
||||||
|
<td><strong>Sydney</strong></td>
|
||||||
|
<td>Melbourne</td>
|
||||||
|
<td>872</td>
|
||||||
|
<td>1.1</td>
|
||||||
|
<td>10.5</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" disabled="disabled"
|
||||||
|
value="">
|
||||||
|
</td>
|
||||||
|
<td><strong>Adelaide</strong></td>
|
||||||
|
<td>Perth</td>
|
||||||
|
<td>2781</td>
|
||||||
|
<td>3.1</td>
|
||||||
|
<td>38</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" disabled="disabled"
|
||||||
|
value="" checked="checked">
|
||||||
|
</td>
|
||||||
|
<td><strong>Adelaide</strong></td>
|
||||||
|
<td>Alice Springs</td>
|
||||||
|
<td>1533</td>
|
||||||
|
<td>2</td>
|
||||||
|
<td>20.25</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" disabled="disabled"
|
||||||
|
value="">
|
||||||
|
</td>
|
||||||
|
<td><strong>Adelaide</strong></td>
|
||||||
|
<td>Brisbane</td>
|
||||||
|
<td>2045</td>
|
||||||
|
<td>2.15</td>
|
||||||
|
<td>40</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<script src="../dist/tablefilter/tablefilter.js"></script>
|
||||||
|
<script src="test-cell-parser.js"></script>
|
||||||
|
|
||||||
|
<div id="qunit"></div>
|
||||||
|
<div id="qunit-fixture"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
80
test/test-cell-parser.js
Normal file
80
test/test-cell-parser.js
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
(function(win, TableFilter){
|
||||||
|
|
||||||
|
var tf = new TableFilter('demo', {
|
||||||
|
base_path: '../dist/tablefilter/',
|
||||||
|
col_0: 'select',
|
||||||
|
cell_parser: {
|
||||||
|
cols: [0],
|
||||||
|
parse: function(tf, cell) {
|
||||||
|
var chk = cell.getElementsByTagName('input')[0];
|
||||||
|
if (chk.checked) {
|
||||||
|
return 'yes';
|
||||||
|
} else {
|
||||||
|
return 'no';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
tf.init();
|
||||||
|
|
||||||
|
module('Sanity checks');
|
||||||
|
test('Sanity checks', function() {
|
||||||
|
deepEqual(tf instanceof TableFilter, true, 'TableFilter instanciated');
|
||||||
|
deepEqual(tf.cellParser.cols.length, 1,
|
||||||
|
'Columns implementing cell parser');
|
||||||
|
deepEqual(typeof tf.cellParser.parse, 'function', 'Parse function');
|
||||||
|
deepEqual(
|
||||||
|
tf.getFilterElement(0).nodeName, 'SELECT', 'Expected filter type');
|
||||||
|
});
|
||||||
|
|
||||||
|
module('Behaviour');
|
||||||
|
test('Can filter with parsed value', function() {
|
||||||
|
// setup
|
||||||
|
tf.setFilterValue(0, 'yes');
|
||||||
|
|
||||||
|
// act
|
||||||
|
tf.filter();
|
||||||
|
|
||||||
|
// assert
|
||||||
|
deepEqual(tf.getValidRows(), [2, 4, 5, 7], 'Number of parsed values');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Can parse with custom function', function() {
|
||||||
|
// setup
|
||||||
|
var cell = tf.dom().rows[3].cells[0];
|
||||||
|
|
||||||
|
// act
|
||||||
|
var value = tf.getCellValue(cell);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
deepEqual(value, 'no', 'Value returned by custom cell parser');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Should not parse with custom function if no columns defined',
|
||||||
|
function() {
|
||||||
|
// setup
|
||||||
|
var initialCellParser = tf.cellParser;
|
||||||
|
var hit = 0;
|
||||||
|
var cell = tf.dom().rows[3].cells[0];
|
||||||
|
|
||||||
|
tf.cellParser.cols = [];
|
||||||
|
tf.cellParser.parse = function() {
|
||||||
|
hit++;
|
||||||
|
};
|
||||||
|
|
||||||
|
// act
|
||||||
|
tf.getCellValue(cell);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
deepEqual(hit, 0, 'Cell parser not invoked');
|
||||||
|
|
||||||
|
tf.cellParser = initialCellParser;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
module('Tear-down');
|
||||||
|
test('can destroy', function() {
|
||||||
|
tf.destroy();
|
||||||
|
deepEqual(tf.isInitialized(), false, 'Filters removed');
|
||||||
|
});
|
||||||
|
})(window, TableFilter);
|
|
@ -41,7 +41,7 @@ test('Can refresh all drop-down filters', function() {
|
||||||
tf.clearFilters();
|
tf.clearFilters();
|
||||||
var build = checkList.build;
|
var build = checkList.build;
|
||||||
var hit = 0;
|
var hit = 0;
|
||||||
checkList.build = function() { hit++ };
|
checkList.build = function() { hit++; };
|
||||||
|
|
||||||
//act
|
//act
|
||||||
checkList.refreshAll();
|
checkList.refreshAll();
|
||||||
|
@ -100,18 +100,43 @@ test('Can sort options', function() {
|
||||||
tf.destroy();
|
tf.destroy();
|
||||||
tf = new TableFilter('demo', {
|
tf = new TableFilter('demo', {
|
||||||
base_path: '../dist/tablefilter/',
|
base_path: '../dist/tablefilter/',
|
||||||
|
col_0: 'checklist',
|
||||||
|
col_1: 'checklist',
|
||||||
col_2: 'checklist',
|
col_2: 'checklist',
|
||||||
col_3: 'checklist',
|
col_3: 'checklist',
|
||||||
col_4: 'checklist',
|
col_4: 'checklist',
|
||||||
sort_num_asc: [2, 3],
|
col_types: ['string', 'string', 'number', 'number', 'number'],
|
||||||
sort_num_desc: [4]
|
sort_filter_options_asc: [0, 2, 3],
|
||||||
|
sort_filter_options_desc: [1, 4]
|
||||||
});
|
});
|
||||||
tf.init();
|
tf.init();
|
||||||
|
|
||||||
|
var flt0 = id(tf.fltIds[0]);
|
||||||
|
var flt1 = id(tf.fltIds[1]);
|
||||||
var flt2 = id(tf.fltIds[2]);
|
var flt2 = id(tf.fltIds[2]);
|
||||||
var flt3 = id(tf.fltIds[3]);
|
var flt3 = id(tf.fltIds[3]);
|
||||||
var flt4 = id(tf.fltIds[4]);
|
var flt4 = id(tf.fltIds[4]);
|
||||||
|
|
||||||
|
deepEqual(
|
||||||
|
flt0.getElementsByTagName('li')[1].firstChild.firstChild.value,
|
||||||
|
'Adelaide',
|
||||||
|
'First option value for column 0'
|
||||||
|
);
|
||||||
|
deepEqual(
|
||||||
|
flt0.getElementsByTagName('li')[2].firstChild.firstChild.value,
|
||||||
|
'Sydney',
|
||||||
|
'Last option value for column 0'
|
||||||
|
);
|
||||||
|
deepEqual(
|
||||||
|
flt1.getElementsByTagName('li')[1].firstChild.firstChild.value,
|
||||||
|
'Perth',
|
||||||
|
'First option value for column 1'
|
||||||
|
);
|
||||||
|
deepEqual(
|
||||||
|
flt1.getElementsByTagName('li')[6].firstChild.firstChild.value,
|
||||||
|
'Adelaide',
|
||||||
|
'Last option value for column 1'
|
||||||
|
);
|
||||||
deepEqual(
|
deepEqual(
|
||||||
flt2.getElementsByTagName('li')[1].firstChild.firstChild.value,
|
flt2.getElementsByTagName('li')[1].firstChild.firstChild.value,
|
||||||
'286',
|
'286',
|
||||||
|
@ -181,6 +206,55 @@ test('Can select empty and non-empty options', function() {
|
||||||
'Filter 3 options values attribute');
|
'Filter 3 options values attribute');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// issue 714, clear filter text
|
||||||
|
module('Clear filter text');
|
||||||
|
test('Can define clear filter text for each column', function() {
|
||||||
|
tf.clearFilters();
|
||||||
|
tf.destroy();
|
||||||
|
tf = new TableFilter('demo', {
|
||||||
|
base_path: '../dist/tablefilter/',
|
||||||
|
col_2: 'checklist',
|
||||||
|
col_3: 'checklist',
|
||||||
|
col_4: 'checklist',
|
||||||
|
clear_filter_text: [null, null, 'clear 2', 'clear 3', 'clear 4']
|
||||||
|
});
|
||||||
|
tf.init();
|
||||||
|
|
||||||
|
var flt2 = tf.getFilterElement(2).getElementsByTagName('li');
|
||||||
|
var flt3 = tf.getFilterElement(3).getElementsByTagName('li');
|
||||||
|
var flt4 = tf.getFilterElement(4).getElementsByTagName('li');
|
||||||
|
|
||||||
|
deepEqual(flt2[0].getElementsByTagName('label')[0].innerText,
|
||||||
|
'clear 2', 'clear text filter 2');
|
||||||
|
deepEqual(flt3[0].getElementsByTagName('label')[0].innerText,
|
||||||
|
'clear 3', 'clear text filter 3');
|
||||||
|
deepEqual(flt4[0].getElementsByTagName('label')[0].innerText,
|
||||||
|
'clear 4', 'clear text filter 4');
|
||||||
|
});
|
||||||
|
test('Can define clear filter text globally', function() {
|
||||||
|
tf.clearFilters();
|
||||||
|
tf.destroy();
|
||||||
|
tf = new TableFilter('demo', {
|
||||||
|
base_path: '../dist/tablefilter/',
|
||||||
|
col_2: 'checklist',
|
||||||
|
col_3: 'checklist',
|
||||||
|
col_4: 'checklist',
|
||||||
|
clear_filter_text: 'reset'
|
||||||
|
});
|
||||||
|
tf.init();
|
||||||
|
|
||||||
|
var flt2 = tf.getFilterElement(2).getElementsByTagName('li');
|
||||||
|
var flt3 = tf.getFilterElement(3).getElementsByTagName('li');
|
||||||
|
var flt4 = tf.getFilterElement(4).getElementsByTagName('li');
|
||||||
|
|
||||||
|
deepEqual(flt2[0].getElementsByTagName('label')[0].innerText,
|
||||||
|
'reset', 'clear text filter 2');
|
||||||
|
deepEqual(flt3[0].getElementsByTagName('label')[0].innerText,
|
||||||
|
'reset', 'clear text filter 3');
|
||||||
|
deepEqual(flt4[0].getElementsByTagName('label')[0].innerText,
|
||||||
|
'reset', 'clear text filter 4');
|
||||||
|
});
|
||||||
|
|
||||||
module('Tear down');
|
module('Tear down');
|
||||||
test('TableFilter removed', function() {
|
test('TableFilter removed', function() {
|
||||||
tf.destroy();
|
tf.destroy();
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
<script src="libs/polyfill.js"></script>
|
<script src="libs/polyfill.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<div id="external-container"></div>
|
||||||
<table id="demo" cellpadding="0" cellspacing="0">
|
<table id="demo" cellpadding="0" cellspacing="0">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
@ -6,6 +6,7 @@ var tf = new TableFilter('demo', {
|
||||||
tf.init();
|
tf.init();
|
||||||
|
|
||||||
var clearButton = tf.feature('clearButton');
|
var clearButton = tf.feature('clearButton');
|
||||||
|
|
||||||
module('Sanity checks');
|
module('Sanity checks');
|
||||||
test('Clear button component', function() {
|
test('Clear button component', function() {
|
||||||
deepEqual(typeof clearButton, 'object', 'ClearButton instanciated');
|
deepEqual(typeof clearButton, 'object', 'ClearButton instanciated');
|
||||||
|
@ -58,6 +59,61 @@ test('Can check is enabled', function() {
|
||||||
deepEqual(clearButton.enabled, true, 'enabled');
|
deepEqual(clearButton.enabled, true, 'enabled');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
module('Behaviour');
|
||||||
|
test('Cannot init if already initialised', function() {
|
||||||
|
// setup
|
||||||
|
clearButton.initialized = true;
|
||||||
|
var emit = clearButton.emitter.emit;
|
||||||
|
var hit = 0;
|
||||||
|
clearButton.emitter.emit = function() {
|
||||||
|
hit++;
|
||||||
|
};
|
||||||
|
|
||||||
|
// act
|
||||||
|
clearButton.init();
|
||||||
|
|
||||||
|
// assert
|
||||||
|
deepEqual(hit, 0, 'does not initialise');
|
||||||
|
|
||||||
|
clearButton.emitter.emit = emit;
|
||||||
|
});
|
||||||
|
|
||||||
|
test('onClick does nothing if not enabled', function() {
|
||||||
|
// setup
|
||||||
|
clearButton.disable();
|
||||||
|
var clearFilters = clearButton.tf.clearFilters;
|
||||||
|
var hit = 0;
|
||||||
|
clearButton.tf.clearFilters = function() {
|
||||||
|
hit++;
|
||||||
|
};
|
||||||
|
|
||||||
|
// act
|
||||||
|
clearButton.onClick();
|
||||||
|
|
||||||
|
// assert
|
||||||
|
deepEqual(hit, 0, 'onClick does nothing');
|
||||||
|
|
||||||
|
clearButton.tf.clearFilters = clearFilters;
|
||||||
|
});
|
||||||
|
|
||||||
|
test('onClick calls clearFilters if enabled', function() {
|
||||||
|
// setup
|
||||||
|
clearButton.enable();
|
||||||
|
var clearFilters = clearButton.tf.clearFilters;
|
||||||
|
var hit = 0;
|
||||||
|
clearButton.tf.clearFilters = function() {
|
||||||
|
hit++;
|
||||||
|
};
|
||||||
|
|
||||||
|
// act
|
||||||
|
clearButton.onClick();
|
||||||
|
|
||||||
|
// assert
|
||||||
|
deepEqual(hit, 1, 'onClick calls clearFilters');
|
||||||
|
|
||||||
|
clearButton.tf.clearFilters = clearFilters;
|
||||||
|
});
|
||||||
|
|
||||||
module('UI elements');
|
module('UI elements');
|
||||||
test('ClearButton UI elements', function() {
|
test('ClearButton UI elements', function() {
|
||||||
var container = clearButton.container;
|
var container = clearButton.container;
|
||||||
|
@ -73,7 +129,7 @@ test('Remove UI', function() {
|
||||||
deepEqual(btnResetEl, null, 'Clear button is removed');
|
deepEqual(btnResetEl, null, 'Clear button is removed');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Re-set UI', function() {
|
test('Re-set UI with no icons and text button', function() {
|
||||||
clearButton.destroy();
|
clearButton.destroy();
|
||||||
tf.enableIcons = false;
|
tf.enableIcons = false;
|
||||||
clearButton.html = null;
|
clearButton.html = null;
|
||||||
|
@ -85,6 +141,40 @@ test('Re-set UI', function() {
|
||||||
deepEqual(btnResetEl.innerText, 'Clear', 'Clear button text');
|
deepEqual(btnResetEl.innerText, 'Clear', 'Clear button text');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Destroy and init with text button and icons enabled', function() {
|
||||||
|
tf.destroy();
|
||||||
|
tf = new TableFilter('demo', {
|
||||||
|
base_path: '../dist/tablefilter/',
|
||||||
|
btn_reset: {
|
||||||
|
text: 'Clear all'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
tf.init();
|
||||||
|
|
||||||
|
clearButton = tf.feature('clearButton');
|
||||||
|
|
||||||
|
var btnResetEl = clearButton.element;
|
||||||
|
deepEqual(btnResetEl.nodeName, 'A', 'Clear button tag changed');
|
||||||
|
deepEqual(btnResetEl.innerText, 'Clear all', 'Clear button text');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Destroy and init in external container', function() {
|
||||||
|
tf.destroy();
|
||||||
|
tf = new TableFilter('demo', {
|
||||||
|
base_path: '../dist/tablefilter/',
|
||||||
|
btn_reset: {
|
||||||
|
target_id: 'external-container'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
tf.init();
|
||||||
|
|
||||||
|
clearButton = tf.feature('clearButton');
|
||||||
|
|
||||||
|
deepEqual(clearButton.element.nodeName, 'INPUT', 'Clear button tag');
|
||||||
|
deepEqual(clearButton.container.parentNode.id, 'external-container',
|
||||||
|
'container id');
|
||||||
|
});
|
||||||
|
|
||||||
module('Tear-down');
|
module('Tear-down');
|
||||||
test('can destroy TableFilter DOM elements', function() {
|
test('can destroy TableFilter DOM elements', function() {
|
||||||
tf.destroy();
|
tf.destroy();
|
||||||
|
|
|
@ -6,8 +6,9 @@ var totRowIndex = table.getElementsByTagName('tr').length;
|
||||||
tf = new TableFilter('demo', {
|
tf = new TableFilter('demo', {
|
||||||
base_path: '../dist/tablefilter/',
|
base_path: '../dist/tablefilter/',
|
||||||
col_types: ['string', 'string', 'number', 'number', 'number'],
|
col_types: ['string', 'string', 'number', 'number', 'number'],
|
||||||
paging: true,
|
paging: {
|
||||||
paging_length: 4,
|
length: 4
|
||||||
|
},
|
||||||
rows_always_visible: [
|
rows_always_visible: [
|
||||||
totRowIndex-6,
|
totRowIndex-6,
|
||||||
totRowIndex-5,
|
totRowIndex-5,
|
||||||
|
|
|
@ -140,6 +140,61 @@ test('Can make column calculations', function() {
|
||||||
deepEqual(result2, 2781, 'columnCalc max');
|
deepEqual(result2, 2781, 'columnCalc max');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Can make column calculations with formated results', function() {
|
||||||
|
// setup
|
||||||
|
var colOps = tf.extension('colOps');
|
||||||
|
colOps.formatResults[2] = { suffix: ' Km' };
|
||||||
|
colOps.formatResults[4] = { suffix: ' Km' };
|
||||||
|
colOps.formatResults[6] = { suffix: ' Km' };
|
||||||
|
tf.colTypes[2] = { type: 'formatted-number', decimal: '.', thousands: ',' };
|
||||||
|
|
||||||
|
// act
|
||||||
|
colOps.calcAll();
|
||||||
|
|
||||||
|
// assert
|
||||||
|
deepEqual(id('mean1').innerHTML, '1,416 Km', 'Formatted mean result');
|
||||||
|
deepEqual(id('min1').innerHTML, '286 Km', 'Formatted min result');
|
||||||
|
deepEqual(id('max1').innerHTML, '2,781 Km', 'Formatted max result');
|
||||||
|
|
||||||
|
colOps.formatResults[2] = undefined;
|
||||||
|
colOps.formatResults[4] = undefined;
|
||||||
|
colOps.formatResults[6] = undefined;
|
||||||
|
tf.colTypes[2] = undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Can configure result format', function() {
|
||||||
|
// setup
|
||||||
|
var colOps = tf.extension('colOps');
|
||||||
|
var format = { prefix: '$', suffix: '/item' };
|
||||||
|
|
||||||
|
// act
|
||||||
|
var format = colOps.configureFormat(2, format);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
deepEqual(format.prefix, '$', 'prefix');
|
||||||
|
deepEqual(format.suffix, '/item', 'suffix');
|
||||||
|
deepEqual(format.decimal, '', 'decimal separator');
|
||||||
|
deepEqual(format.integerSeparator, '', 'thousands separator');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Can configure result format for formatted number column', function() {
|
||||||
|
// setup
|
||||||
|
var colOps = tf.extension('colOps');
|
||||||
|
var format = { prefix: '$', suffix: '/item' };
|
||||||
|
tf.colTypes = [null, null, null, null, null];
|
||||||
|
tf.colTypes[3] = { type: 'formatted-number', decimal: ',', thousands: '.' };
|
||||||
|
|
||||||
|
// act
|
||||||
|
var format = colOps.configureFormat(3, format);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
deepEqual(format.prefix, '$', 'prefix');
|
||||||
|
deepEqual(format.suffix, '/item', 'suffix');
|
||||||
|
deepEqual(format.decimal, ',', 'decimal separator');
|
||||||
|
deepEqual(format.integerSeparator, '.', 'thousands separator');
|
||||||
|
tf.colTypes[3] = undefined;
|
||||||
|
});
|
||||||
|
|
||||||
module('Tear-down');
|
module('Tear-down');
|
||||||
test('can destroy', function() {
|
test('can destroy', function() {
|
||||||
tf.destroy();
|
tf.destroy();
|
||||||
|
|
|
@ -9,10 +9,12 @@
|
||||||
|
|
||||||
module('Sanity checks');
|
module('Sanity checks');
|
||||||
test('Column widths', function() {
|
test('Column widths', function() {
|
||||||
var cols = tf.tbl.getElementsByTagName('col');
|
var cols = tf.dom().getElementsByTagName('col');
|
||||||
deepEqual(tf instanceof TableFilter, true, 'TableFilter instanciated');
|
deepEqual(tf instanceof TableFilter, true, 'TableFilter instanciated');
|
||||||
deepEqual(cols[1].style.width, '100px', 'Expected column width');
|
deepEqual(cols[1].style.width, '100px', 'Expected column width');
|
||||||
deepEqual(cols[4].style.width, '', 'Expected column width');
|
deepEqual(cols[4].style.width, '', 'Expected column width');
|
||||||
|
deepEqual(tf.dom().style.width, '645px', 'Table width set');
|
||||||
|
deepEqual(tf.dom().style.tableLayout, 'fixed', 'Table layout fixed');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Grid layout column widths', function() {
|
test('Grid layout column widths', function() {
|
||||||
|
@ -20,14 +22,19 @@
|
||||||
tf = null;
|
tf = null;
|
||||||
tf = new TableFilter('demo', {
|
tf = new TableFilter('demo', {
|
||||||
base_path: '../dist/tablefilter/',
|
base_path: '../dist/tablefilter/',
|
||||||
col_widths: ['150px', '100px', '175px', '120px', '200px'],
|
col_widths: ['150px', '100px', '175px', '120px', null],
|
||||||
grid_layout: true,
|
grid_layout: true
|
||||||
sort: false
|
|
||||||
});
|
});
|
||||||
tf.init();
|
tf.init();
|
||||||
var cols = tf.feature('gridLayout').headTbl.getElementsByTagName('col');
|
var gridLayout = tf.feature('gridLayout');
|
||||||
|
var cols = gridLayout.headTbl.getElementsByTagName('col');
|
||||||
deepEqual(cols[0].style.width, '150px', 'Expected column width');
|
deepEqual(cols[0].style.width, '150px', 'Expected column width');
|
||||||
deepEqual(cols[4].style.width, '200px', 'Expected column width');
|
deepEqual(cols[3].style.width, '120px', 'Expected column width');
|
||||||
|
deepEqual(
|
||||||
|
tf.dom().style.width === gridLayout.headTbl.style.width,
|
||||||
|
true,
|
||||||
|
'Content and headers table have same width'
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
})(window, TableFilter);
|
})(window, TableFilter);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue