mirror of
https://github.com/koalyptus/TableFilter.git
synced 2024-05-29 12:04:06 +02:00
Compare commits
405 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 |
|
@ -13,8 +13,8 @@
|
|||
"array-bracket-spacing": 2,
|
||||
"keyword-spacing": ["error", { "after": true, "before": true }],
|
||||
"max-depth": [2, 7],
|
||||
"max-statements": [2, 131],
|
||||
"complexity": [2, 41],
|
||||
"max-statements": [2, 133],
|
||||
"complexity": [2, 45],
|
||||
"no-unused-vars": 2,
|
||||
"no-eval": 2,
|
||||
"no-underscore-dangle": 0,
|
||||
|
|
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/
|
39
.travis.yml
39
.travis.yml
|
@ -7,22 +7,47 @@ before_script:
|
|||
script:
|
||||
- npm test
|
||||
- npm run codecov
|
||||
- npm run deploy
|
||||
- npm run build:all
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- /^greenkeeper/.*$/
|
||||
- gh-pages
|
||||
before_deploy:
|
||||
- git config --global user.email "maxgug@hotmail.com"
|
||||
- git config --global user.name "koalyptus"
|
||||
- export GIT_TAG=$(node -p -e "require('./package.json').version")
|
||||
- export GIT_TAG=$(git describe --tags --abbrev=0)
|
||||
- echo -n $GIT_TAG
|
||||
- git tag $GIT_TAG -am "Generated tag from TravisCI build $TRAVIS_BUILD_NUMBER"
|
||||
- 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
|
||||
api_key: $GITHUB_OAUTH_ACCESS_TOKEN
|
||||
skip_cleanup: true
|
||||
- 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:
|
||||
global:
|
||||
- secure: A1G8GvJkV0rjy7XCTVdOpTHy3xaoSZZAbMWhI+ikrqBqd8mRz+sB71FhRusouTcYdsT5VfF9Io2doS8LKAeP0TNC34Pp0uvjtsvarzn8a/oNEOuqR3Ub0ws2bmbZIZc+wOpgErKOj1H1QSJAUpd6ZjIuEAbOVXlhGBJz3zUCmcpRDh32CpFKC62oFWeGlvttxPciLLzBfKgkVKEGhPtdGP/xCHL1MCQptYVHZiXwWsaIQ5wHFO6KCVlRrPgdfOL+Yce3mT02iXH6ZjW6U6zA6vYQVQZVD873AkU5RmirYblW+jW1wdvu4UXI71lSH6Z3uXRVnrw1b0TsLVTjP9ZUbCtkTHtLbxYzeDjEukxKoCjpAppIhOtaNIxrdA8oKJAabQYp5X+QK6lkosy0zdT5u2B1+g8unZhsf0y//7lgLUe04iQ7sc1Q6AHiiEGtByaXg4BHNW53bUfKgNnbV4+IbXf8rz5wWOxL2/yWAU/GoiszjqRQfajAXCpSf6SyMjXjhhvQdeFn+Cz6FwdtaxH+tOIY0Hq9Gqy1xrLIkv/httd3O+AbhLrU1c/M0MwlFQue7GeJb7ZyF3KsK7bXvoz2dEqvzHd98NZXiQEqFXCIs77uVh4eZMoYrbEyrkOAgkUZNQYhHh9fuvfynJ/zgUvyA0v3GUvBebq3ybYKD/vqX7s=
|
||||
|
|
|
@ -123,8 +123,6 @@ In general, we follow the "fork-and-pull" Git workflow.
|
|||
NOTE: Be sure to merge the latest from "upstream" before making a pull request!
|
||||
|
||||
## Donations
|
||||
To support this project simply locate the `Donate` button in the [project's
|
||||
website](http://koalyptus.github.io/TableFilter/)
|
||||
which points to PayPal.
|
||||
Thanks to all those who supported this project in the past and to those who will
|
||||
Support this project by donating [here](http://www.tablefilter.com/donate.html).
|
||||
Thanks to all those who supported this project in the past and those who will
|
||||
in the future!
|
||||
|
|
126
Gruntfile.js
126
Gruntfile.js
|
@ -4,7 +4,6 @@ module.exports = function (grunt) {
|
|||
var testDir = 'test';
|
||||
var testHost = 'http://localhost:8000/';
|
||||
var pkg = grunt.file.readJSON('package.json');
|
||||
var repo = 'github.com/koalyptus/TableFilter';
|
||||
|
||||
grunt.initConfig({
|
||||
|
||||
|
@ -14,7 +13,7 @@ module.exports = function (grunt) {
|
|||
coverage: {
|
||||
disposeCollector: true,
|
||||
src: ['dist/tablefilter/*.js'],
|
||||
instrumentedFiles: 'temp/',
|
||||
instrumentedFiles: 'report/temp/',
|
||||
htmlReport: 'report/coverage',
|
||||
coberturaReport: 'report/',
|
||||
lcovReport: 'report/',
|
||||
|
@ -145,78 +144,7 @@ module.exports = function (grunt) {
|
|||
'build-css': {
|
||||
command: 'npm run build: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-contrib-copy');
|
||||
|
@ -226,7 +154,6 @@ module.exports = function (grunt) {
|
|||
grunt.loadNpmTasks('grunt-contrib-connect');
|
||||
grunt.loadNpmTasks('grunt-shell');
|
||||
grunt.loadNpmTasks('grunt-qunit-istanbul');
|
||||
grunt.loadNpmTasks('grunt-gh-pages');
|
||||
|
||||
grunt.registerTask('eslint', ['shell:eslint']);
|
||||
grunt.registerTask('esdoc', ['shell:esdoc']);
|
||||
|
@ -253,15 +180,9 @@ module.exports = function (grunt) {
|
|||
// Tests with coverage
|
||||
grunt.registerTask('test', ['build-test', 'connect', 'qunit:all']);
|
||||
|
||||
// Publish to gh-pages
|
||||
grunt.registerTask('publish', 'Publish from CLI', [
|
||||
'build', 'build-demos', 'esdoc', 'gh-pages:publish-lib',
|
||||
'gh-pages:publish-readme', 'gh-pages:publish-docs'
|
||||
]);
|
||||
|
||||
// Deploy to gh-pages
|
||||
grunt.registerTask('deploy', 'Publish from Travis', [
|
||||
'build', 'esdoc', 'check-deploy'
|
||||
// Build all for deployment from travis
|
||||
grunt.registerTask('build-all', 'Prepare for deployment', [
|
||||
'build', 'build-demos', 'esdoc'
|
||||
]);
|
||||
|
||||
// Custom task running QUnit tests for specified files.
|
||||
|
@ -328,43 +249,4 @@ module.exports = function (grunt) {
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
[![Build Status](https://api.travis-ci.org/koalyptus/TableFilter.svg?branch=master)](https://travis-ci.org/koalyptus/TableFilter)
|
||||
[![Document](https://koalyptus.github.io/TableFilter/docs/badge.svg)](https://koalyptus.github.io/TableFilter/docs/source.html)
|
||||
[![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)
|
||||
[![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
|
||||
|
||||
|
@ -23,7 +24,7 @@ users to filter and limit the data displayed within a long table. By default, th
|
|||
* Attach to an existing HTML table
|
||||
* Integration with any server-side technology as this is a pure client-side
|
||||
solution
|
||||
* Exhaustive documentation and poweful API
|
||||
* Exhaustive documentation and powerful API
|
||||
|
||||
## Getting started
|
||||
* Clone the repo using Git:
|
||||
|
@ -133,7 +134,7 @@ to view the coverage report(s), open the `index.html` under the
|
|||
[online](https://codecov.io/gh/koalyptus/TableFilter).
|
||||
|
||||
## 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:
|
||||
```shell
|
||||
npm run build:demos
|
||||
|
@ -150,7 +151,7 @@ http://localhost:8080/demos/
|
|||
## Documentation
|
||||
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
|
||||
options you are using are still supported: [Obsolete](https://github.com/koalyptus/TableFilter/wiki/Obsolete)
|
||||
|
|
6
dist/starter.html
vendored
6
dist/starter.html
vendored
|
@ -1,10 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>tablefilter v0.6.25 - Starter</title>
|
||||
<title>tablefilter v0.7.3 - Starter</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>tablefilter v0.6.25</h1>
|
||||
<h1>tablefilter v0.7.3</h1>
|
||||
|
||||
|
||||
|
||||
|
@ -479,7 +479,7 @@
|
|||
},
|
||||
col_widths: [
|
||||
'150px', '100px', '100px',
|
||||
'70px', '70px', '70px',
|
||||
'100px', '100px', '100px',
|
||||
'70px', '60px', '60px'
|
||||
],
|
||||
extensions:[{ name: 'sort' }]
|
||||
|
|
2
dist/tablefilter/style/tablefilter.css
vendored
2
dist/tablefilter/style/tablefilter.css
vendored
File diff suppressed because one or more lines are too long
3
dist/tablefilter/tablefilter.js
vendored
3
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
12536
package-lock.json
generated
12536
package-lock.json
generated
File diff suppressed because it is too large
Load diff
45
package.json
45
package.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "tablefilter",
|
||||
"version": "0.6.28",
|
||||
"version": "0.7.3",
|
||||
"description": "A Javascript library making HTML tables filterable and a bit more",
|
||||
"license": "MIT",
|
||||
"author": {
|
||||
|
@ -33,46 +33,47 @@
|
|||
"codecov": "./node_modules/.bin/codecov",
|
||||
"esdoc": "esdoc",
|
||||
"dist": "grunt",
|
||||
"deploy": "grunt deploy",
|
||||
"build:all": "grunt build-all",
|
||||
"start": "npm run server"
|
||||
},
|
||||
"publishConfig": {
|
||||
"tag": "next"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.24.1",
|
||||
"babel-eslint": "8.2.3",
|
||||
"babel-loader": "^7.0.0",
|
||||
"babel-plugin-transform-es2015-classes": "^6.24.1",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"clean-webpack-plugin": "^0.1.16",
|
||||
"codecov": "3.0.0",
|
||||
"@babel/core": "7.10.0",
|
||||
"@babel/preset-env": "7.10.0",
|
||||
"babel-eslint": "10.1.0",
|
||||
"babel-loader": "^8.0.2",
|
||||
"babel-preset-env": "1.7.0",
|
||||
"clean-webpack-plugin": "^3.0.0",
|
||||
"codecov": "3.7.1",
|
||||
"diacritics": "1.3.0",
|
||||
"esdoc": "1.0.4",
|
||||
"esdoc": "1.1.0",
|
||||
"esdoc-standard-plugin": "1.0.0",
|
||||
"eslint": "4.19.1",
|
||||
"eslint": "6.5.0",
|
||||
"format-number": "3.0.0",
|
||||
"grunt": "^1.0.1",
|
||||
"grunt-cli": "1.2.0",
|
||||
"grunt-contrib-clean": "^1.1.0",
|
||||
"grunt-contrib-connect": "^1.0.2",
|
||||
"grunt-cli": "1.3.2",
|
||||
"grunt-contrib-clean": "^2.0.0",
|
||||
"grunt-contrib-connect": "^2.0.0",
|
||||
"grunt-contrib-copy": "^1.0.0",
|
||||
"grunt-contrib-watch": "^1.0.0",
|
||||
"grunt-gh-pages": "^2.0.0",
|
||||
"grunt-qunit-istanbul": "1.0.0",
|
||||
"grunt-shell": "2.1.0",
|
||||
"grunt-qunit-istanbul": "1.1.0",
|
||||
"grunt-shell": "3.0.0",
|
||||
"grunt-string-replace": "^1.3.1",
|
||||
"isparta-loader": "2.0.0",
|
||||
"script-loader": "^0.7.0",
|
||||
"string-replace-webpack-plugin": "^0.1.3",
|
||||
"stylus": "^0.54.5",
|
||||
"sugar-date": "2.0.4",
|
||||
"webpack": "^4.0.1",
|
||||
"webpack-cli": "^2.0.10",
|
||||
"webpack-dev-server": "^3.0.0"
|
||||
"sugar-date": "2.0.6",
|
||||
"uglifyjs-webpack-plugin": "2.2.0",
|
||||
"webpack": "^4.38.0",
|
||||
"webpack-cli": "^3.0.8",
|
||||
"webpack-dev-server": "^3.1.11"
|
||||
},
|
||||
"dependencies": {},
|
||||
"bugs": {
|
||||
"url": "https://github.com/koalyptus/TableFilter/issues"
|
||||
},
|
||||
"homepage": "http://koalyptus.github.io/TableFilter"
|
||||
"homepage": "https://www.tablefilter.com"
|
||||
}
|
||||
|
|
88
src/const.js
88
src/const.js
|
@ -1,19 +1,3 @@
|
|||
import {DateType} from './modules/dateType';
|
||||
import {Help} from './modules/help';
|
||||
import {State} from './modules/state';
|
||||
import {GridLayout} from './modules/gridLayout';
|
||||
import {Loader} from './modules/loader';
|
||||
import {HighlightKeyword} from './modules/highlightKeywords';
|
||||
import {PopupFilter} from './modules/popupFilter';
|
||||
import {MarkActiveColumns} from './modules/markActiveColumns';
|
||||
import {RowsCounter} from './modules/rowsCounter';
|
||||
import {StatusBar} from './modules/statusBar';
|
||||
import {ClearButton} from './modules/clearButton';
|
||||
import {AlternateRows} from './modules/alternateRows';
|
||||
import {NoResults} from './modules/noResults';
|
||||
import {Paging} from './modules/paging';
|
||||
import {Toolbar} from './modules/toolbar';
|
||||
|
||||
/**
|
||||
* Filter types
|
||||
*/
|
||||
|
@ -132,75 +116,3 @@ export const IP_ADDRESS = 'ipaddress';
|
|||
* @type {Number}
|
||||
*/
|
||||
export const AUTO_FILTER_DELAY = 750;
|
||||
|
||||
/**
|
||||
* TableFilter features definitions
|
||||
* @type {Object}
|
||||
*/
|
||||
export const FEATURES = {
|
||||
dateType: {
|
||||
class: DateType,
|
||||
name: 'dateType'
|
||||
},
|
||||
help: {
|
||||
class: Help,
|
||||
name: 'help',
|
||||
enforce: true
|
||||
},
|
||||
state: {
|
||||
class: State,
|
||||
name: 'state'
|
||||
},
|
||||
markActiveColumns: {
|
||||
class: MarkActiveColumns,
|
||||
name: 'markActiveColumns'
|
||||
},
|
||||
gridLayout: {
|
||||
class: GridLayout,
|
||||
name: 'gridLayout'
|
||||
},
|
||||
loader: {
|
||||
class: Loader,
|
||||
name: 'loader'
|
||||
},
|
||||
highlightKeyword: {
|
||||
class: HighlightKeyword,
|
||||
name: 'highlightKeyword',
|
||||
property: 'highlightKeywords'
|
||||
},
|
||||
popupFilter: {
|
||||
class: PopupFilter,
|
||||
name: 'popupFilter',
|
||||
property: 'popupFilters'
|
||||
},
|
||||
rowsCounter: {
|
||||
class: RowsCounter,
|
||||
name: 'rowsCounter'
|
||||
},
|
||||
statusBar: {
|
||||
class: StatusBar,
|
||||
name: 'statusBar'
|
||||
},
|
||||
clearButton: {
|
||||
class: ClearButton,
|
||||
name: 'clearButton',
|
||||
property: 'btnReset'
|
||||
},
|
||||
alternateRows: {
|
||||
class: AlternateRows,
|
||||
name: 'alternateRows'
|
||||
},
|
||||
noResults: {
|
||||
class: NoResults,
|
||||
name: 'noResults'
|
||||
},
|
||||
paging: {
|
||||
class: Paging,
|
||||
name: 'paging'
|
||||
},
|
||||
toolbar: {
|
||||
class: Toolbar,
|
||||
name: 'toolbar',
|
||||
enforce: true
|
||||
}
|
||||
};
|
||||
|
|
|
@ -36,7 +36,7 @@ export const getFirstTextNode = (node) => {
|
|||
|
||||
/**
|
||||
* 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
|
||||
* items, the attribute name and its value ['id','myId']
|
||||
* @return {Object} created element
|
||||
|
|
13
src/event.js
13
src/event.js
|
@ -109,3 +109,16 @@ export const keyCode = (evt) => {
|
|||
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];
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ export default class AdapterEzEditTable extends Feature {
|
|||
* @param {Object} cfg Configuration options for ezEditTable library
|
||||
*/
|
||||
constructor(tf, cfg) {
|
||||
super(tf, cfg.name);
|
||||
super(tf, AdapterEzEditTable);
|
||||
|
||||
/**
|
||||
* Module description
|
||||
|
@ -505,3 +505,5 @@ export default class AdapterEzEditTable extends Feature {
|
|||
this.initialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
AdapterEzEditTable.meta = {altName: 'advancedGrid'};
|
||||
|
|
|
@ -5,6 +5,7 @@ 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 = [
|
||||
'after-filtering',
|
||||
|
@ -32,7 +33,7 @@ export default class ColOps extends Feature {
|
|||
* @param {Object} opts Configuration object
|
||||
*/
|
||||
constructor(tf, opts) {
|
||||
super(tf, opts.name);
|
||||
super(tf, ColOps);
|
||||
|
||||
/**
|
||||
* Callback fired before columns operations start
|
||||
|
@ -115,7 +116,7 @@ export default class ColOps extends Feature {
|
|||
return;
|
||||
}
|
||||
// subscribe to events
|
||||
this.emitter.on(EVENTS, () => this.calcAll());
|
||||
this.emitter.on(EVENTS, bound(this.calcAll, this));
|
||||
|
||||
this.calcAll();
|
||||
|
||||
|
@ -471,7 +472,7 @@ export default class ColOps extends Feature {
|
|||
return;
|
||||
}
|
||||
// unsubscribe to events
|
||||
this.emitter.off(EVENTS, () => this.calcAll());
|
||||
this.emitter.off(EVENTS, bound(this.calcAll, this));
|
||||
|
||||
this.initialized = false;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ export default class ColsVisibility extends Feature {
|
|||
* @param {Object} Configuration object
|
||||
*/
|
||||
constructor(tf, f) {
|
||||
super(tf, f.name);
|
||||
super(tf, ColsVisibility);
|
||||
|
||||
// Configuration object
|
||||
let cfg = this.config;
|
||||
|
@ -710,7 +710,7 @@ export default class ColsVisibility extends Feature {
|
|||
}
|
||||
|
||||
_hideCol(tbl, colIdx, hide) {
|
||||
let colElms = tag(this.tf.dom(), 'col');
|
||||
let colElms = tag(tbl, 'col');
|
||||
if (colElms.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ export default class FiltersVisibility extends Feature {
|
|||
* @param {Object} Configuration object
|
||||
*/
|
||||
constructor(tf, f) {
|
||||
super(tf, f.name);
|
||||
super(tf, FiltersVisibility);
|
||||
|
||||
/**
|
||||
* Module name
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {Feature} from '../../feature';
|
||||
import {isUndef, isObj, EMPTY_FN} from '../../types';
|
||||
import {createElm, elm, getText, tag} from '../../dom';
|
||||
import {addEvt} from '../../event';
|
||||
import {createElm, elm, tag} from '../../dom';
|
||||
import {addEvt, bound} from '../../event';
|
||||
import {parse as parseNb} from '../../number';
|
||||
import {
|
||||
NONE, CELL_TAG, HEADER_TAG, STRING, NUMBER, DATE, FORMATTED_NUMBER,
|
||||
|
@ -20,7 +20,7 @@ export default class AdapterSortableTable extends Feature {
|
|||
* @param {Object} opts Configuration object
|
||||
*/
|
||||
constructor(tf, opts) {
|
||||
super(tf, opts.name);
|
||||
super(tf, AdapterSortableTable);
|
||||
|
||||
/**
|
||||
* Module name
|
||||
|
@ -189,8 +189,7 @@ export default class AdapterSortableTable extends Feature {
|
|||
this.stt.sort(sortColAtStart[0], sortColAtStart[1]);
|
||||
}
|
||||
|
||||
this.emitter.on(['sort'],
|
||||
(tf, colIdx, desc) => this.sortByColumnIndex(colIdx, desc));
|
||||
this.emitter.on(['sort'], bound(this.sortByColumnIndexHandler, this));
|
||||
|
||||
/** @inherited */
|
||||
this.initialized = true;
|
||||
|
@ -207,6 +206,11 @@ export default class AdapterSortableTable extends Feature {
|
|||
this.stt.sort(colIdx, desc);
|
||||
}
|
||||
|
||||
/** @private */
|
||||
sortByColumnIndexHandler(tf, colIdx, desc) {
|
||||
this.sortByColumnIndex(colIdx, desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set SortableTable overrides for TableFilter integration
|
||||
*/
|
||||
|
@ -357,17 +361,17 @@ export default class AdapterSortableTable extends Feature {
|
|||
/**
|
||||
* Overrides getInnerText in order to avoid Firefox unexpected sorting
|
||||
* behaviour with untrimmed text elements
|
||||
* @param {Object} oNode DOM element
|
||||
* @param {Object} cell DOM element
|
||||
* @return {String} DOM element inner text
|
||||
*/
|
||||
SortableTable.getInnerText = function (oNode) {
|
||||
if (!oNode) {
|
||||
SortableTable.getInnerText = function (cell) {
|
||||
if (!cell) {
|
||||
return;
|
||||
}
|
||||
if (oNode.getAttribute(adpt.customKey)) {
|
||||
return oNode.getAttribute(adpt.customKey);
|
||||
if (cell.getAttribute(adpt.customKey)) {
|
||||
return cell.getAttribute(adpt.customKey);
|
||||
} else {
|
||||
return getText(oNode);
|
||||
return tf.getCellValue(cell);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -377,8 +381,8 @@ export default class AdapterSortableTable extends Feature {
|
|||
*/
|
||||
addSortType(...args) {
|
||||
// Extract the arguments
|
||||
let [id, caster, sorter] = args;
|
||||
SortableTable.prototype.addSortType(id, caster, sorter);
|
||||
let [id, caster, sorter, getRowValue] = args;
|
||||
SortableTable.prototype.addSortType(id, caster, sorter, getRowValue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -486,8 +490,7 @@ export default class AdapterSortableTable extends Feature {
|
|||
return;
|
||||
}
|
||||
let tf = this.tf;
|
||||
this.emitter.off(['sort'],
|
||||
(tf, colIdx, desc) => this.sortByColumnIndex(colIdx, desc));
|
||||
this.emitter.off(['sort'], bound(this.sortByColumnIndexHandler, this));
|
||||
this.sorted = false;
|
||||
this.stt.destroy();
|
||||
|
||||
|
@ -505,9 +508,12 @@ export default class AdapterSortableTable extends Feature {
|
|||
|
||||
}
|
||||
|
||||
AdapterSortableTable.meta = {altName: 'sort'};
|
||||
|
||||
//Converters
|
||||
function ipAddress(value) {
|
||||
let vals = value.split('.');
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
for (let x in vals) {
|
||||
let val = vals[x];
|
||||
while (3 > val.length) {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import {toCamelCase} from './string';
|
||||
|
||||
const NOT_IMPLEMENTED = 'Not implemented.';
|
||||
|
||||
|
@ -8,9 +9,11 @@ export class Feature {
|
|||
/**
|
||||
* Creates an instance of Feature
|
||||
* @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
|
||||
* @type {TableFilter}
|
||||
|
@ -18,16 +21,18 @@ export class Feature {
|
|||
this.tf = tf;
|
||||
|
||||
/**
|
||||
* Feature name
|
||||
* Feature name is the camelised class name as per TableFilter's
|
||||
* convention
|
||||
* @type {String}
|
||||
*/
|
||||
this.feature = feature;
|
||||
this.feature = cls.meta.altName || cls.meta.name
|
||||
|| toCamelCase(cls.name);
|
||||
|
||||
/**
|
||||
* TableFilter feature setting
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.enabled = tf[feature];
|
||||
this.enabled = tf[this.feature];
|
||||
|
||||
/**
|
||||
* TableFilter configuration
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import {Feature} from '../feature';
|
||||
import {addClass, removeClass} from '../dom';
|
||||
import {defaultsStr} from '../settings';
|
||||
import {bound} from '../event';
|
||||
|
||||
/**
|
||||
* Rows with alternating background color for improved readability
|
||||
|
@ -13,9 +14,10 @@ export class AlternateRows extends Feature {
|
|||
* @param {Object} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, 'alternateRows');
|
||||
super(tf, AlternateRows);
|
||||
|
||||
let config = this.config;
|
||||
|
||||
/**
|
||||
* Css class for even rows (default: 'even')
|
||||
* @type {String}
|
||||
|
@ -41,10 +43,9 @@ export class AlternateRows extends Feature {
|
|||
|
||||
// Subscribe to events
|
||||
this.emitter.on(['row-processed', 'row-paged'],
|
||||
(tf, rowIndex, arrIndex, isValid) =>
|
||||
this.processRow(rowIndex, arrIndex, isValid));
|
||||
bound(this.processRowHandler, this));
|
||||
this.emitter.on(['column-sorted', 'rows-changed'],
|
||||
() => this.processAll());
|
||||
bound(this.processAll, this));
|
||||
|
||||
/** @inherited */
|
||||
this.initialized = true;
|
||||
|
@ -116,6 +117,11 @@ export class AlternateRows extends Feature {
|
|||
removeClass(rows[idx], this.evenCss);
|
||||
}
|
||||
|
||||
/** @private */
|
||||
processRowHandler(tf, rowIndex, arrIndex, isValid) {
|
||||
this.processRow(rowIndex, arrIndex, isValid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all alternating backgrounds
|
||||
*/
|
||||
|
@ -129,10 +135,9 @@ export class AlternateRows extends Feature {
|
|||
|
||||
// Unsubscribe to events
|
||||
this.emitter.off(['row-processed', 'row-paged'],
|
||||
(tf, rowIndex, arrIndex, isValid) =>
|
||||
this.processRow(rowIndex, arrIndex, isValid));
|
||||
bound(this.processRowHandler, this));
|
||||
this.emitter.off(['column-sorted', 'rows-changed'],
|
||||
() => this.processAll());
|
||||
bound(this.processAll, this));
|
||||
|
||||
this.initialized = false;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {Feature} from '../feature';
|
||||
import {
|
||||
ignoreCase, numSortAsc, numSortDesc,
|
||||
dateSortAsc, sortNumberStr, sortDateStr
|
||||
dateSortAsc, dateSortDesc, sortNumberStr, sortDateStr
|
||||
} from '../sort';
|
||||
import {isArray, isObj, isEmpty} from '../types';
|
||||
import {NUMBER, FORMATTED_NUMBER, DATE} from '../const';
|
||||
|
@ -18,8 +18,8 @@ export class BaseDropdown extends Feature {
|
|||
* Creates an instance of BaseDropdown
|
||||
* @param {TableFilter} tf
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, 'baseDropdown');
|
||||
constructor(tf, cls) {
|
||||
super(tf, cls);
|
||||
|
||||
let f = this.config;
|
||||
|
||||
|
@ -33,7 +33,7 @@ export class BaseDropdown extends Feature {
|
|||
f.filter_options_sorter :
|
||||
null;
|
||||
|
||||
// TODO: move here all properties shared by Dropdown CheckList
|
||||
// TODO: move here all properties shared by Dropdown and CheckList
|
||||
|
||||
/**
|
||||
* Has custom options
|
||||
|
@ -72,14 +72,15 @@ export class BaseDropdown extends Feature {
|
|||
* @private
|
||||
*/
|
||||
sortOptions(colIndex, options = []) {
|
||||
let tf = this.tf;
|
||||
let {tf} = this;
|
||||
|
||||
if (tf.isCustomOptions(colIndex) || !tf.sortSlc ||
|
||||
(isArray(tf.sortSlc) && tf.sortSlc.indexOf(colIndex) === -1)) {
|
||||
return options;
|
||||
}
|
||||
|
||||
let { caseSensitive, sortNumDesc } = tf;
|
||||
let { caseSensitive, sortFilterOptionsDesc } = tf;
|
||||
let isSortDesc = sortFilterOptionsDesc.indexOf(colIndex) !== -1;
|
||||
let compareFn;
|
||||
|
||||
if (this.customSorter &&
|
||||
|
@ -89,18 +90,18 @@ export class BaseDropdown extends Feature {
|
|||
}
|
||||
else if (tf.hasType(colIndex, [NUMBER, FORMATTED_NUMBER])) {
|
||||
let decimal = tf.getDecimal(colIndex);
|
||||
let comparer = numSortAsc;
|
||||
if (sortNumDesc === true || sortNumDesc.indexOf(colIndex) !== -1) {
|
||||
comparer = numSortDesc;
|
||||
}
|
||||
let comparer = isSortDesc ? numSortDesc : numSortAsc;
|
||||
compareFn = sortNumberStr(comparer, decimal);
|
||||
}
|
||||
else if (tf.hasType(colIndex, [DATE])) {
|
||||
let locale = tf.feature('dateType').getLocale(colIndex);
|
||||
let comparer = dateSortAsc;
|
||||
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);
|
||||
|
@ -144,4 +145,16 @@ export class BaseDropdown extends Feature {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh linked filters to offer only selected options
|
||||
*/
|
||||
linkFilters() {
|
||||
let tf = this.tf;
|
||||
if (!tf.linkedFilters || !tf.activeFilterId) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.refreshAll();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ export class CheckList extends BaseDropdown {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, 'checkList');
|
||||
super(tf, CheckList);
|
||||
|
||||
let f = this.config;
|
||||
|
||||
|
@ -178,6 +178,8 @@ export class CheckList extends BaseDropdown {
|
|||
|
||||
this.emitter.on(['rows-changed'], () => this.refreshAll());
|
||||
|
||||
this.emitter.on(['after-filtering'], () => this.linkFilters());
|
||||
|
||||
/** @inherited */
|
||||
this.initialized = true;
|
||||
}
|
||||
|
@ -483,6 +485,10 @@ export class CheckList extends BaseDropdown {
|
|||
getValues(colIndex) {
|
||||
let tf = this.tf;
|
||||
let flt = tf.getFilterElement(colIndex);
|
||||
if (!flt) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let fltAttr = flt.getAttribute('value');
|
||||
let values = isEmpty(fltAttr) ? '' : fltAttr;
|
||||
//removes last operator ||
|
||||
|
@ -506,6 +512,7 @@ export class CheckList extends BaseDropdown {
|
|||
(tf, colIndex, values) => this.selectOptions(colIndex, values)
|
||||
);
|
||||
this.emitter.off(['rows-changed'], () => this.refreshAll());
|
||||
this.emitter.off(['after-filtering'], () => this.linkFilters());
|
||||
|
||||
this.initialized = false;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ export class ClearButton extends Feature {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, 'btnReset');
|
||||
super(tf, ClearButton);
|
||||
|
||||
let f = this.config.btn_reset || {};
|
||||
|
||||
|
@ -137,3 +137,6 @@ export class ClearButton extends Feature {
|
|||
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
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, 'dateType');
|
||||
super(tf, DateType);
|
||||
|
||||
/**
|
||||
* Global locale
|
||||
|
|
|
@ -19,7 +19,7 @@ export class Dropdown extends BaseDropdown {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, 'dropdown');
|
||||
super(tf, Dropdown);
|
||||
|
||||
// Configuration object
|
||||
let f = this.config;
|
||||
|
@ -137,6 +137,8 @@ export class Dropdown extends BaseDropdown {
|
|||
);
|
||||
this.emitter.on(['rows-changed'], () => this.refreshAll());
|
||||
|
||||
this.emitter.on(['after-filtering'], () => this.linkFilters());
|
||||
|
||||
/** @inherited */
|
||||
this.initialized = true;
|
||||
}
|
||||
|
@ -368,6 +370,7 @@ export class Dropdown extends BaseDropdown {
|
|||
(tf, colIndex, values) => this.selectOptions(colIndex, values)
|
||||
);
|
||||
this.emitter.off(['rows-changed'], () => this.refreshAll());
|
||||
this.emitter.off(['after-filtering'], () => this.linkFilters());
|
||||
this.initialized = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ export class GridLayout extends Feature {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, 'gridLayout');
|
||||
super(tf, GridLayout);
|
||||
|
||||
let f = this.config.grid_layout || {};
|
||||
|
||||
|
|
|
@ -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
|
||||
* @returns {Object} JSON object
|
||||
|
|
|
@ -4,12 +4,12 @@ import {addEvt, targetEvt, removeEvt} from '../event';
|
|||
import {NONE} from '../const';
|
||||
import {root} from '../root';
|
||||
import {isEmpty, isNull} from '../types';
|
||||
import {defaultsStr} from '../settings';
|
||||
import {defaultsStr, defaultsNb} from '../settings';
|
||||
import {RIGHT} from './toolbar';
|
||||
|
||||
const WIKI_URL = 'https://github.com/koalyptus/TableFilter/wiki/' +
|
||||
'4.-Filter-operators';
|
||||
const WEBSITE_URL = 'http://koalyptus.github.io/TableFilter/';
|
||||
const WEBSITE_URL = 'https://www.tablefilter.com/';
|
||||
|
||||
/**
|
||||
* Help UI component
|
||||
|
@ -21,7 +21,7 @@ export class Help extends Feature {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, 'help');
|
||||
super(tf, Help);
|
||||
|
||||
let f = this.config.help_instructions || {};
|
||||
|
||||
|
@ -92,6 +92,15 @@ export class Help extends Feature {
|
|||
*/
|
||||
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
|
||||
* @private
|
||||
|
@ -214,9 +223,21 @@ export class Help extends Feature {
|
|||
let divDisplay = this.cont.style.display;
|
||||
if (divDisplay === '' || divDisplay === NONE) {
|
||||
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);
|
||||
} else {
|
||||
this.cont.style.display = NONE;
|
||||
this.cont.style.left = '';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,3 +259,6 @@ export class Help extends Feature {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
// TODO: remove as soon as feature name is fixed
|
||||
Help.meta = {alwaysInstantiate: true};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {createText, createElm, getText} from '../dom';
|
||||
import {isArray} from '../types';
|
||||
import {isNull} from '../types';
|
||||
import {rgxEsc} from '../string';
|
||||
import {defaultsStr} from '../settings';
|
||||
|
||||
|
@ -105,7 +105,8 @@ export class HighlightKeyword {
|
|||
let n = highlightedNodes[i];
|
||||
let nodeVal = getText(n);
|
||||
|
||||
if (nodeVal.toLowerCase().indexOf(term.toLowerCase()) !== -1) {
|
||||
if (isNull(term) ||
|
||||
nodeVal.toLowerCase().indexOf(term.toLowerCase()) !== -1) {
|
||||
let parentNode = n.parentNode;
|
||||
parentNode.replaceChild(createText(nodeVal), n);
|
||||
parentNode.normalize();
|
||||
|
@ -120,15 +121,8 @@ export class HighlightKeyword {
|
|||
if (!this.tf.highlightKeywords) {
|
||||
return;
|
||||
}
|
||||
// iterate filters values to unhighlight all values
|
||||
this.tf.getFiltersValue().forEach((val) => {
|
||||
if (isArray(val)) {
|
||||
val.forEach((item) =>
|
||||
this.unhighlight(item, this.highlightCssClass));
|
||||
} else {
|
||||
this.unhighlight(val, this.highlightCssClass);
|
||||
}
|
||||
});
|
||||
|
||||
this.unhighlight(null, this.highlightCssClass);
|
||||
}
|
||||
|
||||
/** Remove feature */
|
||||
|
@ -178,3 +172,9 @@ export class HighlightKeyword {
|
|||
this.highlight(cell, term, this.highlightCssClass);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove as soon as feature name is fixed
|
||||
HighlightKeyword.meta = {
|
||||
name: 'highlightKeyword',
|
||||
altName: 'highlightKeywords'
|
||||
};
|
||||
|
|
|
@ -5,7 +5,7 @@ import {root} from '../root';
|
|||
import {NONE} from '../const';
|
||||
import {defaultsStr, defaultsFn} from '../settings';
|
||||
|
||||
const EVENTS = [
|
||||
const BEFORE_ACTION_EVENTS = [
|
||||
'before-filtering',
|
||||
'before-populating-filter',
|
||||
'before-page-change',
|
||||
|
@ -17,6 +17,18 @@ const EVENTS = [
|
|||
'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
|
||||
*
|
||||
|
@ -32,7 +44,7 @@ export class Loader extends Feature {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, 'loader');
|
||||
super(tf, Loader);
|
||||
|
||||
let f = this.config.loader || {};
|
||||
|
||||
|
@ -116,8 +128,8 @@ export class Loader extends Feature {
|
|||
this.show(NONE);
|
||||
|
||||
// Subscribe to events
|
||||
emitter.on(EVENTS, () => this.show(''));
|
||||
emitter.on(EVENTS, () => this.show(NONE));
|
||||
emitter.on(BEFORE_ACTION_EVENTS, () => this.show(''));
|
||||
emitter.on(AFTER_ACTION_EVENTS, () => this.show(NONE));
|
||||
|
||||
/** @inherited */
|
||||
this.initialized = true;
|
||||
|
@ -132,7 +144,7 @@ export class Loader extends Feature {
|
|||
return;
|
||||
}
|
||||
|
||||
let displayLoader = () => {
|
||||
function displayLoader() {
|
||||
if (!this.cont) {
|
||||
return;
|
||||
}
|
||||
|
@ -146,7 +158,7 @@ export class Loader extends Feature {
|
|||
};
|
||||
|
||||
let t = p === NONE ? this.closeDelay : 1;
|
||||
root.setTimeout(displayLoader, t);
|
||||
root.setTimeout(displayLoader.bind(this), t);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -163,8 +175,8 @@ export class Loader extends Feature {
|
|||
this.cont = null;
|
||||
|
||||
// Unsubscribe to events
|
||||
emitter.off(EVENTS, () => this.show(''));
|
||||
emitter.off(EVENTS, () => this.show(NONE));
|
||||
emitter.off(BEFORE_ACTION_EVENTS, () => this.show(''));
|
||||
emitter.off(AFTER_ACTION_EVENTS, () => this.show(NONE));
|
||||
|
||||
this.initialized = false;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ export class MarkActiveColumns extends Feature {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, 'markActiveColumns');
|
||||
super(tf, MarkActiveColumns);
|
||||
|
||||
let config = this.config.mark_active_columns || {};
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ export class NoResults extends Feature {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, 'noResults');
|
||||
super(tf, NoResults);
|
||||
|
||||
//configuration object
|
||||
let f = this.config.no_results_message || {};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {Feature} from '../feature';
|
||||
import {createElm, createOpt, createText, elm, removeElm} from '../dom';
|
||||
import {isArray, isNull, EMPTY_FN} from '../types';
|
||||
import {addEvt, removeEvt, isKeyPressed} from '../event';
|
||||
import {addEvt, removeEvt, isKeyPressed, bound} from '../event';
|
||||
import {INPUT, SELECT, NONE, ENTER_KEY} from '../const';
|
||||
import {
|
||||
defaultsStr, defaultsNb, defaultsBool, defaultsArr, defaultsFn
|
||||
|
@ -21,7 +21,7 @@ export class Paging extends Feature {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, 'paging');
|
||||
super(tf, Paging);
|
||||
|
||||
// Configuration object
|
||||
let f = this.config.paging || {};
|
||||
|
@ -483,11 +483,10 @@ export class Paging extends Feature {
|
|||
this.setPagingInfo(tf.validRowsIndex);
|
||||
}
|
||||
|
||||
this.emitter.on(['after-filtering'], () => this.resetPagingInfo());
|
||||
this.emitter.on(['change-page'],
|
||||
(tf, pageNumber) => this.setPage(pageNumber));
|
||||
this.emitter.on(['after-filtering'], bound(this.resetPagingInfo, this));
|
||||
this.emitter.on(['change-page'], bound(this.changePageHandler, this));
|
||||
this.emitter.on(['change-page-results'],
|
||||
(tf, pageLength) => this.changeResultsPerPage(pageLength));
|
||||
bound(this.changePageResultsHandler, this));
|
||||
|
||||
/** @inherited */
|
||||
this.initialized = true;
|
||||
|
@ -830,6 +829,16 @@ export class Paging extends Feature {
|
|||
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
|
||||
*/
|
||||
|
@ -893,11 +902,11 @@ export class Paging extends Feature {
|
|||
this.removeResultsPerPage();
|
||||
}
|
||||
|
||||
this.emitter.off(['after-filtering'], () => this.resetPagingInfo());
|
||||
this.emitter.off(['change-page'],
|
||||
(tf, pageNumber) => this.setPage(pageNumber));
|
||||
this.emitter.off(['after-filtering'],
|
||||
bound(this.resetPagingInfo, this));
|
||||
this.emitter.off(['change-page'], bound(this.changePageHandler, this));
|
||||
this.emitter.off(['change-page-results'],
|
||||
(tf, pageLength) => this.changeResultsPerPage(pageLength));
|
||||
bound(this.changePageResultsHandler, this));
|
||||
|
||||
this.pageSlc = null;
|
||||
this.nbPages = 0;
|
||||
|
|
|
@ -19,7 +19,7 @@ export class PopupFilter extends Feature {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, 'popupFilters');
|
||||
super(tf, PopupFilter);
|
||||
|
||||
// Configuration object
|
||||
let f = this.config.popup_filters || {};
|
||||
|
@ -456,3 +456,6 @@ export class PopupFilter extends Feature {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
// TODO: remove as soon as feature name is fixed
|
||||
PopupFilter.meta = {altName: 'popupFilters'};
|
||||
|
|
|
@ -17,7 +17,7 @@ export class RowsCounter extends Feature {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, 'rowsCounter');
|
||||
super(tf, RowsCounter);
|
||||
|
||||
// TableFilter configuration
|
||||
let f = this.config.rows_counter || {};
|
||||
|
|
|
@ -19,7 +19,7 @@ export class State extends Feature {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, 'state');
|
||||
super(tf, State);
|
||||
|
||||
let cfg = this.config.state || {};
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ export class StatusBar extends Feature {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, 'statusBar');
|
||||
super(tf, StatusBar);
|
||||
|
||||
// Configuration object
|
||||
let f = this.config.status_bar || {};
|
||||
|
|
|
@ -29,7 +29,7 @@ export class Toolbar extends Feature {
|
|||
* @memberof Toolbar
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, 'toolbar');
|
||||
super(tf, Toolbar);
|
||||
|
||||
// Configuration object
|
||||
let f = this.config.toolbar || {};
|
||||
|
@ -219,3 +219,6 @@ export class Toolbar extends Feature {
|
|||
this.initialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove as soon as feature name is fixed
|
||||
Toolbar.meta = {alwaysInstantiate: true};
|
||||
|
|
|
@ -74,3 +74,39 @@ export const contains = (term, data, exactMatch = false, caseSensitive = false,
|
|||
}
|
||||
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();
|
||||
};
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
import {addEvt, cancelEvt, stopEvt, targetEvt, isKeyPressed} from './event';
|
||||
import {
|
||||
addClass, createElm, createOpt, elm, getText, getFirstTextNode,
|
||||
removeClass, tag
|
||||
addClass, createElm, elm, getText, getFirstTextNode, removeClass, tag
|
||||
} from './dom';
|
||||
import {contains, matchCase, rgxEsc, trim} from './string';
|
||||
import {isEmpty as isEmptyString} from './string';
|
||||
import {contains, matchCase, rgxEsc, trim, toCamelCase, uuid} from './string';
|
||||
import {
|
||||
isArray, isEmpty, isFn, isNumber, isObj, isString, isUndef, EMPTY_FN,
|
||||
isBoolean
|
||||
|
@ -19,16 +17,36 @@ import {root} from './root';
|
|||
import {Emitter} from './emitter';
|
||||
import {Dropdown} from './modules/dropdown';
|
||||
import {CheckList} from './modules/checkList';
|
||||
import {DateType} from './modules/dateType';
|
||||
import {Help} from './modules/help';
|
||||
import {State} from './modules/state';
|
||||
import {GridLayout} from './modules/gridLayout';
|
||||
import {Loader} from './modules/loader';
|
||||
import {HighlightKeyword} from './modules/highlightKeywords';
|
||||
import {PopupFilter} from './modules/popupFilter';
|
||||
import {MarkActiveColumns} from './modules/markActiveColumns';
|
||||
import {RowsCounter} from './modules/rowsCounter';
|
||||
import {StatusBar} from './modules/statusBar';
|
||||
import {ClearButton} from './modules/clearButton';
|
||||
import {AlternateRows} from './modules/alternateRows';
|
||||
import {NoResults} from './modules/noResults';
|
||||
import {Paging} from './modules/paging';
|
||||
import {Toolbar} from './modules/toolbar';
|
||||
|
||||
import {
|
||||
INPUT, SELECT, MULTIPLE, CHECKLIST, NONE,
|
||||
ENTER_KEY, TAB_KEY, ESC_KEY, UP_ARROW_KEY, DOWN_ARROW_KEY,
|
||||
CELL_TAG, AUTO_FILTER_DELAY, NUMBER, DATE, FORMATTED_NUMBER,
|
||||
FEATURES
|
||||
CELL_TAG, AUTO_FILTER_DELAY, NUMBER, DATE, FORMATTED_NUMBER
|
||||
} from './const';
|
||||
|
||||
let doc = root.document;
|
||||
|
||||
const FEATURES = [
|
||||
DateType, Help, State, MarkActiveColumns, GridLayout, Loader,
|
||||
HighlightKeyword, PopupFilter, RowsCounter, StatusBar, ClearButton,
|
||||
AlternateRows, NoResults, Paging, Toolbar
|
||||
];
|
||||
|
||||
/**
|
||||
* Makes HTML tables filterable and a bit more :)
|
||||
*
|
||||
|
@ -124,7 +142,7 @@ export class TableFilter {
|
|||
args.forEach((arg) => {
|
||||
if (typeof arg === 'object' && arg.nodeName === 'TABLE') {
|
||||
this.tbl = arg;
|
||||
this.id = arg.id || `tf_${new Date().getTime()}_`;
|
||||
this.id = arg.id || `tf_${uuid()}`;
|
||||
this.tbl.id = this.id;
|
||||
} else if (isString(arg)) {
|
||||
this.id = arg;
|
||||
|
@ -319,7 +337,7 @@ export class TableFilter {
|
|||
this.onAfterFilter = defaultsFn(f.on_after_filter, EMPTY_FN);
|
||||
|
||||
/**
|
||||
* Enable/disable case sensitivity filtering
|
||||
* Enable/disable case sensitivity for filtering, default false
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.caseSensitive = Boolean(f.case_sensitive);
|
||||
|
@ -401,8 +419,7 @@ export class TableFilter {
|
|||
* Enable/disable single filter mode
|
||||
* @type {Boolean|Object}
|
||||
*/
|
||||
this.singleFlt = isObj(f.single_filter) ||
|
||||
Boolean(f.single_filter);
|
||||
this.singleFlt = isObj(f.single_filter) || Boolean(f.single_filter);
|
||||
|
||||
/**
|
||||
* Specify columns to be excluded from single filter search, by default
|
||||
|
@ -476,7 +493,9 @@ export class TableFilter {
|
|||
* Text for clear option in drop-down filter types (1st option)
|
||||
* @type {String|Array}
|
||||
*/
|
||||
this.clearFilterText = defaultsStr(f.clear_filter_text, 'Clear');
|
||||
this.clearFilterText = isArray(f.clear_filter_text)
|
||||
? f.clear_filter_text
|
||||
: defaultsStr(f.clear_filter_text, 'Clear');
|
||||
|
||||
/**
|
||||
* Indicate whether empty option is enabled in drop-down filter types
|
||||
|
@ -515,38 +534,24 @@ export class TableFilter {
|
|||
* by default globally or on a column basis
|
||||
* @type {Boolean|Array}
|
||||
*/
|
||||
this.sortSlc = isUndef(f.sort_select) ? true :
|
||||
isArray(f.sort_select) ? f.sort_select : Boolean(f.sort_select);
|
||||
this.sortSlc = isUndef(f.sort_select)
|
||||
? true
|
||||
: defaultsArr(f.sort_select, Boolean(f.sort_select));
|
||||
|
||||
/**
|
||||
* Indicate whether options in drop-down filter types are sorted in a
|
||||
* ascending numeric manner
|
||||
* @type {Boolean}
|
||||
* @private
|
||||
*/
|
||||
this.isSortNumAsc = Boolean(f.sort_num_asc);
|
||||
|
||||
/**
|
||||
* List of columns implementing options sorting in a ascending numeric
|
||||
* manner
|
||||
* List of columns implementing filter options sorting in ascending
|
||||
* manner based on column data type
|
||||
* @type {Array}
|
||||
*/
|
||||
this.sortNumAsc = this.isSortNumAsc ? f.sort_num_asc : [];
|
||||
this.sortFilterOptionsAsc = defaultsArr(f.sort_filter_options_asc, []);
|
||||
|
||||
/**
|
||||
* Indicate whether options in drop-down filter types are sorted in a
|
||||
* descending numeric manner
|
||||
* @type {Boolean}
|
||||
* @private
|
||||
*/
|
||||
this.isSortNumDesc = Boolean(f.sort_num_desc);
|
||||
|
||||
/**
|
||||
* List of columns implementing options sorting in a descending numeric
|
||||
* manner
|
||||
* List of columns implementing filter options sorting in descending
|
||||
* manner based on column data type
|
||||
* @type {Array}
|
||||
*/
|
||||
this.sortNumDesc = this.isSortNumDesc ? f.sort_num_desc : [];
|
||||
this.sortFilterOptionsDesc =
|
||||
defaultsArr(f.sort_filter_options_desc, []);
|
||||
|
||||
/**
|
||||
* Indicate whether drop-down filter types are populated on demand at
|
||||
|
@ -859,6 +864,9 @@ export class TableFilter {
|
|||
*/
|
||||
this.prfxResponsive = 'resp';
|
||||
|
||||
/** @private */
|
||||
this.stickyCssClass = 'sticky';
|
||||
|
||||
/*** extensions ***/
|
||||
/**
|
||||
* List of loaded extensions
|
||||
|
@ -907,6 +915,12 @@ export class TableFilter {
|
|||
*/
|
||||
this.toolbar = isObj(f.toolbar) || Boolean(f.toolbar);
|
||||
|
||||
/**
|
||||
* Enable sticky headers
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.stickyHeaders = Boolean(f.sticky_headers);
|
||||
|
||||
/**
|
||||
* Features registry
|
||||
* @private
|
||||
|
@ -919,10 +933,8 @@ export class TableFilter {
|
|||
*/
|
||||
this.ExtRegistry = {};
|
||||
|
||||
// conditionally instantiate required features
|
||||
this.instantiateFeatures(
|
||||
Object.keys(FEATURES).map((item) => FEATURES[item])
|
||||
);
|
||||
// instantiate features if needed
|
||||
this.instantiateFeatures(FEATURES);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -942,20 +954,16 @@ export class TableFilter {
|
|||
//loads theme
|
||||
this.loadThemes();
|
||||
|
||||
const { dateType, help, state, markActiveColumns, gridLayout, loader,
|
||||
highlightKeyword, popupFilter, rowsCounter, statusBar, clearButton,
|
||||
alternateRows, noResults, paging, toolbar } = FEATURES;
|
||||
|
||||
//explicitly initialise features in given order
|
||||
this.initFeatures([
|
||||
dateType,
|
||||
help,
|
||||
state,
|
||||
markActiveColumns,
|
||||
gridLayout,
|
||||
loader,
|
||||
highlightKeyword,
|
||||
popupFilter
|
||||
DateType,
|
||||
Help,
|
||||
State,
|
||||
MarkActiveColumns,
|
||||
GridLayout,
|
||||
Loader,
|
||||
HighlightKeyword,
|
||||
PopupFilter
|
||||
]);
|
||||
|
||||
//filters grid is not generated
|
||||
|
@ -1028,13 +1036,13 @@ export class TableFilter {
|
|||
}
|
||||
|
||||
this.initFeatures([
|
||||
rowsCounter,
|
||||
statusBar,
|
||||
clearButton,
|
||||
alternateRows,
|
||||
noResults,
|
||||
paging,
|
||||
toolbar
|
||||
RowsCounter,
|
||||
StatusBar,
|
||||
ClearButton,
|
||||
AlternateRows,
|
||||
NoResults,
|
||||
Paging,
|
||||
Toolbar
|
||||
]);
|
||||
|
||||
this.setColWidths();
|
||||
|
@ -1048,16 +1056,14 @@ export class TableFilter {
|
|||
if (this.colWidths.length > 0) {
|
||||
this.setFixedLayout();
|
||||
}
|
||||
if (this.stickyHeaders && this.dom().tHead) {
|
||||
addClass(this.dom(), this.stickyCssClass);
|
||||
}
|
||||
}
|
||||
|
||||
/* Load extensions */
|
||||
this.initExtensions();
|
||||
|
||||
// Subscribe to events
|
||||
if (this.linkedFilters) {
|
||||
this.emitter.on(['after-filtering'], () => this.linkFilters());
|
||||
}
|
||||
|
||||
this.initialized = true;
|
||||
|
||||
this.onFiltersLoaded(this);
|
||||
|
@ -1245,47 +1251,41 @@ export class TableFilter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Istantiate the collection of features required by the
|
||||
* configuration and add them to the features registry. A feature is
|
||||
* described by a `class` and `name` fields and and optional `property`
|
||||
* field:
|
||||
* {
|
||||
* class: AClass,
|
||||
* name: 'aClass'
|
||||
* }
|
||||
* Conditionally istantiate each feature class in passed collection if
|
||||
* required by configuration and add it to the features registry. A feature
|
||||
* class meta information contains a `name` field and optional `altName` and
|
||||
* `alwaysInstantiate` fields
|
||||
* @param {Array} [features=[]]
|
||||
* @private
|
||||
*/
|
||||
instantiateFeatures(features = []) {
|
||||
features.forEach((feature) => {
|
||||
// TODO: remove the property field.
|
||||
// Due to naming convention inconsistencies, a `property`
|
||||
// field is added to allow a conditional instanciation based
|
||||
// on that property on TableFilter, if supplied.
|
||||
feature.property = feature.property || feature.name;
|
||||
if (!this.hasConfig || this[feature.property] === true ||
|
||||
feature.enforce === true) {
|
||||
let {class: Cls, name} = feature;
|
||||
features.forEach(featureCls => {
|
||||
let Cls = featureCls;
|
||||
|
||||
// assign meta info if not present
|
||||
Cls.meta = Cls.meta || {name: null, altName: null};
|
||||
Cls.meta.name = toCamelCase(Cls.name);
|
||||
let {name, altName, alwaysInstantiate} = Cls.meta;
|
||||
let prop = altName || name;
|
||||
|
||||
if (!this.hasConfig || this[prop] === true
|
||||
|| Boolean(alwaysInstantiate)) {
|
||||
this.Mod[name] = this.Mod[name] || new Cls(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the passed features collection. A feature is described by a
|
||||
* `class` and `name` fields and and optional `property` field:
|
||||
* {
|
||||
* class: AClass,
|
||||
* name: 'aClass'
|
||||
* }
|
||||
* Initialise each feature class in passed collection.
|
||||
* @param {Array} [features=[]]
|
||||
* @private
|
||||
*/
|
||||
initFeatures(features = []) {
|
||||
features.forEach((feature) => {
|
||||
let {property, name} = feature;
|
||||
if (this[property] === true && this.Mod[name]) {
|
||||
features.forEach(featureCls => {
|
||||
let {name, altName} = featureCls.meta;
|
||||
let prop = altName || name;
|
||||
|
||||
if (this[prop] === true && this.Mod[name]) {
|
||||
this.Mod[name].init();
|
||||
}
|
||||
});
|
||||
|
@ -1463,14 +1463,15 @@ export class TableFilter {
|
|||
if (this.hasExcludedRows) {
|
||||
emitter.off(['after-filtering'], () => this.setExcludeRows());
|
||||
}
|
||||
if (this.linkedFilters) {
|
||||
emitter.off(['after-filtering'], () => this.linkFilters());
|
||||
}
|
||||
|
||||
this.emitter.off(['filter-focus'],
|
||||
(tf, filter) => this.setActiveFilterId(filter.id));
|
||||
|
||||
removeClass(this.dom(), this.prfxTf);
|
||||
removeClass(this.dom(), this.prfxResponsive);
|
||||
if (this.dom().tHead) {
|
||||
removeClass(this.dom().tHead, this.stickyCssClass);
|
||||
}
|
||||
|
||||
this.nbHiddenRows = 0;
|
||||
this.validRowsIndex = [];
|
||||
|
@ -1608,7 +1609,7 @@ export class TableFilter {
|
|||
// isolate search term and check occurence in cell data
|
||||
for (let w = 0, len = s.length; w < len; w++) {
|
||||
cS = trim(s[w]);
|
||||
found = this._match(cS, cellValue, j);
|
||||
found = this._match(cS, cellValue, cells[j]);
|
||||
|
||||
if (found) {
|
||||
emitter.emit('highlight-keyword', this,
|
||||
|
@ -1627,7 +1628,8 @@ export class TableFilter {
|
|||
}
|
||||
//single search parameter
|
||||
else {
|
||||
occurence[j] = this._match(trim(sA), cellValue, j);
|
||||
occurence[j] =
|
||||
this._match(trim(sA), cellValue, cells[j]);
|
||||
if (occurence[j]) {
|
||||
emitter.emit('highlight-keyword', this, cells[j],
|
||||
sA);
|
||||
|
@ -1657,7 +1659,7 @@ export class TableFilter {
|
|||
}
|
||||
|
||||
emitter.emit('row-processed', this, k,
|
||||
this.validRowsIndex.length, isMatch);
|
||||
this.validRowsIndex.length - 1, isMatch);
|
||||
},
|
||||
// continue condition
|
||||
(row) => row.cells.length !== this.nbCells
|
||||
|
@ -1673,14 +1675,15 @@ export class TableFilter {
|
|||
|
||||
/**
|
||||
* Match search term in cell data
|
||||
* @param {String} term Search term
|
||||
* @param {String} term Search term
|
||||
* @param {String} cellValue Cell data
|
||||
* @param {Number} colIdx Column index
|
||||
* @param {DOMElement} cell Current cell
|
||||
* @return {Boolean}
|
||||
* @private
|
||||
*/
|
||||
_match(term, cellValue, colIdx) {
|
||||
_match(term, cellValue, cell) {
|
||||
let numData;
|
||||
let colIdx = cell.cellIndex;
|
||||
let decimal = this.getDecimal(colIdx);
|
||||
let reLe = new RegExp(this.leOperator),
|
||||
reGe = new RegExp(this.geOperator),
|
||||
|
@ -1782,11 +1785,11 @@ export class TableFilter {
|
|||
}
|
||||
//empty
|
||||
else if (hasEM) {
|
||||
occurence = isEmptyString(cellValue);
|
||||
occurence = !cell.hasChildNodes() || isEmpty(cellValue);
|
||||
}
|
||||
//non-empty
|
||||
else if (hasNM) {
|
||||
occurence = !isEmptyString(cellValue);
|
||||
occurence = cell.hasChildNodes() && !isEmpty(cellValue);
|
||||
} else {
|
||||
occurence = contains(term, cellValue,
|
||||
this.isExactMatch(colIdx), this.caseSensitive);
|
||||
|
@ -1872,11 +1875,11 @@ export class TableFilter {
|
|||
}
|
||||
//empty
|
||||
else if (hasEM) {
|
||||
occurence = isEmptyString(cellValue);
|
||||
occurence = !cell.hasChildNodes() || isEmpty(cellValue);
|
||||
}
|
||||
//non-empty
|
||||
else if (hasNM) {
|
||||
occurence = !isEmptyString(cellValue);
|
||||
occurence = cell.hasChildNodes() && !isEmpty(cellValue);
|
||||
} else {
|
||||
// If numeric type data, perform a strict equality test and
|
||||
// fallback to unformatted number string comparison
|
||||
|
@ -2479,15 +2482,8 @@ export class TableFilter {
|
|||
return;
|
||||
}
|
||||
|
||||
if (fltColType !== MULTIPLE && fltColType !== CHECKLIST) {
|
||||
if (this.loadFltOnDemand && !this.initialized) {
|
||||
this.emitter.emit('build-select-filter', this, index,
|
||||
this.linkedFilters, this.isExternalFlt());
|
||||
}
|
||||
slc.value = query;
|
||||
}
|
||||
//multiple selects
|
||||
else if (fltColType === MULTIPLE) {
|
||||
if (fltColType === MULTIPLE) {
|
||||
let values = isArray(query) ? query :
|
||||
query.split(' ' + this.orOperator + ' ');
|
||||
|
||||
|
@ -2514,6 +2510,13 @@ export class TableFilter {
|
|||
|
||||
this.emitter.emit('select-checklist-options', this, index, values);
|
||||
}
|
||||
else {
|
||||
if (this.loadFltOnDemand && !this.initialized) {
|
||||
this.emitter.emit('build-select-filter', this, index,
|
||||
this.linkedFilters, this.isExternalFlt());
|
||||
}
|
||||
slc.value = query;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2685,43 +2688,6 @@ export class TableFilter {
|
|||
this.setActiveFilterId(this.getFilterId(colIndex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the filters subject to linking ('select', 'multiple',
|
||||
* 'checklist' type)
|
||||
*/
|
||||
linkFilters() {
|
||||
if (!this.linkedFilters || !this.activeFilterId) {
|
||||
return;
|
||||
}
|
||||
let slcA1 = this.getFiltersByType(SELECT, true),
|
||||
slcA2 = this.getFiltersByType(MULTIPLE, true),
|
||||
slcA3 = this.getFiltersByType(CHECKLIST, true),
|
||||
slcIndex = slcA1.concat(slcA2);
|
||||
slcIndex = slcIndex.concat(slcA3);
|
||||
|
||||
slcIndex.forEach((colIdx) => {
|
||||
let curSlc = this.getFilterElement(colIdx);
|
||||
let slcSelectedValue = this.getFilterValue(colIdx);
|
||||
|
||||
//1st option needs to be inserted
|
||||
if (this.loadFltOnDemand) {
|
||||
let opt0 = createOpt(this.getClearFilterText(colIdx), '');
|
||||
curSlc.innerHTML = '';
|
||||
curSlc.appendChild(opt0);
|
||||
}
|
||||
|
||||
if (slcA3.indexOf(colIdx) !== -1) {
|
||||
this.emitter.emit('build-checklist-filter', this, colIdx,
|
||||
true);
|
||||
} else {
|
||||
this.emitter.emit('build-select-filter', this, colIdx,
|
||||
true);
|
||||
}
|
||||
|
||||
this.setFilterValue(colIdx, slcSelectedValue);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if passed filter column implements exact query match
|
||||
* @param {Number} colIndex Column index
|
||||
|
|
|
@ -32,6 +32,7 @@ div.helpCont
|
|||
color #333
|
||||
background #fff
|
||||
text-align left
|
||||
z-index 1000
|
||||
|
||||
a
|
||||
color #cc0000
|
||||
|
|
|
@ -28,10 +28,17 @@ table.TF
|
|||
border-bottom 1px solid $td-border-color
|
||||
text-overflow ellipsis
|
||||
|
||||
// responsiveness
|
||||
// responsive
|
||||
&.resp
|
||||
display block
|
||||
overflow-x auto
|
||||
overflow-y hidden
|
||||
|
||||
.sort-arrow
|
||||
position initial
|
||||
|
||||
// stick headers
|
||||
&.sticky
|
||||
th
|
||||
position sticky
|
||||
top -1px
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
},
|
||||
btn_reset: true,
|
||||
status_bar: true,
|
||||
sticky_headers: true,
|
||||
msg_filter: 'Filtering...'
|
||||
};
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
highlight_column: true
|
||||
},
|
||||
no_results_message: true,
|
||||
responsive: true,
|
||||
custom_options: {
|
||||
cols:[3],
|
||||
texts: [
|
||||
|
|
|
@ -22,7 +22,7 @@ var tfConfig = {
|
|||
col_2: 'checklist',
|
||||
col_widths: [
|
||||
'75px', '200px', '200px',
|
||||
'100px', '75px', ''
|
||||
'100px', '75px', '400px'
|
||||
],
|
||||
paging: true,
|
||||
alternate_rows: true,
|
||||
|
|
|
@ -20,14 +20,15 @@ var tfConfig = {
|
|||
base_path: '../dist/tablefilter/',
|
||||
col_widths: [
|
||||
'150px', '100px', '100px',
|
||||
'70px', '70px', '70px',
|
||||
'70px', '60px', '60px'
|
||||
'100px', '100px', '100px',
|
||||
'90px', '90px', '90px'
|
||||
],
|
||||
alternate_rows: true,
|
||||
rows_counter: true,
|
||||
btn_reset: true,
|
||||
status_bar: true,
|
||||
load_filters_on_demand: true,
|
||||
sticky_headers: true,
|
||||
col_0: 'multiple',
|
||||
col_1: 'select',
|
||||
col_2: 'checklist'
|
||||
|
|
|
@ -40,6 +40,10 @@
|
|||
page_length: true,
|
||||
sort: true
|
||||
},
|
||||
responsive: true,
|
||||
help_instructions: {
|
||||
container_adjust_left_position: 30
|
||||
},
|
||||
alternate_rows: true,
|
||||
btn_reset: true,
|
||||
rows_counter: true,
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
},
|
||||
col_widths: [
|
||||
'150px', '100px', '100px',
|
||||
'70px', '70px', '70px',
|
||||
'100px', '100px', '100px',
|
||||
'70px', '60px', '60px'
|
||||
],
|
||||
extensions:[{ name: 'sort' }]
|
||||
|
|
|
@ -91,8 +91,8 @@ test('Clear filters', function() {
|
|||
tf.clearFilters();
|
||||
tf.filter();
|
||||
|
||||
deepEqual(tbl.querySelectorAll('tr.odd').length, 3, 'Odd bgs removed');
|
||||
deepEqual(tbl.querySelectorAll('tr.even').length, 4, 'Even bg removed');
|
||||
deepEqual(tbl.querySelectorAll('tr.odd').length, 4, 'Odd bgs removed');
|
||||
deepEqual(tbl.querySelectorAll('tr.even').length, 3, 'Even bg removed');
|
||||
});
|
||||
|
||||
test('Set background on a row', function() {
|
||||
|
@ -242,42 +242,6 @@ test('Can handle `row-paged` event', function() {
|
|||
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');
|
||||
test('Grid layout: initialising alternating rows', function() {
|
||||
tf.destroy();
|
||||
|
@ -309,8 +273,8 @@ test('Grid layout: clear filters', function() {
|
|||
tf.clearFilters();
|
||||
tf.filter();
|
||||
|
||||
deepEqual(tbl.querySelectorAll('tr.odd').length, 3, 'Odd bgs removed');
|
||||
deepEqual(tbl.querySelectorAll('tr.even').length, 4, 'Even bg removed');
|
||||
deepEqual(tbl.querySelectorAll('tr.odd').length, 4, 'Odd bgs removed');
|
||||
deepEqual(tbl.querySelectorAll('tr.even').length, 3, 'Even bg removed');
|
||||
});
|
||||
|
||||
test('Grid layout: set background on a row', function() {
|
||||
|
|
|
@ -100,19 +100,43 @@ test('Can sort options', function() {
|
|||
tf.destroy();
|
||||
tf = new TableFilter('demo', {
|
||||
base_path: '../dist/tablefilter/',
|
||||
col_0: 'checklist',
|
||||
col_1: 'checklist',
|
||||
col_2: 'checklist',
|
||||
col_3: 'checklist',
|
||||
col_4: 'checklist',
|
||||
col_types: ['string', 'string', 'number', 'number', 'number'],
|
||||
sort_num_asc: [2, 3],
|
||||
sort_num_desc: [4]
|
||||
sort_filter_options_asc: [0, 2, 3],
|
||||
sort_filter_options_desc: [1, 4]
|
||||
});
|
||||
tf.init();
|
||||
|
||||
var flt0 = id(tf.fltIds[0]);
|
||||
var flt1 = id(tf.fltIds[1]);
|
||||
var flt2 = id(tf.fltIds[2]);
|
||||
var flt3 = id(tf.fltIds[3]);
|
||||
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(
|
||||
flt2.getElementsByTagName('li')[1].firstChild.firstChild.value,
|
||||
'286',
|
||||
|
@ -182,6 +206,55 @@ test('Can select empty and non-empty options', function() {
|
|||
'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');
|
||||
test('TableFilter removed', function() {
|
||||
tf.destroy();
|
||||
|
|
|
@ -6,6 +6,7 @@ var tf = new TableFilter('demo', {
|
|||
tf.init();
|
||||
|
||||
var clearButton = tf.feature('clearButton');
|
||||
|
||||
module('Sanity checks');
|
||||
test('Clear button component', function() {
|
||||
deepEqual(typeof clearButton, 'object', 'ClearButton instanciated');
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
(function(win, TableFilter){
|
||||
(function(TableFilter) {
|
||||
var id = function (id) { return document.getElementById(id); };
|
||||
|
||||
// TODO: add sort to test it with different column types
|
||||
var tf = new TableFilter('demo', {
|
||||
base_path: '../dist/tablefilter/',
|
||||
|
@ -17,7 +19,6 @@
|
|||
]
|
||||
});
|
||||
tf.init();
|
||||
window.tf = tf;
|
||||
|
||||
module('Sanity checks');
|
||||
test('Data types', function() {
|
||||
|
@ -279,7 +280,7 @@
|
|||
tf.filter();
|
||||
|
||||
// assert
|
||||
deepEqual(tf.getValidRows().length, 8, 'Expected rows');
|
||||
deepEqual(tf.getValidRows().length, 7, 'Expected rows');
|
||||
});
|
||||
|
||||
module('Locale helpers');
|
||||
|
@ -300,10 +301,92 @@
|
|||
deepEqual(result, '.', 'Decimal separator for given column');
|
||||
});
|
||||
|
||||
module('Data types filters options sorting');
|
||||
test('Can sort date types', function () {
|
||||
// setup
|
||||
tf.clearFilters();
|
||||
tf.destroy();
|
||||
tf = new TableFilter('demo', {
|
||||
base_path: '../dist/tablefilter/',
|
||||
col_6: 'checklist',
|
||||
col_7: 'multiple',
|
||||
col_8: 'checklist',
|
||||
col_10: 'select',
|
||||
col_types: [
|
||||
null, null, null,
|
||||
{type: 'formatted-number', decimal: ',', thousands: ','},
|
||||
'formatted-number', null,
|
||||
{type: 'date', locale: 'fr',},
|
||||
{type: 'date', locale: 'en', format: '{dd}-{MM}-{yyyy|yy}'},
|
||||
{
|
||||
type: 'date', locale: 'en',
|
||||
format: ['{dd}-{months}-{yyyy|yy}']
|
||||
},
|
||||
'IpAddress',
|
||||
{
|
||||
type: 'date', locale: 'en',
|
||||
format: ['{yyyy|yy}-{MM}-{dd} {HH}:{mm}:{ss}']
|
||||
}
|
||||
],
|
||||
sort_filter_options_asc: [6, 7],
|
||||
sort_filter_options_desc: [8, 10]
|
||||
});
|
||||
|
||||
// act
|
||||
tf.init();
|
||||
|
||||
var flt6 = id(tf.fltIds[6]);
|
||||
var flt7 = id(tf.fltIds[7]);
|
||||
var flt8 = id(tf.fltIds[8]);
|
||||
var flt10 = id(tf.fltIds[10]);
|
||||
|
||||
// assert
|
||||
deepEqual(
|
||||
flt6.getElementsByTagName('li')[1].firstChild.firstChild.value,
|
||||
'19/1/1984',
|
||||
'First option value for column 6'
|
||||
);
|
||||
deepEqual(
|
||||
flt6.getElementsByTagName('li')[20].firstChild.firstChild.value,
|
||||
'3/7/2002',
|
||||
'Last option value for column 6'
|
||||
);
|
||||
deepEqual(
|
||||
flt7.options[1].value,
|
||||
'1/19/1984',
|
||||
'First option value for column 7'
|
||||
);
|
||||
deepEqual(
|
||||
flt7.options[20].value,
|
||||
'7/3/2002',
|
||||
'Last option value for column 7'
|
||||
);
|
||||
deepEqual(
|
||||
flt8.getElementsByTagName('li')[1].firstChild.firstChild.value,
|
||||
'3-Jul-2002',
|
||||
'First option value for column 8'
|
||||
);
|
||||
deepEqual(
|
||||
flt8.getElementsByTagName('li')[20].firstChild.firstChild.value,
|
||||
'19-Jan-1984',
|
||||
'Last option value for column 8'
|
||||
);
|
||||
deepEqual(
|
||||
flt10.options[1].value,
|
||||
'03-11-21 12:02:04',
|
||||
'First option value for column 10'
|
||||
);
|
||||
deepEqual(
|
||||
flt10.options[19].value,
|
||||
'1899-11-27 02:02:04',
|
||||
'Last option value for column 10'
|
||||
);
|
||||
});
|
||||
|
||||
module('Tear-down');
|
||||
test('can destroy TableFilter DOM elements', function() {
|
||||
tf.destroy();
|
||||
deepEqual(tf.isInitialized(), false, 'Filters removed');
|
||||
});
|
||||
|
||||
})(window, TableFilter);
|
||||
})(TableFilter);
|
||||
|
|
|
@ -157,24 +157,31 @@ test('Can enable options sorting on a column basis', function() {
|
|||
deepEqual(flt4.options[7].value, '40', 'Last option value for column 4');
|
||||
});
|
||||
|
||||
test('Can sort numeric options in asc and desc manner', function() {
|
||||
test('Can sort options in asc and desc manner', function() {
|
||||
tf.clearFilters();
|
||||
tf.destroy();
|
||||
tf = new TableFilter('demo', {
|
||||
base_path: '../dist/tablefilter/',
|
||||
col_0: 'select',
|
||||
col_2: 'multiple',
|
||||
col_3: 'select',
|
||||
col_4: 'multiple',
|
||||
col_types: ['string', 'string', 'number', 'number', 'number'],
|
||||
sort_num_asc: [2, 3],
|
||||
sort_num_desc: [4]
|
||||
case_sensitive: true,
|
||||
sort_filter_options_asc: [2, 3],
|
||||
sort_filter_options_desc: [0, 4]
|
||||
});
|
||||
tf.init();
|
||||
|
||||
var flt0 = id(tf.fltIds[0]);
|
||||
var flt2 = id(tf.fltIds[2]);
|
||||
var flt3 = id(tf.fltIds[3]);
|
||||
var flt4 = id(tf.fltIds[4]);
|
||||
|
||||
deepEqual(flt0.options[1].value, 'Sydney',
|
||||
'First option value for column 0');
|
||||
deepEqual(flt0.options[2].value, 'Adelaide',
|
||||
'Last option value for column 0');
|
||||
deepEqual(flt2.options[1].value, '286', 'First option value for column 2');
|
||||
deepEqual(flt2.options[7].value, '2781', 'Last option value for column 2');
|
||||
deepEqual(flt3.options[1].value, '.6', 'First option value for column 3');
|
||||
|
@ -183,6 +190,51 @@ test('Can sort numeric options in asc and desc manner', function() {
|
|||
deepEqual(flt4.options[7].value, '4.3', 'Last option value for column 4');
|
||||
});
|
||||
|
||||
// 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: 'multiple',
|
||||
col_3: 'select',
|
||||
col_4: 'multiple',
|
||||
clear_filter_text: [null, null, 'clear 2', 'clear 3', 'clear 4']
|
||||
});
|
||||
tf.init();
|
||||
|
||||
var flt2 = tf.getFilterElement(2);
|
||||
var flt3 = tf.getFilterElement(3);
|
||||
var flt4 = tf.getFilterElement(4);
|
||||
|
||||
deepEqual(flt2.options[0].innerHTML, 'clear 2', 'clear text filter 2');
|
||||
deepEqual(flt3.options[0].innerHTML, 'clear 3', 'clear text filter 3');
|
||||
deepEqual(flt4.options[0].innerHTML, '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: 'multiple',
|
||||
col_3: 'select',
|
||||
col_4: 'multiple',
|
||||
clear_filter_text: 'reset'
|
||||
});
|
||||
tf.init();
|
||||
|
||||
var flt2 = tf.getFilterElement(2);
|
||||
var flt3 = tf.getFilterElement(3);
|
||||
var flt4 = tf.getFilterElement(4);
|
||||
|
||||
deepEqual(flt2.options[0].innerHTML, 'reset', 'clear text filter 2');
|
||||
deepEqual(flt3.options[0].innerHTML, 'reset', 'clear text filter 3');
|
||||
deepEqual(flt4.options[0].innerHTML, 'reset', 'clear text filter 4');
|
||||
});
|
||||
|
||||
|
||||
module('Tear down');
|
||||
test('TableFilter removed', function() {
|
||||
tf.destroy();
|
||||
deepEqual(id(tf.fltIds[3]), null, 'Filter is removed');
|
||||
|
|
|
@ -51,10 +51,13 @@
|
|||
});
|
||||
|
||||
test('Empty operator - [empty]', function() {
|
||||
var cell = tf.getWorkingRows()[4].cells[4];
|
||||
cell.innerHTML = '';
|
||||
tf.clearFilters();
|
||||
tf.setFilterValue(4, '[empty]');
|
||||
tf.filter();
|
||||
var filteredData = tf.getFilteredData();
|
||||
|
||||
deepEqual(tf.getValidRows().length, 1, 'Expected number of matches');
|
||||
deepEqual(
|
||||
filteredData[0],
|
||||
|
@ -63,7 +66,25 @@
|
|||
);
|
||||
});
|
||||
|
||||
test('Empty operator - with cell containing dom element', function() {
|
||||
var cell = tf.getWorkingRows()[4].cells[4];
|
||||
cell.innerHTML = '<img>';
|
||||
tf.clearFilters();
|
||||
tf.setFilterValue(4, '[empty]');
|
||||
tf.filter();
|
||||
var filteredData = tf.getFilteredData();
|
||||
|
||||
deepEqual(tf.getValidRows().length, 1, 'Expected match');
|
||||
deepEqual(
|
||||
filteredData[0],
|
||||
[6, ['Adelaide', 'Perth', '2781', '3.1', '']],
|
||||
'Expected row data'
|
||||
);
|
||||
});
|
||||
|
||||
test('Non-empty operator - [nonempty]', function() {
|
||||
var cell = tf.getWorkingRows()[4].cells[4];
|
||||
cell.innerHTML = '';
|
||||
tf.clearFilters();
|
||||
tf.setFilterValue(4, '[nonempty]');
|
||||
tf.filter();
|
||||
|
@ -75,6 +96,16 @@
|
|||
'Expected row data');
|
||||
});
|
||||
|
||||
test('Non-empty operator - with cell containing dom element', function() {
|
||||
var cell = tf.getWorkingRows()[4].cells[4];
|
||||
cell.innerHTML = '<img>';
|
||||
tf.clearFilters();
|
||||
tf.setFilterValue(4, '[nonempty]');
|
||||
tf.filter();
|
||||
|
||||
deepEqual(tf.getValidRows().length, 6, 'Expected number of matches');
|
||||
});
|
||||
|
||||
test('Or operator - ||', function() {
|
||||
tf.clearFilters();
|
||||
tf.setFilterValue(1, 'Canberra||Alice Springs');
|
||||
|
|
79
test/test-help-responsive.html
Normal file
79
test/test-help-responsive.html
Normal file
|
@ -0,0 +1,79 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>TableFilter help pop-up with responsive behaviour</title>
|
||||
<link rel="stylesheet" href="libs/qunit/qunit.css">
|
||||
<script src="libs/qunit/qunit.js"></script>
|
||||
<script src="libs/polyfill.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div style="float: right; width: 80%; border: 1px solid #f4f4f4;"></div>
|
||||
<table id="demo" cellpadding="0" cellspacing="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>From</th>
|
||||
<th>Destination</th>
|
||||
<th>Road Distance (km)</th>
|
||||
<th>By Air (hrs)</th>
|
||||
<th>By Rail (hrs)</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Sydney</strong></td>
|
||||
<td>Adelaide</td>
|
||||
<td>1412</td>
|
||||
<td>1.4</td>
|
||||
<td>25.3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Sydney</strong></td>
|
||||
<td>Brisbane</td>
|
||||
<td>982</td>
|
||||
<td>1.5</td>
|
||||
<td>16</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Sydney</strong></td>
|
||||
<td>Canberra</td>
|
||||
<td>286</td>
|
||||
<td>.6</td>
|
||||
<td>4.3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Sydney</strong></td>
|
||||
<td>Melbourne</td>
|
||||
<td>872</td>
|
||||
<td>1.1</td>
|
||||
<td>10.5</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Adelaide</strong></td>
|
||||
<td>Perth</td>
|
||||
<td>2781</td>
|
||||
<td>3.1</td>
|
||||
<td>38</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Adelaide</strong></td>
|
||||
<td>Alice Springs</td>
|
||||
<td>1533</td>
|
||||
<td>2</td>
|
||||
<td>20.25</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<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-help-responsive.js"></script>
|
||||
|
||||
<div id="qunit"></div>
|
||||
<div id="qunit-fixture"></div>
|
||||
</body>
|
||||
</html>
|
70
test/test-help-responsive.js
Normal file
70
test/test-help-responsive.js
Normal file
|
@ -0,0 +1,70 @@
|
|||
|
||||
var tf = new TableFilter('demo', {
|
||||
base_path: '../dist/tablefilter/',
|
||||
help_instructions: {
|
||||
container_adjust_left_position: 20
|
||||
},
|
||||
responsive: true
|
||||
});
|
||||
tf.init();
|
||||
|
||||
var help = tf.feature('help');
|
||||
module('Sanity checks');
|
||||
test('Button element', function() {
|
||||
deepEqual(typeof help, 'object', 'Help instanciated');
|
||||
notEqual(help.btn, null, 'btn property');
|
||||
});
|
||||
|
||||
module('Pop-up container position');
|
||||
test('Help UI elements', function() {
|
||||
var container = help.cont,
|
||||
helpBtn = help.btn;
|
||||
deepEqual(container.nodeName, 'DIV', 'Help container');
|
||||
deepEqual(helpBtn.nodeName, 'SPAN', 'Help button');
|
||||
});
|
||||
|
||||
// 772 issue: pop-up container position when table feature horizontal scroll
|
||||
test('When table has horizontal scroll', function() {
|
||||
// setup
|
||||
tf.dom().scrollLeft = 10000;
|
||||
|
||||
// act
|
||||
help.toggle();
|
||||
|
||||
// assert
|
||||
deepEqual(
|
||||
parseFloat(help.cont.style.left),
|
||||
(help.btn.offsetLeft
|
||||
- tf.dom().scrollLeft
|
||||
+ help.contAdjustLeftPosition),
|
||||
'Pop-up container position'
|
||||
);
|
||||
});
|
||||
|
||||
test('When table does not have horizontal scroll', function() {
|
||||
tf.destroy();
|
||||
tf = new TableFilter('demo', {
|
||||
base_path: '../dist/tablefilter/',
|
||||
help_instructions: true,
|
||||
responsive: false
|
||||
});
|
||||
tf.init();
|
||||
var help = tf.feature('help');
|
||||
|
||||
// act
|
||||
help.toggle();
|
||||
|
||||
// assert
|
||||
deepEqual(help.cont.style.left, '', 'Pop-up container position');
|
||||
});
|
||||
|
||||
module('Tear-down');
|
||||
test('can destroy Help UI component', function() {
|
||||
// act
|
||||
tf.destroy();
|
||||
var help = tf.feature('help');
|
||||
|
||||
// assert
|
||||
deepEqual(help.btn, null, 'Help button removed');
|
||||
deepEqual(help.cont, null, 'Help pop-up container removed');
|
||||
});
|
|
@ -44,6 +44,35 @@ test('Match same term with increasing number of chars', function() {
|
|||
'Search term matched');
|
||||
});
|
||||
|
||||
// issue 628
|
||||
test('unhighlight with term', function() {
|
||||
// setup
|
||||
tf.clearFilters();
|
||||
tf.setFilterValue(0, 'Sydney');
|
||||
tf.filter();
|
||||
|
||||
// act
|
||||
highlightKeyword.unhighlight('Sydney', highlightKeyword.highlightCssClass);
|
||||
|
||||
// assert
|
||||
deepEqual(tf.dom().querySelectorAll('.keyword').length, 0,
|
||||
'term unhighlighted');
|
||||
});
|
||||
test('unhighlight with null term', function() {
|
||||
// setup
|
||||
tf.clearFilters();
|
||||
tf.setFilterValue(0, 'Sydney');
|
||||
tf.setFilterValue(1, 'Canbe');
|
||||
tf.filter();
|
||||
|
||||
// act
|
||||
highlightKeyword.unhighlight(null, highlightKeyword.highlightCssClass);
|
||||
|
||||
// assert
|
||||
deepEqual(tf.dom().querySelectorAll('.keyword').length, 0,
|
||||
'all terms unhighlighted');
|
||||
});
|
||||
|
||||
module('Reset feature');
|
||||
test('can destroy and init TableFilter', function() {
|
||||
tf.destroy();
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
});
|
||||
|
||||
var ct = 0;
|
||||
tf.emitter.on(['build-checklist-filter'], function() {
|
||||
tf.emitter.on(['after-filtering'], function() {
|
||||
ct++;
|
||||
});
|
||||
|
||||
|
@ -31,7 +31,7 @@
|
|||
tf.clearFilters();
|
||||
|
||||
deepEqual(ct, 2,
|
||||
'build-checklist-filter event emitted after filtering');
|
||||
'after-filtering event emitted after filtering');
|
||||
tf.onAfterFilter = null;
|
||||
tf.destroy();
|
||||
tf = null;
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>TableFilter basic test</title>
|
||||
<title>TableFilter loader ui component tests</title>
|
||||
<link rel="stylesheet" href="libs/qunit/qunit.css">
|
||||
<script src="libs/qunit/qunit.js"></script>
|
||||
<script src="libs/polyfill.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="my-loader"></div>
|
||||
<table id="demo" cellpadding="0" cellspacing="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
|
@ -75,4 +76,4 @@
|
|||
<div id="qunit"></div>
|
||||
<div id="qunit-fixture"></div>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -75,6 +75,82 @@ test('Can show loader', function() {
|
|||
loader.show('');
|
||||
deepEqual(loader.cont.style.display, '', 'Loader is displayed');
|
||||
});
|
||||
test('Does not show loader if feature not enabled', function() {
|
||||
// setup
|
||||
var isEnabled = loader.isEnabled;
|
||||
var hit = 0;
|
||||
loader.isEnabled = function() {
|
||||
hit++;
|
||||
};
|
||||
|
||||
// act
|
||||
loader.show('');
|
||||
|
||||
// assert
|
||||
deepEqual(hit, 1, 'loader not shown');
|
||||
|
||||
loader.isEnabled = isEnabled;
|
||||
});
|
||||
test('Can generate loader in target element', function() {
|
||||
// setup
|
||||
loader.destroy();
|
||||
loader.targetId = 'my-loader';
|
||||
var targetEl = document.getElementById('my-loader');
|
||||
|
||||
// act
|
||||
loader.init();
|
||||
|
||||
// assert
|
||||
deepEqual(targetEl.innerHTML, '<div class="loader">Loading...</div>',
|
||||
'Loader injected in target element');
|
||||
});
|
||||
test('Can generate loader with custom html', function() {
|
||||
// setup
|
||||
loader.destroy();
|
||||
loader.html = '<h3>loading...</h3>';
|
||||
|
||||
// act
|
||||
loader.init();
|
||||
|
||||
// assert
|
||||
deepEqual(loader.cont.innerHTML, '<h3>loading...</h3>',
|
||||
'Loader with custom html');
|
||||
});
|
||||
test('Can show loader when known event is emitted', function() {
|
||||
// setup
|
||||
var show = loader.show;
|
||||
var hit = 0;
|
||||
loader.show = function() {
|
||||
hit++;
|
||||
};
|
||||
|
||||
// act
|
||||
tf.emitter.emit('before-clearing-filters', tf);
|
||||
|
||||
// assert
|
||||
deepEqual(hit, 1, 'show method is called');
|
||||
|
||||
loader.show = show;
|
||||
});
|
||||
test('Can hide loader when known event is emitted', function() {
|
||||
// setup
|
||||
var show = loader.show;
|
||||
var hit = 0;
|
||||
var arg = null;
|
||||
loader.show = function() {
|
||||
hit++;
|
||||
arg = arguments[0];
|
||||
};
|
||||
|
||||
// act
|
||||
tf.emitter.emit('after-clearing-filters', tf);
|
||||
|
||||
// assert
|
||||
deepEqual(hit, 1, 'show method is called');
|
||||
deepEqual(arg, 'none', 'with `none` argument');
|
||||
|
||||
loader.show = show;
|
||||
});
|
||||
|
||||
module('Tear-down');
|
||||
test('can destroy TableFilter DOM elements', function() {
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
const webpack = require('webpack');
|
||||
const path = require('path');
|
||||
const Clean = require('clean-webpack-plugin');
|
||||
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
|
||||
const StringReplacePlugin = require('string-replace-webpack-plugin');
|
||||
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
|
||||
const fs = require('fs');
|
||||
const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
|
||||
|
||||
|
@ -30,9 +31,7 @@ module.exports = {
|
|||
exclude: /tablefilter\/node_modules/,
|
||||
options: {
|
||||
compact: false,
|
||||
presets: ['es2015'],
|
||||
// plugins: [['transform-es2015-classes', {loose: true}]]
|
||||
plugins: 'transform-es2015-classes'
|
||||
presets: ['@babel/env']
|
||||
},
|
||||
loader: 'babel-loader'
|
||||
}, {
|
||||
|
@ -53,12 +52,24 @@ module.exports = {
|
|||
}
|
||||
]
|
||||
},
|
||||
devtool: 'source-map',
|
||||
// devtool: 'source-map',
|
||||
optimization: {
|
||||
minimize: true
|
||||
minimizer: [
|
||||
new UglifyJsPlugin({
|
||||
// sourceMap: true,
|
||||
uglifyOptions: {
|
||||
beautify: false,
|
||||
warnings: false,
|
||||
comments: false,
|
||||
keep_fnames: true
|
||||
}
|
||||
})
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new Clean(['dist']),
|
||||
new CleanWebpackPlugin({
|
||||
cleanOnceBeforeBuildPatterns: [path.join(process.cwd(), 'dist')]
|
||||
}),
|
||||
new webpack.optimize.AggressiveMergingPlugin(),
|
||||
new StringReplacePlugin(),
|
||||
new webpack.optimize.MinChunkSizePlugin({
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const webpack = require('webpack');
|
||||
const webpackConfig = require('./webpack.config.js');
|
||||
const path = require('path');
|
||||
const Clean = require('clean-webpack-plugin');
|
||||
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
|
||||
|
||||
module.exports = {
|
||||
mode: 'development',
|
||||
|
@ -23,7 +23,9 @@ module.exports = {
|
|||
},
|
||||
devtool: 'source-map',
|
||||
plugins: [
|
||||
new Clean(['dist']),
|
||||
new CleanWebpackPlugin({
|
||||
cleanOnceBeforeBuildPatterns: [path.join(process.cwd(), 'dist')]
|
||||
}),
|
||||
new webpack.LoaderOptionsPlugin({
|
||||
debug: true,
|
||||
options: {
|
||||
|
@ -32,7 +34,7 @@ module.exports = {
|
|||
noAutoWrap: true,
|
||||
babel: {
|
||||
compact: false,
|
||||
presets: ['es2015'],
|
||||
presets: ['env'],
|
||||
plugins: [['transform-es2015-classes', {loose: true}]]
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue