1
0
Fork 0
mirror of https://github.com/koalyptus/TableFilter.git synced 2024-06-27 09:50:24 +02:00

Compare commits

...

781 commits

Author SHA1 Message Date
koalyptus 7afe45f1e6
Merge pull request #787 from koalyptus/dependabot/npm_and_yarn/codecov-3.7.1
Bump codecov from 3.7.0 to 3.7.1
2020-07-22 19:51:17 +10:00
koalyptus 6e01e45dfb prepare dist 2020-07-22 19:45:07 +10:00
dependabot[bot] 12c30629af
Bump codecov from 3.7.0 to 3.7.1
Bumps [codecov](https://github.com/codecov/codecov-node) from 3.7.0 to 3.7.1.
- [Release notes](https://github.com/codecov/codecov-node/releases)
- [Commits](https://github.com/codecov/codecov-node/compare/v3.7.0...v3.7.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-21 12:35:35 +00:00
koalyptus 3e763efac9
Merge pull request #784 from koalyptus/769-refine-empty-cell-logic
769 refine empty nonempty operators logic
2020-06-16 13:03:27 +10:00
koalyptus 825b915ae8 769 refine empty nonempty operators logic 2020-06-16 12:28:12 +10:00
koalyptus 8e48bf2943
Merge pull request #783 from koalyptus/greenkeeper/monorepo.babel7-20200526215451
Update babel7 to the latest version 🚀
2020-06-15 15:20:26 +10:00
koalyptus be7a5e585f prepare dist for 0.7.1 2020-06-15 15:19:11 +10:00
greenkeeper[bot] c44bef22a2
chore(package): update lockfile package-lock.json 2020-05-26 23:57:32 +00:00
greenkeeper[bot] 6dcebbf67e
chore(package): update @babel/preset-env to version 7.10.0 2020-05-26 23:57:28 +00:00
greenkeeper[bot] 44cb6f9124
chore(package): update @babel/core to version 7.10.0 2020-05-26 23:57:25 +00:00
koalyptus 571c31e8da
Merge pull request #780 from koalyptus/772-fix
Fix for #772: help instructions pop-up position with responsive behaviour
2020-05-14 12:58:23 +10:00
koalyptus 8633891fdb add unit tests - prepare dist 2020-05-14 12:40:44 +10:00
koalyptus 8eddc6f35c introduce adjust_container_left_position option in help_instructions configuration 2020-05-13 20:46:23 +10:00
koalyptus 577fb0b90a
Merge pull request #768 from koalyptus/greenkeeper/monorepo.babel7-20200228094136
Update babel7 to the latest version 🚀
2020-05-07 20:56:13 +10:00
Max Guglielmi 88a5bfe425 bump dep - prepare dist 2020-05-07 20:23:53 +10:00
Max Guglielmi cac2900444 prepare dist 2020-05-07 20:21:35 +10:00
greenkeeper[bot] 5dad4dae8e
chore(package): update lockfile package-lock.json 2020-02-28 11:43:33 +00:00
greenkeeper[bot] 134851525c
chore(package): update @babel/preset-env to version 7.8.6 2020-02-28 11:43:28 +00:00
greenkeeper[bot] 9a66748bb8
chore(package): update @babel/core to version 7.8.6 2020-02-28 11:43:25 +00:00
koalyptus c52004421f
Merge pull request #762 from koalyptus/greenkeeper/codecov-3.6.3
Update codecov to the latest version 🚀
2020-02-04 14:16:41 +11:00
koalyptus f53b392c59 prepare dist 2020-02-04 14:03:29 +11:00
koalyptus c496b0916d Merge branch 'master' into greenkeeper/codecov-3.6.3 2020-02-04 13:50:04 +11:00
koalyptus 25b89b19e7
Merge pull request #760 from koalyptus/greenkeeper/monorepo.babel7-20200112133918
Update babel7 to the latest version 🚀
2020-02-03 14:11:32 +11:00
koalyptus 8b4a05be02 prepare dist 2020-02-03 13:50:29 +11:00
koalyptus 1c4961a25b Merge branch 'master' into greenkeeper/monorepo.babel7-20200112133918 2020-02-03 13:35:30 +11:00
greenkeeper[bot] 40daf54768
chore(package): update lockfile package-lock.json 2020-01-31 14:09:11 +00:00
greenkeeper[bot] c43debc7ac
chore(package): update codecov to version 3.6.3 2020-01-31 14:09:07 +00:00
koalyptus 3ac2603e47
Merge pull request #759 from koalyptus/dependabot/npm_and_yarn/handlebars-4.5.3
Bump handlebars from 4.1.2 to 4.5.3
2020-01-14 14:53:40 +11:00
koalyptus 185c119342 prepare dist 2020-01-14 13:44:44 +11:00
koalyptus 80c9b3d734 Merge branch 'master' into dependabot/npm_and_yarn/handlebars-4.5.3 2020-01-14 13:26:01 +11:00
greenkeeper[bot] e8605e5e19
chore(package): update lockfile package-lock.json 2020-01-12 15:47:37 +00:00
greenkeeper[bot] bd95afb3eb
chore(package): update @babel/preset-env to version 7.8.0 2020-01-12 15:47:33 +00:00
greenkeeper[bot] c16f885951
chore(package): update @babel/core to version 7.8.0 2020-01-12 15:47:30 +00:00
koalyptus 6be9ad491f
Merge pull request #758 from koalyptus/greenkeeper/monorepo.babel7-20191219010209
Update babel7 to the latest version 🚀
2020-01-09 09:56:14 +11:00
koalyptus 447a3119aa Prepare dist 2020-01-09 09:44:26 +11:00
dependabot[bot] 2025aa4010
Bump handlebars from 4.1.2 to 4.5.3
Bumps [handlebars](https://github.com/wycats/handlebars.js) from 4.1.2 to 4.5.3.
- [Release notes](https://github.com/wycats/handlebars.js/releases)
- [Changelog](https://github.com/wycats/handlebars.js/blob/master/release-notes.md)
- [Commits](https://github.com/wycats/handlebars.js/compare/v4.1.2...v4.5.3)

Signed-off-by: dependabot[bot] <support@github.com>
2019-12-27 00:16:57 +00:00
greenkeeper[bot] bdc03755e8
chore(package): update lockfile package-lock.json 2019-12-19 02:28:44 +00:00
greenkeeper[bot] 2dceed888e
chore(package): update @babel/preset-env to version 7.7.7 2019-12-19 02:28:40 +00:00
greenkeeper[bot] 982769a020
chore(package): update @babel/core to version 7.7.7 2019-12-19 02:28:37 +00:00
koalyptus 4318826ead
Merge pull request #754 from koalyptus/greenkeeper/monorepo.babel7-20191106233658
Update babel7 to the latest version 🚀
2019-12-09 14:53:11 +11:00
koalyptus 66b8fa9d94 prepare dist: include missing file 2019-12-09 14:46:14 +11:00
koalyptus 79cea3e27f prepare dist + miscellaneous fixes 2019-12-09 14:44:37 +11:00
greenkeeper[bot] 7af493da27
chore(package): update lockfile package-lock.json 2019-11-07 01:41:18 +00:00
greenkeeper[bot] 90c3b7f937
chore(package): update @babel/preset-env to version 7.7.1 2019-11-07 01:41:14 +00:00
greenkeeper[bot] 85dce5847a
chore(package): update @babel/core to version 7.7.2 2019-11-07 01:41:11 +00:00
koalyptus 65863b635a
Merge pull request #753 from koalyptus/greenkeeper/monorepo.babel7-20191105110141
Update babel7 to the latest version 🚀
2019-11-06 14:08:51 +11:00
koalyptus 3c001f52e2 prepare dist 2019-11-06 13:56:55 +11:00
greenkeeper[bot] e3957977b6
chore(package): update lockfile package-lock.json 2019-11-05 14:06:38 +00:00
greenkeeper[bot] 8923c4db94
chore(package): update @babel/preset-env to version 7.7.0 2019-11-05 14:06:34 +00:00
greenkeeper[bot] c7d1a25467
chore(package): update @babel/core to version 7.7.0 2019-11-05 14:06:31 +00:00
koalyptus ebdd817199
Merge pull request #746 from koalyptus/greenkeeper/eslint-6.5.0
Update eslint to the latest version 🚀
2019-10-21 14:28:13 +11:00
koalyptus 27365e25d4 prepare dist 2019-10-21 14:20:42 +11:00
koalyptus 2e960867ab Merge branch 'master' into greenkeeper/eslint-6.5.0 2019-10-21 13:25:34 +11:00
koalyptus 3d35d53005
Merge pull request #745 from koalyptus/greenkeeper/monorepo.babel7-20190923213305
Update babel7 to the latest version 🚀
2019-10-20 17:59:00 +11:00
koalyptus 02bc5e3ae1 fix conflict - prepare dist 2019-10-20 17:32:55 +11:00
koalyptus 09c1f8ff52
Merge pull request #744 from koalyptus/greenkeeper/codecov-3.6.1
Update codecov to the latest version 🚀
2019-10-10 13:50:18 +11:00
koalyptus 6b339f7bd7 merge master in, resolve conflix 2019-10-10 13:38:17 +11:00
koalyptus a1efe26a85 prepare dist 2019-10-10 13:36:03 +11:00
koalyptus 64e6c6597f
Merge pull request #737 from koalyptus/greenkeeper/babel-eslint-10.0.3
Update babel-eslint to the latest version 🚀
2019-09-30 07:58:23 +10:00
koalyptus 9363a7a661 prepare dist 2019-09-30 07:09:32 +10:00
greenkeeper[bot] 41e220efa9
chore(package): update lockfile package-lock.json 2019-09-29 06:24:29 +00:00
greenkeeper[bot] 64d3808a2b
chore(package): update eslint to version 6.5.0 2019-09-29 06:24:25 +00:00
greenkeeper[bot] eb15788965
chore(package): update lockfile package-lock.json 2019-09-23 23:07:35 +00:00
greenkeeper[bot] fede2f6e86
chore(package): update @babel/preset-env to version 7.6.2 2019-09-23 23:07:26 +00:00
greenkeeper[bot] 9738c8ed91
chore(package): update @babel/core to version 7.6.2 2019-09-23 23:07:21 +00:00
greenkeeper[bot] b285d01b54
chore(package): update lockfile package-lock.json 2019-09-20 12:24:13 +00:00
greenkeeper[bot] 37eed72f2c
chore(package): update codecov to version 3.6.1 2019-09-20 12:24:01 +00:00
koalyptus 71103cd04b
Merge pull request #743 from koalyptus/greenkeeper/codecov-3.6.0
Update codecov to the latest version 🚀
2019-09-20 20:01:13 +10:00
koalyptus 42a347550b prepare dist 2019-09-20 19:54:27 +10:00
koalyptus bed04b5b9b Merge remote-tracking branch 'origin/greenkeeper/monorepo.babel7-20190906190906' into greenkeeper/codecov-3.6.0 2019-09-20 19:46:05 +10:00
koalyptus 43fc68df31 Merge remote-tracking branch 'origin/greenkeeper/eslint-6.4.0' into greenkeeper/codecov-3.6.0 2019-09-20 19:45:52 +10:00
greenkeeper[bot] d116525f73
chore(package): update lockfile package-lock.json 2019-09-20 02:31:28 +00:00
greenkeeper[bot] d7ff36514d
chore(package): update codecov to version 3.6.0 2019-09-20 02:31:18 +00:00
greenkeeper[bot] 0d0abf3206
chore(package): update lockfile package-lock.json 2019-09-14 02:14:37 +00:00
greenkeeper[bot] 4cd004e423
chore(package): update eslint to version 6.4.0 2019-09-14 02:14:29 +00:00
greenkeeper[bot] 459829a214
chore(package): update lockfile package-lock.json 2019-09-06 22:27:01 +00:00
greenkeeper[bot] b8c0c1bc3f
chore(package): update @babel/preset-env to version 7.6.0 2019-09-06 22:26:54 +00:00
greenkeeper[bot] 5686e8a470
chore(package): update @babel/core to version 7.6.0 2019-09-06 22:26:48 +00:00
koalyptus b04d4f55ed
Merge pull request #735 from koalyptus/greenkeeper/eslint-6.2.0
Update eslint to the latest version 🚀
2019-09-06 14:26:50 +10:00
koalyptus 3004963058 prepare dist 2019-09-06 14:15:54 +10:00
greenkeeper[bot] 3454187be6
chore(package): update lockfile package-lock.json 2019-08-25 21:33:46 +00:00
greenkeeper[bot] 1dac7736b1
chore(package): update babel-eslint to version 10.0.3 2019-08-25 21:33:28 +00:00
greenkeeper[bot] 2c7ad88346
chore(package): update lockfile package-lock.json 2019-08-18 22:53:24 +00:00
greenkeeper[bot] 6e41c4a8c6
chore(package): update eslint to version 6.2.0 2019-08-18 22:53:09 +00:00
koalyptus 859f6b1eeb
Merge pull request #734 from koalyptus/greenkeeper/uglifyjs-webpack-plugin-2.2.0
Update uglifyjs-webpack-plugin to the latest version 🚀
2019-08-09 14:21:29 +10:00
koalyptus 7204c4b546 prepare dist 2019-08-09 12:24:02 +10:00
greenkeeper[bot] f29b59fdbd chore(package): update lockfile package-lock.json 2019-07-31 12:27:29 +00:00
greenkeeper[bot] 6cc887e806 chore(package): update uglifyjs-webpack-plugin to version 2.2.0 2019-07-31 12:27:24 +00:00
koalyptus f7ad9741ca
Merge pull request #733 from koalyptus/731-upgrade-webpack
731 prepare dist
2019-07-30 13:07:16 +10:00
koalyptus 323a80d1d7 731 prepare dist 2019-07-30 12:59:37 +10:00
koalyptus fc46f0b4ae
Merge pull request #728 from koalyptus/greenkeeper/monorepo.babel7-20190704132520
Update babel7 to the latest version 🚀
2019-07-21 18:44:00 +10:00
koalyptus 0471570985 prepare dist 2019-07-21 18:12:46 +10:00
koalyptus 20243b641f Merge remote-tracking branch 'origin/greenkeeper/eslint-8.0.0' into greenkeeper/monorepo.babel7-20190704132520 2019-07-21 17:21:03 +10:00
koalyptus 99722cbdb0 resolve merge conflicts 2019-07-21 17:20:30 +10:00
koalyptus 64cc6825c5 bump tablefilter version 2019-07-21 17:17:47 +10:00
greenkeeper[bot] bcb541fcad chore(package): update lockfile package-lock.json 2019-07-04 18:45:43 +00:00
greenkeeper[bot] 1c3c1bbb0a chore(package): update @babel/preset-env to version 7.5.0 2019-07-04 18:45:38 +00:00
greenkeeper[bot] bba009c505 chore(package): update @babel/core to version 7.5.0 2019-07-04 18:45:35 +00:00
greenkeeper[bot] 48659ec1d5 chore(package): update lockfile package-lock.json 2019-06-22 04:01:53 +00:00
greenkeeper[bot] 1d32dcea7d chore(package): update eslint to version 6.0.0 2019-06-22 04:01:44 +00:00
greenkeeper[bot] 0e1c617b06 chore(package): update lockfile package-lock.json 2019-06-17 14:21:21 +00:00
greenkeeper[bot] 5c705fe591 chore(package): update babel-eslint to version 10.0.2 2019-06-17 14:21:13 +00:00
koalyptus 3c501e3aef
Merge pull request #722 from koalyptus/716-fix-sort-date-desc
Enhance filter options sorting based on column data type
2019-06-07 21:43:09 +10:00
koalyptus 78ae09c861 Enhance filter options sorting based on column data type 2019-06-07 18:26:33 +10:00
koalyptus 2e1af5efb3
Merge pull request #715 from koalyptus/greenkeeper/uglifyjs-webpack-plugin-2.1.3
Update uglifyjs-webpack-plugin to the latest version 🚀
2019-06-06 11:28:09 +10:00
koalyptus da270df5d6 fix CleanWebpackPlugin webpack plugin upgrade 2019-06-06 11:22:03 +10:00
koalyptus 8a8419bf02 Merge remote-tracking branch 'origin/greenkeeper/clean-webpack-plugin-3.0.0' into greenkeeper/uglifyjs-webpack-plugin-2.1.3 2019-06-06 10:35:09 +10:00
koalyptus a6c24c7885 fix uglifyjs webpack plugin upgrade 2019-06-06 10:33:43 +10:00
koalyptus ed2fef999a Merge branch 'master' into greenkeeper/uglifyjs-webpack-plugin-2.1.3 2019-06-06 10:19:35 +10:00
greenkeeper[bot] 47c66d71bb chore(package): update lockfile package-lock.json 2019-05-30 13:44:30 +00:00
greenkeeper[bot] f99f850c4d chore(package): update clean-webpack-plugin to version 3.0.0 2019-05-30 13:44:24 +00:00
koalyptus 10c06b5100
Merge pull request #720 from koalyptus/714-fix-clear-filter-text
address #714: clear_filter_text
2019-05-24 19:53:01 +10:00
koalyptus 1cc810c341 remove tmp file 2019-05-24 17:08:26 +10:00
koalyptus c707978e19 address #714: clear_filter_text 2019-05-24 17:03:09 +10:00
koalyptus 32b541239e
Merge pull request #719 from koalyptus/greenkeeper/monorepo.babel7-20190521175803
Update babel7 to the latest version 🚀
2019-05-22 16:41:55 +10:00
koalyptus 2963962250 prep dist 2019-05-22 16:30:51 +10:00
koalyptus bbec44cc15 Merge remote-tracking branch 'origin/greenkeeper/grunt-qunit-istanbul-1.1.0' into greenkeeper/monorepo.babel7-20190521175803 2019-05-22 16:25:16 +10:00
koalyptus 352a700fb2 Merge remote-tracking branch 'origin/greenkeeper/codecov-3.4.0' into greenkeeper/monorepo.babel7-20190521175803 2019-05-22 16:24:25 +10:00
koalyptus fae4ec9e07 bump TableFilter version 2019-05-22 16:24:18 +10:00
greenkeeper[bot] 226f18a6f6 chore(package): update lockfile package-lock.json 2019-05-21 21:28:45 +00:00
greenkeeper[bot] 1d58191127 chore(package): update @babel/preset-env to version 7.4.5 2019-05-21 21:28:41 +00:00
greenkeeper[bot] 1559c74fd9 chore(package): update @babel/core to version 7.4.5 2019-05-21 21:28:37 +00:00
greenkeeper[bot] 2cd30b1bfb chore(package): update lockfile package-lock.json 2019-05-15 11:23:47 +00:00
greenkeeper[bot] cd5e5589a4 chore(package): update uglifyjs-webpack-plugin to version 2.1.3 2019-05-15 11:23:43 +00:00
greenkeeper[bot] 5499093810 chore(package): update lockfile package-lock.json 2019-05-09 04:49:09 +00:00
greenkeeper[bot] df54ddda33 chore(package): update codecov to version 3.4.0 2019-05-09 04:49:04 +00:00
greenkeeper[bot] 80ebc0aa8c chore(package): update lockfile package-lock.json 2019-05-07 14:38:14 +00:00
greenkeeper[bot] a5fa336a08 chore(package): update grunt-qunit-istanbul to version 1.1.0 2019-05-07 14:38:06 +00:00
koalyptus 36d4f85f6c
Merge pull request #708 from koalyptus/greenkeeper/monorepo.babel7-20190426211543
Update babel7 to the latest version 🚀
2019-04-28 11:49:01 +10:00
koalyptus e886a6f1a8 prepare dist 2019-04-28 11:32:55 +10:00
koalyptus 7204746e5f Merge branch 'master' into greenkeeper/monorepo.babel6-20190426211543 2019-04-28 11:25:36 +10:00
koalyptus ecd33d0631 Add support template 2019-04-28 11:21:18 +10:00
greenkeeper[bot] f97394fc32 chore(package): update lockfile package-lock.json 2019-04-26 22:51:31 +00:00
greenkeeper[bot] eef0ab3bbd chore(package): update @babel/preset-env to version 7.4.4 2019-04-26 22:51:26 +00:00
greenkeeper[bot] c48b48f924 chore(package): update @babel/core to version 7.4.4 2019-04-26 22:51:23 +00:00
koalyptus d699d02914 Update feature request template 2019-04-26 22:53:03 +10:00
koalyptus 09b3f7875d
Merge pull request #706 from koalyptus/koalyptus-patch-1
Update issue templates
2019-04-26 22:34:54 +10:00
koalyptus 9c54974338 Update issue templates 2019-04-26 22:28:22 +10:00
koalyptus b89a52fb77
Merge pull request #698 from koalyptus/greenkeeper/codecov-3.3.0
Update codecov to the latest version 🚀
2019-04-20 22:47:26 +10:00
koalyptus ef46fd4295 bump tf version 2019-04-20 22:39:59 +10:00
koalyptus 8d8c8ae74c Merge branch 'master' into greenkeeper/codecov-4.3.0 2019-04-20 22:33:56 +10:00
koalyptus fafa983dac
Merge pull request #697 from koalyptus/greenkeeper/monorepo.babel7-20190402222217
Update babel7 to the latest version 🚀
2019-04-15 22:25:21 +10:00
koalyptus a19c5a106f prepare dist 2019-04-15 22:10:43 +10:00
koalyptus 1e391233dc Merge branch 'master' into greenkeeper/monorepo.babel-20190402222217 2019-04-15 21:12:35 +10:00
koalyptus aade342976
Merge pull request #696 from koalyptus/greenkeeper/eslint-5.16.0
Update eslint to the latest version 🚀
2019-04-08 16:22:18 +10:00
koalyptus 0443442916
Update package-lock.json 2019-04-05 09:41:27 +11:00
greenkeeper[bot] ed4979331c chore(package): update lockfile package-lock.json 2019-04-03 12:03:37 +00:00
greenkeeper[bot] 0e1a1ff3d1 chore(package): update codecov to version 3.3.0 2019-04-03 12:03:32 +00:00
greenkeeper[bot] e71b3a5c93 chore(package): update lockfile package-lock.json 2019-04-02 22:27:02 +00:00
greenkeeper[bot] a22b009c57 chore(package): update @babel/preset-env to version 7.4.3 2019-04-02 22:26:58 +00:00
greenkeeper[bot] f6a9a058c9 chore(package): update @babel/core to version 7.4.3 2019-04-02 22:26:54 +00:00
koalyptus f7c231b99f
Update package.json 2019-04-02 20:53:29 +11:00
greenkeeper[bot] 6f4e5a91ab chore(package): update eslint to version 5.16.0 2019-03-30 18:26:17 +00:00
koalyptus f405a45d79
Merge pull request #694 from koalyptus/greenkeeper/clean-webpack-plugin-2.0.1
Greenkeeper/clean webpack plugin 2.0.1
2019-03-27 13:59:39 +11:00
koalyptus fbe43b1db4 Fix clean-webpack-plugin usage as not backwards compatible 2019-03-27 13:49:35 +11:00
koalyptus e13201733d Merge branch 'master' into greenkeeper/clean-webpack-plugin-2.0.1 2019-03-27 13:12:25 +11:00
koalyptus 002c46297e
Merge pull request #693 from koalyptus/greenkeeper/monorepo.babel7-20190319230952
Update babel7 to the latest version 🚀
2019-03-27 11:45:50 +11:00
koalyptus 017337b2e2
Update package-lock.json 2019-03-26 22:17:50 +11:00
koalyptus 51679ad61b
Update package-lock.json 2019-03-26 22:17:07 +11:00
koalyptus bc34e8b187
Update package.json 2019-03-26 22:16:18 +11:00
greenkeeper[bot] 58e90cb766 chore(package): update lockfile package-lock.json 2019-03-19 23:14:46 +00:00
greenkeeper[bot] 3243fad4da chore(package): update @babel/preset-env to version 7.4.0 2019-03-19 23:14:42 +00:00
greenkeeper[bot] ea2a8be8b6 chore(package): update @babel/core to version 7.4.0 2019-03-19 23:14:39 +00:00
koalyptus 5e1fe901b7
Merge pull request #692 from koalyptus/greenkeeper/eslint-5.15.2
Update eslint to the latest version 🚀
2019-03-20 07:13:32 +11:00
koalyptus c001e90617 bump TableFilter version 2019-03-19 22:07:00 +11:00
greenkeeper[bot] a446c0afc0 chore(package): update lockfile package-lock.json 2019-03-16 00:10:05 +00:00
greenkeeper[bot] ff88f6c7d7 chore(package): update eslint to version 5.15.2 2019-03-16 00:10:00 +00:00
greenkeeper[bot] d46265eb57 chore(package): update lockfile package-lock.json 2019-03-14 18:54:50 +00:00
greenkeeper[bot] 3057b1949c chore(package): update clean-webpack-plugin to version 2.0.1
Closes #690
2019-03-14 18:54:47 +00:00
koalyptus bca2cee175
Merge pull request #689 from koalyptus/greenkeeper/eslint-5.15.0
Update eslint to the latest version 🚀
2019-03-06 14:01:58 +11:00
koalyptus 077eb3fe87
Update package.json 2019-03-06 13:56:56 +11:00
koalyptus 90e4367951
Update package-lock.json 2019-03-06 13:56:41 +11:00
greenkeeper[bot] 589b356bc6 chore(package): update lockfile package-lock.json 2019-03-02 06:35:38 +00:00
greenkeeper[bot] 7664e054e5 chore(package): update eslint to version 5.15.0 2019-03-02 06:35:34 +00:00
koalyptus 2dcad20d0c
Merge pull request #688 from koalyptus/greenkeeper/monorepo.babel7-20190225223535
Update babel7 to the latest version 🚀
2019-02-28 13:57:08 +11:00
koalyptus 86369ff116
Merge branch 'master' into greenkeeper/monorepo.babel7-20190225223535 2019-02-28 13:23:19 +11:00
koalyptus f1bdd8997f
Update package.json 2019-02-28 13:22:29 +11:00
koalyptus eefbf3fe41
Update package-lock.json 2019-02-28 13:22:17 +11:00
koalyptus 0b455e2ec4
Merge pull request #687 from koalyptus/greenkeeper/uglifyjs-webpack-plugin-2.1.2
Update uglifyjs-webpack-plugin to the latest version 🚀
2019-02-27 13:26:28 +11:00
koalyptus de6745821f
Update package.json 2019-02-26 21:18:40 +11:00
koalyptus f79234ea7e
Update package-lock.json 2019-02-26 21:18:07 +11:00
greenkeeper[bot] 8bcf731d3c chore(package): update lockfile package-lock.json 2019-02-25 22:37:50 +00:00
greenkeeper[bot] 5247493035 chore(package): update @babel/preset-env to version 7.3.4 2019-02-25 22:37:45 +00:00
greenkeeper[bot] 69a1fd3ee9 chore(package): update @babel/core to version 7.3.4 2019-02-25 22:37:41 +00:00
greenkeeper[bot] 9c80252935 chore(package): update lockfile package-lock.json 2019-02-25 13:34:31 +00:00
greenkeeper[bot] c22f9981e6 chore(package): update uglifyjs-webpack-plugin to version 2.1.2 2019-02-25 13:34:27 +00:00
koalyptus 04012e5a97
Merge pull request #686 from koalyptus/greenkeeper/eslint-5.14.1
Update eslint to the latest version 🚀
2019-02-19 22:20:33 +11:00
koalyptus 02997076d4
Merge branch 'master' into greenkeeper/eslint-5.14.1 2019-02-19 21:26:47 +11:00
koalyptus 9117097750
Update package.json 2019-02-19 21:26:06 +11:00
koalyptus e3f9851848
Update package-lock.json 2019-02-19 21:25:42 +11:00
koalyptus f1febe1688
Merge pull request #685 from koalyptus/679-uuid-generator-fix
fix TableFilter table id generation with more robust uuid generator
2019-02-19 21:14:50 +11:00
greenkeeper[bot] cf9a566e92 chore(package): update lockfile package-lock.json 2019-02-18 18:51:39 +00:00
greenkeeper[bot] 34e8b4099b chore(package): update eslint to version 5.14.1 2019-02-18 18:51:36 +00:00
koalyptus 495b64ecf0 fix TableFilter table id generation with more robust uuid generator 2019-02-18 22:50:04 +11:00
koalyptus 0a69a99dc5
Merge pull request #682 from koalyptus/feature-registering
Feature registering
2019-02-16 22:02:55 +11:00
koalyptus 2d9671e10d upgrade various packages 2019-02-16 21:52:06 +11:00
koalyptus 0f380c03da Merge remote-tracking branch 'origin/greenkeeper/monorepo.babel7-20190216020312' into feature-registering 2019-02-16 21:38:42 +11:00
koalyptus df85babf34 Merge remote-tracking branch 'origin/greenkeeper/codecov-3.2.0' into feature-registering 2019-02-16 21:32:51 +11:00
koalyptus 131280c1a3 merge eslint 2019-02-16 20:23:52 +11:00
greenkeeper[bot] 372473227c chore(package): update lockfile package-lock.json 2019-02-16 02:04:34 +00:00
greenkeeper[bot] cb7fc0d4fa chore(package): update @babel/core to version 7.3.3 2019-02-16 02:04:29 +00:00
greenkeeper[bot] c3b5ef529c chore(package): update lockfile package-lock.json 2019-02-15 22:06:24 +00:00
greenkeeper[bot] 89b1814c2d chore(package): update eslint to version 5.14.0 2019-02-15 22:06:18 +00:00
koalyptus 9a1202c0b5 merge master in, fix conflict 2019-02-15 21:41:56 +11:00
koalyptus 95475b022d prepare dist 2019-02-15 21:37:30 +11:00
koalyptus 8b1d3a6e23 fix extesion registering 2019-02-15 14:16:35 +11:00
greenkeeper[bot] 6b2fbd1eef chore(package): update lockfile package-lock.json 2019-02-13 02:15:43 +00:00
greenkeeper[bot] 8d1dc88f6a chore(package): update codecov to version 3.2.0 2019-02-13 02:15:38 +00:00
koalyptus 34c56e5765 Fix class name registering 2019-02-10 23:14:46 +11:00
koalyptus 87ee312fc5 undo Register class 2019-02-10 00:38:11 +11:00
koalyptus df0221d5e7 refactor feature istantiation helpers 2019-02-10 00:27:55 +11:00
koalyptus 528d587a80 continue messing around 2019-02-07 07:27:52 +11:00
koalyptus b8bdff83aa
Merge pull request #676 from koalyptus/greenkeeper/monorepo.babel7-20190205012427
Update babel7 to the latest version 🚀
2019-02-06 13:15:33 +11:00
koalyptus d40244b7e5
Update package.json 2019-02-06 12:59:41 +11:00
koalyptus ec7799b57b
Update package-lock.json 2019-02-06 12:59:29 +11:00
greenkeeper[bot] fa28abbee8 chore(package): update lockfile package-lock.json 2019-02-05 01:26:33 +00:00
greenkeeper[bot] e06dfbdc35 chore(package): update @babel/preset-env to version 7.3.1 2019-02-05 01:26:29 +00:00
koalyptus 64f56c22a4 include files in git 2019-01-22 22:23:36 +11:00
koalyptus ecfa6c64ad wip continue 2019-01-22 22:23:00 +11:00
koalyptus 37f6db7025 wip 2019-01-15 23:29:13 +11:00
koalyptus bfa440b265
Merge pull request #674 from koalyptus/webpack-dev-server-secutity-update
Webpack dev server secutity update
2019-01-06 20:51:20 +11:00
koalyptus bf9cbd0a69 prepare dist package 2019-01-06 20:43:34 +11:00
koalyptus 967ae801b4
Update package-lock.json 2019-01-06 20:30:22 +11:00
koalyptus 066c5fee56
Update package.json 2019-01-06 20:28:07 +11:00
koalyptus 807c191a01
Update package.json 2019-01-06 20:27:50 +11:00
koalyptus 9382a07c7b
Merge pull request #673 from koalyptus/greenkeeper/sugar-date-2.0.6
Greenkeeper/sugar date 2.0.6
2018-12-31 14:00:02 +11:00
koalyptus 8b09b6feab fix unit tests 2018-12-31 13:52:15 +11:00
koalyptus d733766621
Merge pull request #672 from koalyptus/greenkeeper/uglifyjs-webpack-plugin-2.1.1
Update uglifyjs-webpack-plugin to the latest version 🚀
2018-12-31 13:18:24 +11:00
koalyptus ceba24d727
Merge branch 'master' into greenkeeper/uglifyjs-webpack-plugin-2.1.1 2018-12-31 13:13:52 +11:00
koalyptus c25cae1679
Update package.json 2018-12-31 13:12:15 +11:00
koalyptus 04342ac316
Update package-lock.json 2018-12-31 13:12:02 +11:00
koalyptus 0ad57767f8
Merge pull request #671 from koalyptus/greenkeeper/grunt-shell-3.0.0
Update grunt-shell to the latest version 🚀
2018-12-28 13:52:55 +11:00
koalyptus fd56dabea8
Merge branch 'master' into greenkeeper/grunt-shell-3.0.0 2018-12-28 13:48:12 +11:00
koalyptus 0b11de4f90
Update package.json 2018-12-28 13:47:30 +11:00
koalyptus bbd0ce06ce
Update package-lock.json 2018-12-28 13:47:15 +11:00
greenkeeper[bot] 500344c64a chore(package): update lockfile package-lock.json 2018-12-27 12:49:53 +00:00
greenkeeper[bot] 5845f8c52d chore(package): update uglifyjs-webpack-plugin to version 2.1.1 2018-12-27 12:49:49 +00:00
koalyptus d232f64fa5
Merge pull request #670 from koalyptus/greenkeeper/uglifyjs-webpack-plugin-2.1.0
Update uglifyjs-webpack-plugin to the latest version 🚀
2018-12-27 21:16:04 +11:00
koalyptus 53a77d1b97
Merge branch 'master' into greenkeeper/uglifyjs-webpack-plugin-2.1.0 2018-12-27 21:12:10 +11:00
koalyptus 44ce01be4b
Update package.json 2018-12-27 21:10:15 +11:00
koalyptus 1f17364a00
Update package-lock.json 2018-12-27 21:09:48 +11:00
koalyptus a437dad841
Merge pull request #669 from koalyptus/greenkeeper/monorepo.babel7-20181220134640
Update babel7 to the latest version 🚀
2018-12-27 15:14:36 +11:00
koalyptus 99b34c07b4
Update package-lock.json 2018-12-27 14:38:21 +11:00
koalyptus ff977281c7
Update package.json 2018-12-27 14:38:05 +11:00
greenkeeper[bot] bf667cdd6f chore(package): update lockfile package-lock.json 2018-12-22 22:11:45 +00:00
greenkeeper[bot] 94d6d59593 chore(package): update grunt-shell to version 3.0.0 2018-12-22 22:11:42 +00:00
greenkeeper[bot] 1fc5fa5f8a chore(package): update lockfile package-lock.json 2018-12-22 16:31:56 +00:00
greenkeeper[bot] 34d35a3495 chore(package): update uglifyjs-webpack-plugin to version 2.1.0 2018-12-22 16:31:52 +00:00
greenkeeper[bot] 9750b07e06 chore(package): update lockfile package-lock.json 2018-12-20 13:52:14 +00:00
greenkeeper[bot] bfe6b6dc2c chore(package): update @babel/preset-env to version 7.2.3 2018-12-20 13:52:10 +00:00
koalyptus 67b1d4b65e
Merge pull request #668 from koalyptus/greenkeeper/monorepo.babel7-20181215114759
Update babel7 to the latest version 🚀
2018-12-17 13:17:18 +11:00
koalyptus c7482bec2d
Update package.json 2018-12-16 20:24:25 +11:00
koalyptus b38bc836ee
Update package-lock.json 2018-12-16 20:24:01 +11:00
greenkeeper[bot] 79d06ff09e chore(package): update lockfile package-lock.json 2018-12-15 11:52:27 +00:00
greenkeeper[bot] bd6afe484c chore(package): update @babel/preset-env to version 7.2.0 2018-12-15 11:52:23 +00:00
greenkeeper[bot] 6560392771 chore(package): update @babel/core to version 7.2.2 2018-12-15 11:52:20 +00:00
greenkeeper[bot] 599717ae14 chore(package): update lockfile package-lock.json 2018-12-05 14:32:04 +00:00
greenkeeper[bot] e96273e95f chore(package): update sugar-date to version 2.0.6
Closes #666
2018-12-05 14:32:00 +00:00
koalyptus dcc0a43258
Merge pull request #662 from koalyptus/greenkeeper/monorepo.babel7-7.1.6
Update babel7 to the latest version 🚀
2018-11-15 21:19:52 +11:00
koalyptus 31ece0ff81
Update package-lock.json 2018-11-15 20:27:35 +11:00
koalyptus db0c95e197
Update package.json 2018-11-15 20:27:07 +11:00
greenkeeper[bot] 2945c27ae9 chore(package): update lockfile package-lock.json 2018-11-14 16:43:54 +00:00
greenkeeper[bot] 786bb519b0 chore(package): update @babel/preset-env to version 7.1.6 2018-11-14 16:43:51 +00:00
greenkeeper[bot] db1ecaec42 chore(package): update @babel/core to version 7.1.6 2018-11-14 16:43:48 +00:00
koalyptus 3f74756d58
Merge pull request #661 from koalyptus/greenkeeper/clean-webpack-plugin-1.0.0
Update clean-webpack-plugin to the latest version 🚀
2018-11-14 14:01:05 +11:00
koalyptus dca79c8391
Update package-lock.json 2018-11-14 13:42:56 +11:00
koalyptus dd6de7f219
Update package.json 2018-11-14 13:42:39 +11:00
greenkeeper[bot] 4e222fd98c chore(package): update lockfile package-lock.json 2018-11-12 00:10:56 +00:00
greenkeeper[bot] e45c7ce863 chore(package): update clean-webpack-plugin to version 1.0.0 2018-11-12 00:10:52 +00:00
koalyptus b45815cfc7
Merge pull request #660 from koalyptus/greenkeeper/monorepo.babel7-7.1.5
Greenkeeper/monorepo.babel7 7.1.5
2018-11-07 13:40:58 +11:00
koalyptus 481c7c3970
Update package-lock.json 2018-11-07 13:32:52 +11:00
koalyptus 6b47928c92
Update package.json 2018-11-07 13:32:28 +11:00
greenkeeper[bot] 259a88d0c5 chore(package): update lockfile package-lock.json 2018-11-07 00:41:08 +00:00
greenkeeper[bot] 91ec79d226 chore(package): update @babel/preset-env to version 7.1.5
Closes #652
2018-11-07 00:41:04 +00:00
greenkeeper[bot] 6630a87263 chore(package): update @babel/core to version 7.1.5
Closes #652
2018-11-07 00:41:02 +00:00
koalyptus 4d4d1f4212
Merge pull request #659 from koalyptus/greenkeeper/grunt-cli-1.3.2
Update grunt-cli to the latest version 🚀
2018-11-05 17:23:26 +11:00
koalyptus 7631b51f3d
Update package-lock.json 2018-11-05 11:00:17 +11:00
koalyptus 5bde707a0c
Update package.json 2018-11-05 10:59:41 +11:00
greenkeeper[bot] 2cea817247 chore(package): update lockfile package-lock.json 2018-11-04 19:31:28 +00:00
greenkeeper[bot] 68acd1fcb7 chore(package): update grunt-cli to version 1.3.2 2018-11-04 19:31:24 +00:00
koalyptus 4d424d1d7e
Merge pull request #657 from koalyptus/656-fix-loader
fix events loader subscribes to
2018-10-27 22:12:21 +11:00
koalyptus 50fda2a900 fix events loader subscribes to 2018-10-27 21:46:27 +11:00
koalyptus 335f97a9de
Merge pull request #655 from koalyptus/greenkeeper/babel-eslint-10.0.0
Update babel-eslint to the latest version 🚀
2018-10-05 14:03:41 +10:00
koalyptus a7e0f235a3
Update package.json 2018-10-05 10:00:17 +10:00
greenkeeper[bot] d6a79e14fc chore(package): update lockfile package-lock.json 2018-09-25 22:33:52 +00:00
greenkeeper[bot] 7e780f3463 chore(package): update babel-eslint to version 10.0.0 2018-09-25 22:28:44 +00:00
koalyptus 439f183d95
Merge pull request #653 from koalyptus/greenkeeper/uglifyjs-webpack-plugin-2.0.1
Update uglifyjs-webpack-plugin to the latest version 🚀
2018-09-24 09:16:58 +02:00
koalyptus 10b80612fe
Update package.json 2018-09-24 17:02:15 +10:00
greenkeeper[bot] 72327b84cc chore(package): update lockfile package-lock.json 2018-09-18 16:43:39 +00:00
greenkeeper[bot] ba5323ab3b chore(package): update uglifyjs-webpack-plugin to version 2.0.1 2018-09-18 16:42:32 +00:00
koalyptus a9c0fd9c2f
Merge pull request #651 from koalyptus/591-linked-filters-enhancement
linked filters refactor
2018-09-17 12:02:52 +02:00
koalyptus e6049975ee remove commented out code leftovers 2018-09-17 19:34:50 +10:00
koalyptus 62a55c8d95 linked filters refactor 2018-09-17 19:32:16 +10:00
koalyptus 5d4def11fc
Merge pull request #650 from koalyptus/greenkeeper/uglifyjs-webpack-plugin-2.0.0
Update uglifyjs-webpack-plugin to the latest version 🚀
2018-09-17 10:04:36 +02:00
koalyptus 13eb677b8e
Update package.json 2018-09-17 17:53:09 +10:00
greenkeeper[bot] d48bbeaab5 chore(package): update lockfile package-lock.json 2018-09-14 16:26:57 +00:00
greenkeeper[bot] 6fec4947c4 chore(package): update uglifyjs-webpack-plugin to version 2.0.0 2018-09-14 16:24:23 +00:00
koalyptus d3634bce5f
Merge pull request #648 from koalyptus/628-highlight-auto-filter
fix unhighlight all
2018-09-12 17:58:23 +02:00
koalyptus 6813debb6e fix unit tests 2018-09-13 01:52:51 +10:00
koalyptus b14667a345 more unit tests 2018-09-13 01:44:23 +10:00
koalyptus 2f825a25b4 fix unhighlight all 2018-09-13 01:23:20 +10:00
koalyptus cca223c4d4
Merge pull request #647 from koalyptus/greenkeeper/monorepo.babel7-7.0.1
Update babel7 to the latest version 🚀
2018-09-12 16:13:42 +02:00
koalyptus 09243a9bdb include grunt contrib pkg bumps 2018-09-13 00:10:07 +10:00
greenkeeper[bot] 24e0f3d184 chore(package): update lockfile 2018-09-12 03:40:22 +00:00
greenkeeper[bot] d70cf23624 chore(package): update @babel/core to version 7.0.1 2018-09-12 03:38:51 +00:00
koalyptus 2d963e782f
Merge pull request #641 from koalyptus/greenkeeper/babel-loader-8.0.2
chore(package): update babel-loader to version 8.0.2
2018-09-10 10:11:18 +02:00
koalyptus c100f0f63f
Merge branch 'master' into greenkeeper/babel-loader-8.0.2 2018-09-10 10:05:32 +02:00
koalyptus 875fdc2603 Fix babel-loader 8.x deps, keep old babel deps for test config... 2018-09-10 18:06:40 +10:00
koalyptus 4bdf873ec8
Merge pull request #643 from koalyptus/greenkeeper/codecov-3.1.0
Update codecov to the latest version 🚀
2018-09-08 15:59:08 +02:00
koalyptus d1875f19f2
Update package.json 2018-09-06 14:10:30 +10:00
greenkeeper[bot] 5254983778 chore(package): update codecov to version 3.1.0 2018-09-04 23:33:04 +00:00
koalyptus 7e13d59d0f
Update package.json 2018-09-03 10:40:41 +10:00
greenkeeper[bot] a66402e139 chore(package): update babel-loader to version 8.0.2
Closes #640
2018-09-03 00:32:39 +00:00
koalyptus 8cb8f74fa3
Merge pull request #639 from koalyptus/greenkeeper/babel-eslint-9.0.0
Update babel-eslint to the latest version 🚀
2018-08-29 09:21:17 +10:00
koalyptus c5775ae8aa
Update package.json 2018-08-29 09:14:39 +10:00
greenkeeper[bot] a10d3a2830 chore(package): update babel-eslint to version 9.0.0 2018-08-28 02:30:08 +00:00
koalyptus 2e089a1823
Merge pull request #638 from koalyptus/fixed-headers
sticky headers enhancement
2018-08-26 11:48:13 +10:00
koalyptus 3231da9760 sticky headers enhancement 2018-08-26 11:56:51 +10:00
koalyptus 7533499c40
Merge pull request #637 from koalyptus/greenkeeper/grunt-cli-1.3.1
Update grunt-cli to the latest version 🚀
2018-08-20 17:07:37 +10:00
koalyptus 80cf351eab
Update package.json 2018-08-20 16:46:35 +10:00
greenkeeper[bot] d790156373 chore(package): update grunt-cli to version 1.3.1 2018-08-19 03:59:49 +00:00
koalyptus 70d791f41c
Merge pull request #636 from koalyptus/greenkeeper/grunt-cli-1.3.0
Update grunt-cli to the latest version 🚀
2018-08-17 11:22:48 +10:00
koalyptus f1f28b51cb
Update package.json 2018-08-17 09:40:50 +10:00
greenkeeper[bot] 8a94f2ffd2 chore(package): update grunt-cli to version 1.3.0 2018-08-16 00:10:38 +00:00
koalyptus a0f9f28397
Merge pull request #634 from koalyptus/greenkeeper/uglifyjs-webpack-plugin-1.3.0
Update uglifyjs-webpack-plugin to the latest version 🚀
2018-08-15 13:56:12 +10:00
koalyptus 71292db999
Update package.json 2018-08-15 13:50:38 +10:00
greenkeeper[bot] 42a40a295b chore(package): update uglifyjs-webpack-plugin to version 1.3.0 2018-08-14 15:46:54 +00:00
koalyptus 7a90cb5b13
Merge pull request #633 from koalyptus/donate
please npm
2018-08-09 10:08:02 +10:00
koalyptus 7eecd95122 please npm 2018-08-08 22:25:55 +10:00
koalyptus a45217bc9f add donate badge 2018-08-08 21:15:10 +10:00
koalyptus d14a0a359a
Merge pull request #632 from koalyptus/donate
add donate badge
2018-08-08 21:13:20 +10:00
koalyptus e09bab000b
Merge pull request #626 from koalyptus/625-fix-empty-filter-operator
refine empty-nonempty operator checks
2018-07-29 11:12:02 +10:00
koalyptus efffa40248 refine empty-nonempty operator checks 2018-07-29 11:18:16 +10:00
koalyptus 50afb94340
Merge pull request #622 from koalyptus/greenkeeper/babel-eslint-8.2.6
Update babel-eslint to the latest version 🚀
2018-07-16 09:52:29 +10:00
koalyptus d35ea7cb26
Update package.json 2018-07-13 16:31:21 +10:00
greenkeeper[bot] 52705e56f7 chore(package): update babel-eslint to version 8.2.6 2018-07-12 14:10:28 +00:00
koalyptus b34e5696f3
Merge pull request #621 from koalyptus/greenkeeper/codecov-3.0.4
Update codecov to the latest version 🚀
2018-07-09 13:11:21 +10:00
koalyptus 606cc00393
Update package.json 2018-07-09 10:41:08 +10:00
greenkeeper[bot] c728209c92 chore(package): update codecov to version 3.0.4 2018-07-09 00:17:55 +00:00
koalyptus 2e3bdda8bc
Merge pull request #620 from koalyptus/greenkeeper/codecov-3.0.3
Update codecov to the latest version 🚀
2018-07-06 20:18:09 +10:00
greenkeeper[bot] 7bc7b16cfc chore(package): update codecov to version 3.0.3 2018-07-06 04:41:52 +00:00
koalyptus c5bc7cbb33
Merge pull request #618 from koalyptus/greenkeeper/eslint-5.0.1
Update eslint to the latest version 🚀
2018-07-02 19:26:57 +10:00
koalyptus ec6d0779a1
Update package.json 2018-06-29 14:20:16 +10:00
greenkeeper[bot] bcbfe5251f chore(package): update eslint to version 5.0.1 2018-06-26 05:39:20 +00:00
koalyptus 453ff1c59c
Merge pull request #617 from koalyptus/greenkeeper/uglifyjs-webpack-plugin-1.2.7
Update uglifyjs-webpack-plugin to the latest version 🚀
2018-06-26 14:23:31 +10:00
koalyptus 948055da09
Merge branch 'master' into greenkeeper/uglifyjs-webpack-plugin-1.2.7 2018-06-26 13:54:36 +10:00
koalyptus f534a8b23f
Update package.json 2018-06-26 13:54:09 +10:00
koalyptus 6c23ae883f
Merge pull request #616 from koalyptus/greenkeeper/babel-eslint-8.2.5
Update babel-eslint to the latest version 🚀
2018-06-26 13:52:34 +10:00
koalyptus 55e4d6b511
Merge branch 'master' into greenkeeper/babel-eslint-8.2.5 2018-06-26 13:34:16 +10:00
koalyptus 2d5f7401f9
Update package.json 2018-06-26 13:33:34 +10:00
koalyptus 00143a686b
Merge pull request #615 from koalyptus/greenkeeper/eslint-5.0.0
Update eslint to the latest version 🚀
2018-06-26 13:32:26 +10:00
koalyptus 46f7028580
Update package.json 2018-06-26 13:14:45 +10:00
greenkeeper[bot] 313336ab5f chore(package): update uglifyjs-webpack-plugin to version 1.2.7 2018-06-25 18:29:06 +00:00
greenkeeper[bot] 89851eae3b chore(package): update babel-eslint to version 8.2.5 2018-06-23 16:19:05 +00:00
greenkeeper[bot] e49538c442 chore(package): update eslint to version 5.0.0 2018-06-23 05:36:13 +00:00
koalyptus cb0aa73a6d
bump version - babel-eslint upgrade 2018-06-23 11:15:43 +10:00
koalyptus 9b89b78f38
Merge pull request #614 from koalyptus/greenkeeper/babel-eslint-8.2.4
Update babel-eslint to the latest version 🚀
2018-06-23 11:06:25 +10:00
greenkeeper[bot] 1a32ef216b chore(package): update babel-eslint to version 8.2.4 2018-06-22 20:32:47 +00:00
koalyptus bcf7189bbc
Merge pull request #612 from koalyptus/greenkeeper/uglifyjs-webpack-plugin-1.2.6
Update uglifyjs-webpack-plugin to the latest version 🚀
2018-06-21 15:25:46 +10:00
greenkeeper[bot] 9a55c86e5f chore(package): update uglifyjs-webpack-plugin to version 1.2.6 2018-06-20 14:49:58 +00:00
koalyptus c710fa3585
Merge pull request #611 from koalyptus/580-sticky-head
580 sticky head
2018-06-17 21:29:01 +10:00
koalyptus a5164f4ba5 remove 1px gap on sticky headers 2018-06-17 21:21:41 +10:00
koalyptus 0babe0249e test case 2018-06-17 20:39:04 +10:00
koalyptus ca4f0f2afa remove sticky css class on destroy 2018-06-17 20:23:41 +10:00
koalyptus 00150bc9e1 implement sticky headers 2018-06-16 00:21:26 +10:00
koalyptus 46b21b4a20 fix webpack-cli upgrade (remaining es2015 preset ref) 2018-06-15 21:30:00 +10:00
koalyptus 89b0cf843a try name property in travis releases provider 2018-06-15 21:06:57 +10:00
koalyptus 946f600260 re-instate source maps 2018-06-15 20:47:30 +10:00
koalyptus 0cd8fb2aa3
Merge pull request #609 from koalyptus/607-sort-support-cell-parser
missing file
2018-06-09 22:44:34 +10:00
koalyptus ad8c86c599 missing file 2018-06-09 22:50:45 +10:00
koalyptus bf1bdc5a0e
Merge pull request #608 from koalyptus/607-sort-support-cell-parser
support cellparser in sort adapter, fix function name with uglifyjs option
2018-06-09 22:14:30 +10:00
koalyptus ed01c6e201 support cellparser in sort adapter, fix function name with uglifyjs option 2018-06-09 22:09:37 +10:00
koalyptus b4905f7703
Merge pull request #604 from koalyptus/603-alternate-rows-fix
alternate rows background inconsistency fix
2018-06-02 13:51:13 +10:00
koalyptus 2cc28e8072 alternate rows background inconsistency fix 2018-06-02 13:48:07 +10:00
koalyptus 521d02c374
Merge pull request #602 from koalyptus/598-pagination-toggle-fix
introduce bound helper function
2018-05-20 21:46:03 +10:00
koalyptus fe51fdecb8 introduce bound helper function 2018-05-20 21:43:20 +10:00
koalyptus bfa23c3b6e
Merge pull request #601 from koalyptus/599-colvis-gridlayout-fix
fix colvis bug with grid-layout on
2018-05-18 16:20:56 +10:00
koalyptus 2abd81906b url typo in package.json 2018-05-18 16:05:55 +10:00
koalyptus f1e046e331 fix colvis bug with grid-layout on 2018-05-18 15:50:34 +10:00
koalyptus ea8ca2a125 remove deployment to gh-pages, correct website url, bump version 2018-05-06 11:29:37 +10:00
koalyptus 6bc6c8a8eb remove deployment to gh-pages, correct website url 2018-05-06 11:24:38 +10:00
koalyptus c0520dd4bb deploy dist and docs to s3, separate travis providers 2018-05-06 10:46:56 +10:00
koalyptus 3d7945b09c deploy dist and docs to s3, keep deployment to gh-pages 2018-05-06 10:34:49 +10:00
koalyptus 84c964bf13 bump version 2018-05-05 19:31:45 +10:00
koalyptus c7d6de72f7 revert gh-pages in travis 2018-05-05 18:13:54 +10:00
koalyptus 81f31a3106 fix git tag cmd in travis (5) 2018-05-05 17:41:30 +10:00
koalyptus 3995dee394 fix git tag cmd in travis (4) 2018-05-05 17:26:27 +10:00
koalyptus 7540169fcd fix git tag cmd in travis (3) 2018-05-05 17:23:24 +10:00
koalyptus 4bff89b70c fix git tag cmd in travis (2) 2018-05-05 16:57:11 +10:00
koalyptus c8df8992b3 fix git tag cmd in travis (1) 2018-05-05 16:47:10 +10:00
koalyptus 4889b29cda fix git tag cmd in travis 2018-05-05 16:38:25 +10:00
koalyptus b3101a8871
Merge pull request #597 from koalyptus/gh-pages-travis
gh-pages provider in travis
2018-05-05 16:19:26 +10:00
koalyptus bf2f2bd747 gh-pages provider in travis 2018-05-05 16:14:20 +10:00
koalyptus b08b517fa7
Merge pull request #593 from koalyptus/greenkeeper/esdoc-1.1.0
Update esdoc to the latest version 🚀
2018-05-01 08:11:50 +10:00
koalyptus f2c5edbfb8
Update package.json 2018-04-30 13:11:41 +10:00
greenkeeper[bot] ca6ced712a chore(package): update esdoc to version 1.1.0 2018-04-29 10:36:49 +00:00
koalyptus 0d95699fa6 bump version for codecov update + fix build error 2018-04-29 18:01:36 +10:00
koalyptus 4378141d7d Conditional git tag command in travis 2018-04-29 17:42:31 +10:00
koalyptus 0631fd2ef7
Merge pull request #592 from koalyptus/greenkeeper/codecov-3.0.1
Update codecov to the latest version 🚀
2018-04-29 06:54:59 +10:00
greenkeeper[bot] 7cbb38d9ba chore(package): update codecov to version 3.0.1 2018-04-27 00:19:37 +00:00
koalyptus edd2494899
Merge pull request #590 from koalyptus/test-pr-travis-deploy
Test pr travis deploy
2018-04-22 22:11:36 +10:00
koalyptus 49eb4b7bd6 bump package version 2018-04-22 22:17:02 +10:00
koalyptus 5d4627277a Merge branch 'master' into test-pr-travis-deploy 2018-04-22 22:16:10 +10:00
koalyptus 907ccd5e4a
Merge pull request #589 from koalyptus/test-pr-travis-deploy
Define master branch in deploy section travis.yaml
2018-04-22 21:59:22 +10:00
koalyptus c26e6d3c4b Define master branch in deploy section travis.yaml 2018-04-22 21:58:50 +10:00
koalyptus e1106f23a8 travis: git tags automation (10) 2018-04-22 21:35:09 +10:00
koalyptus 7909cde78b travis: git tags automation (9) 2018-04-22 21:28:20 +10:00
koalyptus bc416e0e39 travis: git tags automation (8) 2018-04-22 21:14:47 +10:00
koalyptus 934ba4add0 travis: git tags automation (7) 2018-04-22 20:42:53 +10:00
koalyptus 73fc78e9e3 travis: git tags automation (6) 2018-04-22 15:39:55 +10:00
koalyptus c1000b7684 travis: git tags automation (5) 2018-04-22 15:25:41 +10:00
koalyptus a34009f1e9 travis: git tags automation (4) 2018-04-22 15:08:41 +10:00
koalyptus 51e27c4a2f travis: git tags automation (3) 2018-04-22 14:24:10 +10:00
koalyptus 2fee4d95f2 travis: git tags automation (2) 2018-04-22 14:12:22 +10:00
koalyptus 5b6919ba39 travis: git tags automation (1) 2018-04-22 13:37:49 +10:00
koalyptus 974bb3cc77 travis: git tags automation (0) 2018-04-22 13:06:51 +10:00
koalyptus 1a1560d636 Add missing starter.html file 2018-04-18 10:27:41 +10:00
koalyptus 2d3f67d504 $npm_package_version 2018-04-15 22:48:19 +10:00
koalyptus 81c593382a Merge branch 'toolbar-min-width-1' 2018-04-15 22:33:24 +10:00
koalyptus 62cab3ac2c Add git config to before_script in travis yaml 2018-04-15 22:32:59 +10:00
koalyptus 4ac92a3e73 Merge branch 'toolbar-min-width-0' 2018-04-15 22:10:28 +10:00
koalyptus da8977433d wip 2018-04-15 22:06:47 +10:00
koalyptus cde2e8a326
Merge pull request #588 from koalyptus/toolbar-min-width
amend release command (0)
2018-04-15 21:25:15 +10:00
koalyptus 7b03e23f3c amend release command (0) 2018-04-15 17:52:13 +10:00
koalyptus dc3d40b12c
Merge pull request #587 from koalyptus/toolbar-min-width
Toolbar min-width + add npm release command
2018-04-15 17:25:15 +10:00
koalyptus 48674c3b31 Toolbar min-width + add npm release command 2018-04-15 17:18:14 +10:00
koalyptus a92acfa615
Merge pull request #586 from koalyptus/greenkeeper/babel-eslint-8.2.3
Update babel-eslint to the latest version 🚀
2018-04-14 15:19:56 +10:00
greenkeeper[bot] be1bdf72cd chore(package): update babel-eslint to version 8.2.3 2018-04-13 15:37:24 +00:00
koalyptus b6d9bddc6f
Merge pull request #583 from koalyptus/auto-min-width
introduce default column width
2018-04-07 10:49:15 +10:00
koalyptus 025717f61c introduce default column width 2018-04-07 10:45:33 +10:00
koalyptus e09d30c2cd
Merge pull request #581 from koalyptus/auto-min-width
ensure table layout is fixed when cols widths are defined
2018-04-02 20:35:17 +10:00
koalyptus 39bbe6a19a ensure table layout is fixed when cols widths are defined 2018-04-02 18:01:28 +10:00
koalyptus 2f7b650f5b
Merge pull request #578 from koalyptus/greenkeeper/eslint-4.19.1
Update eslint to the latest version 🚀
2018-03-22 13:09:20 +11:00
greenkeeper[bot] 85092bbd1c chore(package): update eslint to version 4.19.1 2018-03-22 00:59:23 +00:00
koalyptus 3bed943a42
Merge pull request #577 from koalyptus/decommission-grunt-contrib-stylus
Decommission grunt contrib stylus
2018-03-18 13:35:44 +11:00
koalyptus 2452a0bd9e convert var to const in webpack configs 2018-03-18 13:31:54 +11:00
koalyptus 98aca44cb9 remove unused packages from package.json 2018-03-18 13:29:47 +11:00
koalyptus 33ed3cc194 prepare for PR 2018-03-18 13:20:44 +11:00
koalyptus 2da8a56659 wip 2018-03-18 12:59:33 +11:00
koalyptus 71d5cd7a49
Merge pull request #576 from koalyptus/greenkeeper/eslint-4.19.0
Update eslint to the latest version 🚀
2018-03-17 08:44:58 +11:00
greenkeeper[bot] 05c2d6b666 chore(package): update eslint to version 4.19.0 2018-03-16 21:32:05 +00:00
koalyptus 50f4a0014b wip 2018-03-16 16:21:41 +11:00
koalyptus 07eebbd528
Merge pull request #574 from koalyptus/kill-grunt-webpack
Kill grunt webpack
2018-03-03 10:59:30 +11:00
koalyptus 9ccc4dbfd4 update pr template 2018-03-03 10:51:29 +11:00
koalyptus 9d184df49a update readme 2018-03-03 10:49:32 +11:00
koalyptus d664ebb780 Merge branch 'master' into kill-grunt-webpack 2018-03-03 10:32:07 +11:00
koalyptus 0226300af8
Merge pull request #575 from koalyptus/greenkeeper/eslint-4.18.2
Update eslint to the latest version 🚀
2018-03-03 09:53:24 +11:00
greenkeeper[bot] 1e8e4a6467 chore(package): update eslint to version 4.18.2 2018-03-02 20:54:28 +00:00
koalyptus 0ec96ed520 remove accidental npm dep 2018-03-02 23:26:31 +11:00
koalyptus 11d01b1661 remove grunt-babel 2018-03-02 23:24:16 +11:00
koalyptus 2d0219b54d wip 2018-03-02 17:12:15 +11:00
koalyptus 317d795974
Merge pull request #573 from koalyptus/greenkeeper/webpack-4.0.1
Greenkeeper/webpack 4.0.1
2018-02-28 22:13:07 +11:00
koalyptus f2f853c517 Adopt webpack 4 2018-02-28 21:53:57 +11:00
greenkeeper[bot] 9468602f3d chore(package): update webpack to version 4.0.1
Closes #571
2018-02-26 20:36:41 +00:00
koalyptus cc0932f5f7
Merge pull request #572 from koalyptus/greenkeeper/webpack-dev-server-3.0.0
Update webpack-dev-server to the latest version 🚀
2018-02-26 09:03:16 +11:00
greenkeeper[bot] f97ff3a52d chore(package): update webpack-dev-server to version 3.0.0 2018-02-25 11:21:01 +00:00
koalyptus 8575d0ea68
Merge pull request #570 from koalyptus/greenkeeper/eslint-4.18.1
Update eslint to the latest version 🚀
2018-02-21 21:51:30 +11:00
koalyptus d274876976
Merge pull request #569 from koalyptus/greenkeeper/babel-eslint-8.2.2
Update babel-eslint to the latest version 🚀
2018-02-21 08:58:52 +11:00
greenkeeper[bot] a9737da2f6 chore(package): update eslint to version 4.18.1 2018-02-20 21:40:23 +00:00
greenkeeper[bot] 62964c2478 chore(package): update babel-eslint to version 8.2.2 2018-02-20 11:17:00 +00:00
koalyptus 71e7012ba0
Merge pull request #568 from koalyptus/greenkeeper/eslint-4.18.0
Update eslint to the latest version 🚀
2018-02-17 11:38:50 +11:00
greenkeeper[bot] 4a3fbbb736 chore(package): update eslint to version 4.18.0 2018-02-16 23:09:39 +00:00
koalyptus ee128f9d80
Merge pull request #567 from koalyptus/565-562-fixes
565 562 fixes
2018-02-13 22:11:23 +11:00
koalyptus 9b29d1632e dist package 2018-02-13 21:44:21 +11:00
koalyptus 1946d75125 Fix TableFilter start-up when 1 header row only 2018-02-13 14:15:35 +11:00
koalyptus 83ff0aab79
Merge pull request #566 from koalyptus/565-562-fixes
565 562 fixes
2018-02-11 17:06:31 +11:00
koalyptus 8dbc307a39 PR feedback (0) 2018-02-11 17:04:30 +11:00
koalyptus c7eefc8ddc show no results banner at start-up if no working rows #562 2018-02-10 22:12:16 +11:00
koalyptus 0e2d17714d fix unit tests 2018-02-10 21:29:36 +11:00
koalyptus 650959237b refactor setCheckListValues in CheckList class 2018-02-10 21:11:33 +11:00
koalyptus 4a10876a96 wip 2018-02-09 22:45:14 +11:00
koalyptus d5ef7afa1e
Merge pull request #563 from koalyptus/refactor-auto-filter-config
Refactor auto filter config
2018-02-04 22:13:33 +11:00
koalyptus 4cf9a4081d Merge branch 'master' into refactor-auto-filter-config 2018-02-04 22:02:58 +11:00
koalyptus c1e26349ef fix build (0) 2018-02-04 21:36:53 +11:00
koalyptus 16b2997a71
Merge pull request #564 from koalyptus/greenkeeper/eslint-4.17.0
Update eslint to the latest version 🚀
2018-02-03 19:01:13 +11:00
greenkeeper[bot] ab273644e5 chore(package): update eslint to version 4.17.0 2018-02-03 02:31:02 +00:00
koalyptus 731909a267 Remove provate members from auto-generated documentation 2018-02-02 22:34:17 +11:00
koalyptus 7f75e23b1b introduce isKeyPressed in event module 2018-02-02 22:26:28 +11:00
koalyptus 55eadd72eb wip 2018-01-29 23:20:52 +11:00
koalyptus 4855c9064b
Merge pull request #560 from koalyptus/558-filter-cells-with-html-elements
558 filter cells with html elements
2018-01-23 14:36:48 +11:00
koalyptus 032bdd53b0 remove commented out code 2018-01-23 14:18:18 +11:00
koalyptus f73aa02733 fix tests 2018-01-23 14:14:41 +11:00
koalyptus 029f2c35e8 wip 2018-01-21 22:38:22 +11:00
koalyptus 52a514088b
Merge pull request #559 from koalyptus/greenkeeper/eslint-4.16.0
Update eslint to the latest version 🚀
2018-01-21 14:03:46 +11:00
greenkeeper[bot] c7756d8d58 chore(package): update eslint to version 4.16.0 2018-01-20 04:30:35 +00:00
koalyptus 054423f10d
Merge pull request #557 from koalyptus/deprecate-grunt-esdoc
Remove grunt-esdoc, add grunt-shell pointing to esdoc npm command
2018-01-16 22:22:52 +11:00
koalyptus cccc4b71cf Remove grunt-esdoc, add grunt-shell pointing to esdoc npm command 2018-01-16 22:13:31 +11:00
koalyptus db2bb7de18
Merge pull request #555 from koalyptus/deprecate-grunt-eslint
Deprecate grunt eslint
2018-01-12 23:07:10 +11:00
koalyptus 740cce0551 bump babel-eslint version 2018-01-12 22:40:57 +11:00
koalyptus f6a93f7f00 remove grunt-eslint 2018-01-12 22:39:49 +11:00
koalyptus b6db436bca
Merge pull request #554 from koalyptus/greenkeeper/babel-eslint-8.2.0
Update babel-eslint to the latest version 🚀
2018-01-12 21:24:26 +11:00
greenkeeper[bot] 158c8835f9 chore(package): update babel-eslint to version 8.2.0 2018-01-08 23:20:26 +00:00
koalyptus 7a2bc50a56
Merge pull request #553 from koalyptus/545-state-persistence-type-precedence
545 state persistence type precedence
2018-01-08 21:50:56 +11:00
koalyptus 74cea36219 PR feedback 2018-01-08 21:38:55 +11:00
koalyptus 2deeb5d57a Fix multiple state type persistence at start-up 2018-01-07 22:48:35 +11:00
koalyptus 619c272469 Merge branch 'master' into 545-state-persistence-type-precedence 2018-01-07 20:36:48 +11:00
koalyptus 7862bc68d0
Merge pull request #552 from koalyptus/travis-s3-cloudfront
undo s3/cloudfront deployment travis config
2018-01-05 22:16:28 +11:00
koalyptus e2e8331a08 undo s3/cloudfront deployment travis config 2018-01-05 22:08:16 +11:00
koalyptus 3134ee804b
Merge pull request #551 from koalyptus/travis-s3-cloudfront
s3/cloudfront deployment travis config (1)
2018-01-05 16:56:33 +11:00
koalyptus 1c930a0184 s3/cloudfront deployment travis config (1) 2018-01-05 16:50:38 +11:00
koalyptus 51f188e63f
Merge pull request #550 from koalyptus/travis-s3-cloudfront
s3/cloudfront deployment travis config
2018-01-05 16:18:58 +11:00
koalyptus 2ca11374a0 s3/cloudfront deployment travis config 2018-01-05 16:06:08 +11:00
koalyptus 79367df924 build 2018-01-03 13:07:15 +11:00
koalyptus fe384896d5 wip 2017-12-27 23:13:44 +11:00
koalyptus f8c5d081d4
Merge pull request #549 from koalyptus/single-filter-columns
Single filter columns
2017-12-26 21:58:22 +11:00
koalyptus 3ff774d78f Move single filter css class definition in single_filter literal object 2017-12-26 21:25:28 +11:00
koalyptus 33ae62cab7 Merge branch 'master' into single-filter-columns 2017-12-26 20:46:08 +11:00
koalyptus 8be5990a02
Merge pull request #548 from koalyptus/greenkeeper/babel-eslint-8.1.2
Update babel-eslint to the latest version 🚀
2017-12-26 15:11:22 +11:00
greenkeeper[bot] 88d31090b4 chore(package): update babel-eslint to version 8.1.2 2017-12-26 02:17:18 +00:00
koalyptus fbfa2fdf96
Merge pull request #546 from koalyptus/greenkeeper/babel-eslint-8.1.0
Update babel-eslint to the latest version 🚀
2017-12-25 22:27:59 +11:00
koalyptus f447199905
Update package.json 2017-12-25 22:15:17 +11:00
koalyptus be67034e02
Update .eslintrc 2017-12-25 22:00:58 +11:00
greenkeeper[bot] a01c914f0a chore(package): update babel-eslint to version 8.1.0 2017-12-24 07:17:53 +00:00
koalyptus c288fe44ce
Update PULL_REQUEST_TEMPLATE.md 2017-12-17 22:50:01 +11:00
koalyptus dc05239d57
Merge pull request #544 from koalyptus/single-filter-columns
exclude columns from Single filter filtering
2017-12-17 22:21:45 +11:00
koalyptus 42fb561866 exclude columns from Single filter filtering 2017-12-17 22:02:56 +11:00
koalyptus 95c8206eb7
Create PULL_REQUEST_TEMPLATE.md 2017-12-16 13:41:38 +11:00
koalyptus 26beced5c7
Merge pull request #543 from koalyptus/539-persist-regex-url-hash
fix selectOptions on CheckList to use checkbox value instead of text
2017-12-10 21:56:17 +11:00
koalyptus cf7a53354d fix selectOptions on CheckList to use checkbox value instead of text 2017-12-10 21:31:41 +11:00
koalyptus 653b1ce006
Merge pull request #542 from koalyptus/refactor-reset-button-options
Refactor reset button options
2017-12-08 22:10:43 +11:00
koalyptus d69f60aced more unit tests 2017-12-08 21:38:28 +11:00
koalyptus 949f21f446 bumped version to 0.6.8 2017-12-07 22:51:21 +11:00
koalyptus 722c420dc6 prepare dist 2017-12-07 22:48:00 +11:00
koalyptus 590dd8316c resolve conflicts 2017-12-07 22:38:24 +11:00
koalyptus 376102c801 refactor reset button options under a structured literal object 2017-12-07 22:32:21 +11:00
koalyptus a243c96dd3
Merge pull request #541 from maciex/fix_hidden_rows_in_tests
Fix hidden rows in tests
2017-12-07 22:29:12 +11:00
Maciej Sitarz 631f6bdb5c Commit missing files from ./dist 2017-12-07 12:14:18 +01:00
Maciej Sitarz fc089f1b73 Clear filters so the page after tests shows all rows 2017-12-07 10:16:21 +01:00
Maciej Sitarz dfa93b378b Bump version to v.0.6.7 2017-12-07 10:01:28 +01:00
Maciej Sitarz 0affe2c187 Rebuild and update ./dist 2017-12-06 22:08:58 +01:00
Maciej Sitarz 8231252f34 Merge branch 'fix_regex_with_stars' 2017-12-06 22:05:51 +01:00
Maciej Sitarz 75faca6e8d First search for rgx: then for other operators 2017-12-06 21:51:36 +01:00
Maciej Sitarz 4a6ae393a5 Add tests for regex with start(*) and plus(+) 2017-12-06 21:50:50 +01:00
koalyptus 0e669bcc45
Merge pull request #538 from koalyptus/filter-font-size
enforce styling for label element in checklist filter
2017-12-05 13:56:20 +11:00
koalyptus 08fb37b982 enforce styling for label element in checklist filter 2017-12-05 12:55:45 +11:00
koalyptus bde954e570
Merge pull request #536 from koalyptus/filter-font-size
harmonise font-size across filter types
2017-12-04 22:30:47 +11:00
koalyptus 78f6df704b harmonise font-size across filter types 2017-12-04 22:15:09 +11:00
koalyptus 7cf9be1342
Merge pull request #535 from koalyptus/rows-iterator
Rows iterator
2017-12-03 22:07:15 +11:00
koalyptus 86a650ff6d tidy-up code (2) 2017-12-03 21:57:07 +11:00
koalyptus 13adb6fb3a Merge branch 'master' into rows-iterator 2017-12-03 21:48:35 +11:00
koalyptus f2d54839c3 tidy-up code 2017-12-03 21:48:00 +11:00
koalyptus 9abc9802bd
Merge pull request #534 from koalyptus/greenkeeper/babel-eslint-8.0.3
Update babel-eslint to the latest version 🚀
2017-12-02 20:30:09 +11:00
greenkeeper[bot] 82a03d428c chore(package): update babel-eslint to version 8.0.3 2017-12-01 18:20:55 +00:00
koalyptus 0b5160b45d fix merge conflicts 2017-12-01 21:49:08 +11:00
koalyptus fca1fcf23c
Merge pull request #533 from koalyptus/531-popup-filters-1-row
531 popup filters 1 row
2017-11-30 14:43:22 +11:00
koalyptus e311aa36f1 Add missing files to git 2017-11-30 14:36:03 +11:00
koalyptus 9b54c10bc6 tidy-up code 2017-11-30 14:00:10 +11:00
koalyptus eb62703e50 remove commented out code 2017-11-30 13:57:11 +11:00
koalyptus 81062452e2 wip 2017-11-27 19:34:24 +11:00
koalyptus 6e72912c90 add missing files to git 2017-11-26 17:56:24 +11:00
koalyptus 52999f000e loops refactor (1) 2017-11-26 17:51:13 +11:00
koalyptus 6999b0c7f9 Continue loops refactor 2017-11-11 21:42:49 +11:00
koalyptus e205a6b15a wip 2017-11-10 22:29:37 +11:00
koalyptus fbeb52bda2
Merge pull request #528 from koalyptus/greenkeeper/babel-eslint-8.0.2
Update babel-eslint to the latest version 🚀
2017-11-07 09:27:33 +11:00
greenkeeper[bot] 465b216e01 chore(package): update babel-eslint to version 8.0.2 2017-11-06 20:32:00 +00:00
koalyptus ff622ea585
Merge pull request #525 from koalyptus/highlight-active-column
Highlight active column
2017-11-01 22:44:08 +11:00
koalyptus 6a0179681b unit tests 2017-11-01 22:11:24 +11:00
koalyptus 68adc86cbc highlight each cell of an active column 2017-10-29 21:36:15 +11:00
koalyptus e661005ff8 Add eachCol iterator 2017-10-28 22:33:12 +11:00
koalyptus a861cff760
Merge pull request #523 from koalyptus/519-tbody-working-rows
519 tbody working rows
2017-10-28 16:18:59 +11:00
koalyptus 12e4052a9f more unit tests 2017-10-28 16:06:36 +11:00
koalyptus e9441fe1d5 Add empty content css mixin for empty containers in toolbar 2017-10-27 23:00:10 +11:00
koalyptus 175a23934f Merge pull request #522 from koalyptus/519-tbody-working-rows
519 tbody working rows
2017-10-26 14:08:20 +11:00
koalyptus a757bd02fa more unit tests 2017-10-26 13:35:55 +11:00
koalyptus b03ec21a28 unit tests 2017-10-25 22:23:43 +11:00
koalyptus 5f66df7e6a Use tbody for working rows 2017-10-25 17:05:39 +11:00
koalyptus 5a10841f84 Merge branch 'master' into 519-tbody-working-rows 2017-10-24 21:30:56 +11:00
koalyptus 2ef37ed58d Merge pull request #521 from koalyptus/greenkeeper/codecov-3.0.0
Update codecov to the latest version 🚀
2017-10-23 21:49:35 +11:00
greenkeeper[bot] 828a42f938 chore(package): update codecov to version 3.0.0 2017-10-23 06:37:41 +00:00
koalyptus 4428f7b48b Renamed always_visible_rows option exlucde_rows 2017-10-22 20:57:01 +11:00
koalyptus e855fc5bbd Rename visibleRows excludeRows 2017-10-20 23:33:18 +11:00
koalyptus a7f0f442d8 Merge pull request #518 from koalyptus/greenkeeper/codecov-2.3.1
Update codecov to the latest version 🚀
2017-10-15 07:51:22 +11:00
greenkeeper[bot] 2a424e7f6f chore(package): update codecov to version 2.3.1 2017-10-14 14:05:27 +00:00
koalyptus 50f537fbfc Merge pull request #516 from koalyptus/toolbar-refactor
Toolbar refactor
2017-10-10 13:10:55 +11:00
koalyptus 7ba78c94ae Reach doc threshold 2017-10-09 22:15:08 +11:00
koalyptus 763fbcc86e unit tests 2017-10-09 21:56:58 +11:00
koalyptus 3abca0ef22 wip (3) 2017-10-08 21:56:12 +11:00
koalyptus 7888a8ee24 wip (3) 2017-10-08 21:14:25 +11:00
koalyptus abec798b27 wip (2) 2017-10-06 14:07:55 +11:00
koalyptus eb9ac51b5a wip 2017-10-02 22:15:35 +11:00
koalyptus d86601e1a1 Merge branch '507-fix-col-widths-col-visibility-ext' into toolbar-refactor 2017-10-02 21:16:10 +11:00
koalyptus fd48f8c3ec Merge pull request #514 from koalyptus/greenkeeper/babel-eslint-8.0.1
Update babel-eslint to the latest version 🚀
2017-09-27 19:58:34 +10:00
greenkeeper[bot] fa28d6ce17 chore(package): update babel-eslint to version 8.0.1 2017-09-26 21:11:23 +00:00
koalyptus 4250fda098 Merge pull request #513 from koalyptus/507-fix-col-widths-col-visibility-ext
Fix + unit tests
2017-09-23 21:47:35 +10:00
koalyptus 4f9e3dee01 Fix + unit tests 2017-09-23 21:34:09 +10:00
koalyptus e05f0b2c73 Merge pull request #510 from koalyptus/greenkeeper/babel-eslint-8.0.0
Update babel-eslint to the latest version 🚀
2017-09-13 09:45:00 +10:00
greenkeeper[bot] 7c7a5fc1b7 chore(package): update babel-eslint to version 8.0.0 2017-09-12 14:18:29 +00:00
koalyptus a54abc6ea1 Merge pull request #508 from koalyptus/506-linked-filters-paging-fix
Fix link filters with paging on
2017-09-08 18:09:08 +10:00
koalyptus e4ed4d5567 Unit tests 2017-09-08 18:00:03 +10:00
koalyptus 29c4c107bc refactor linked filters logic to filter out values for drop-down and checklist filter 2017-09-07 14:21:40 +10:00
koalyptus 0b242aadc7 Fix link filters with paging on 2017-09-05 22:34:06 +10:00
koalyptus 44a39e7e1f Merge pull request #505 from koalyptus/greenkeeper/grunt-eslint-20.1.0
Update grunt-eslint to the latest version 🚀
2017-09-01 23:39:53 +10:00
greenkeeper[bot] e82640c7da chore(package): update grunt-eslint to version 20.1.0 2017-08-31 04:08:18 +00:00
koalyptus f89bf8859b Merge pull request #504 from koalyptus/style-issue-columns-list
Made ColsVisibility container inherit font-size, expand linked filters unit tests
2017-08-27 11:16:03 +10:00
koalyptus 6b5c432ce7 Made ColsVisibility container inherit font-size, expand linked filters unit tests 2017-08-27 10:54:05 +10:00
koalyptus 409a3bc6eb Merge pull request #501 from koalyptus/style-issue-columns-list
Style issue columns list
2017-08-12 22:46:28 +10:00
koalyptus d406a09a9e more css tweaks for edge 2017-08-12 22:30:41 +10:00
koalyptus 36b045c6d2 other css definition tweak for edge 2017-08-10 15:57:51 +10:00
koalyptus 59902adcf5 Merge pull request #500 from koalyptus/style-issue-columns-list
list-style-type instead of list-style
2017-08-10 14:04:02 +10:00
koalyptus 41842eede4 list-style-type instead of list-style 2017-08-10 13:48:59 +10:00
koalyptus 62c7cb1918 Merge pull request #499 from koalyptus/increase-coverage
refactor _buildSubmitButton in TableFilter
2017-08-09 14:43:55 +10:00
koalyptus d23f6f4cc8 refactor _buildSubmitButton in TableFilter 2017-08-09 14:18:52 +10:00
koalyptus 80f1fc3371 Merge pull request #498 from koalyptus/greenkeeper/grunt-babel-7.0.0
Update grunt-babel to the latest version 🚀
2017-08-09 13:36:19 +10:00
greenkeeper[bot] ea87137a82 chore(package): update grunt-babel to version 7.0.0 2017-08-08 23:35:45 +00:00
koalyptus aa8df36e28 Merge pull request #497 from koalyptus/greenkeeper/codecov-2.3.0
Update codecov to the latest version 🚀
2017-08-04 10:43:31 +10:00
greenkeeper[bot] 0947a87d6c chore(package): update codecov to version 2.3.0 2017-08-03 13:46:49 +00:00
koalyptus 72c47a9b0d Merge pull request #495 from koalyptus/494-formatted-number-no-decimal
Refine cell value coercion to number in filtering logic
2017-08-02 14:36:26 +10:00
koalyptus f0c9a800a5 Refine cell value coercion to number in filtering logic 2017-08-02 13:58:44 +10:00
koalyptus ad5405e699 Merge pull request #493 from koalyptus/358-increase-coverage
358 increase coverage
2017-07-30 21:49:21 +10:00
koalyptus cc5c8b9ed5 Increased TableFilter coverage 2017-07-30 21:39:23 +10:00
koalyptus 04d8fd3d14 Merge branch 'master' into 358-increase-coverage 2017-07-30 11:03:29 +10:00
koalyptus fb0a6a0a01 Merge pull request #492 from koalyptus/490-grid-layout-no-results
Keep scrollbar when grid-layout on and no-results-message
2017-07-29 11:17:10 +10:00
koalyptus 78059d1bf8 Keep scrollbar when grid-layout on and no-results-message 2017-07-29 11:08:13 +10:00
koalyptus 3352765fed Merge pull request #489 from koalyptus/487-fix-state-empty-table
Fix setFilterValue with inexistent filter element
2017-07-26 11:41:21 +10:00
koalyptus f96166be48 Fix setFilterValue with inexistent filter element 2017-07-26 11:30:36 +10:00
koalyptus 3a878c9e90 Merge pull request #488 from koalyptus/485-popup_filter-filters_row_index
Override filters row index setting when popup filters on
2017-07-25 22:51:57 +10:00
koalyptus 7b8c3c7412 Removed unnecessary setting for popup filter tests 2017-07-25 22:24:46 +10:00
koalyptus 9f6751533e Override filters row index setting when popup filters on 2017-07-25 22:22:32 +10:00
koalyptus 82e9b27598 Fix esdoc badge 2017-07-20 16:24:03 +10:00
koalyptus 237fff1351 Merge pull request #483 from koalyptus/481-getcolvalues-optimisation
Revert gh-pages publish-lib unfortunate change
2017-07-20 16:05:33 +10:00
koalyptus e00c560c80 Revert gh-pages publish-lib unfortunate change 2017-07-20 16:04:09 +10:00
koalyptus 407e772fdb Merge pull request #482 from koalyptus/481-getcolvalues-optimisation
getColValues optimisation from @rimace
2017-07-20 15:24:19 +10:00
koalyptus 645437b5e3 getColValues optimisation from @rimace 2017-07-20 13:39:43 +10:00
koalyptus 7f6221cd8e Merge pull request #480 from koalyptus/remove-external_flt_grid-option
Remove external flt grid option
2017-07-16 12:02:53 +10:00
koalyptus d9c770855a Fixed popup filter extra row issue 2017-07-16 11:55:54 +10:00
koalyptus 70a7d6540c Fixing popup filters extra row visibility 2017-07-16 11:27:23 +10:00
koalyptus acf6678619 Merge pull request #479 from koalyptus/remove-external_flt_grid-option
Removed external_flt_grid_option setting, make paths properties functions
2017-07-16 11:07:48 +10:00
koalyptus f2242c4e57 Removed external_flt_grid_option setting, make paths properties functions 2017-07-16 10:52:40 +10:00
koalyptus 8fb7c76e2d Merge pull request #477 from koalyptus/config-settings-helpers
Config settings helpers
2017-07-09 16:02:39 +10:00
koalyptus 72e78fd4bc Introduced settings helpers 2017-07-09 15:11:51 +10:00
koalyptus 2f1e065571 Remove hasExtensions and hasColWidths properties on TableFilter 2017-07-08 10:53:19 +10:00
koalyptus 761c3730ed Merge pull request #475 from koalyptus/refactor-features-instanciation
Refactor features instanciation
2017-07-03 13:28:31 +10:00
koalyptus cdf7b926ba Allowing features instantiation without configuration 2017-07-02 21:53:40 +10:00
koalyptus d3addb09c4 Placed features instantiation inside init method 2017-07-01 21:41:49 +10:00
koalyptus 471203b0a6 Merge branch 'master' into refactor-features-instanciation 2017-07-01 20:37:14 +10:00
koalyptus 7cac5b105e Merge pull request #474 from koalyptus/460-unit-test
Unit tests for popup-filters with grouped headers
2017-06-30 22:22:12 +10:00
koalyptus e8c3f27d93 Commented out test failing on build... 2017-06-30 22:12:31 +10:00
koalyptus 97d2ed0d64 Fixed linting 2017-06-30 22:00:40 +10:00
koalyptus 7278aab649 Unit tests for popup-filters with grouped headers 2017-06-30 21:54:50 +10:00
koalyptus e33e634d0d Merge pull request #473 from koalyptus/greenkeeper/format-number-3.0.0
Update format-number to the latest version 🚀
2017-06-30 13:30:04 +10:00
greenkeeper[bot] 92af5d8842 chore(package): update format-number to version 3.0.0 2017-06-29 11:40:10 +00:00
koalyptus 140f949190 Merge pull request #472 from koalyptus/greenkeeper/initial
Update dependencies to enable Greenkeeper 🌴
2017-06-28 21:04:09 +10:00
koalyptus c5d043f85b Fixed linting errors due to version bump of grunt-eslint 2017-06-28 20:47:32 +10:00
greenkeeper[bot] 06cea02484 docs(readme): add Greenkeeper badge 2017-06-27 12:01:05 +00:00
greenkeeper[bot] 287b7413e3 chore(travis): whitelist greenkeeper branches 2017-06-27 12:01:02 +00:00
greenkeeper[bot] 3c330ac4f0 chore(package): update dependencies 2017-06-27 12:00:59 +00:00
koalyptus 51bc126c8d Merge pull request #471 from koalyptus/465-cols-visibility-callbacks-grid-layout
More defensive with tableLayout
2017-06-27 15:39:26 +10:00
koalyptus edcd166cd8 More defensive with tableLayout 2017-06-27 15:28:16 +10:00
koalyptus aaead0e5ca Merge pull request #470 from koalyptus/465-cols-visibility-callbacks-grid-layout
465 cols visibility callbacks grid layout
2017-06-27 13:59:56 +10:00
koalyptus 990ef45e45 Removed commented out code 2017-06-27 13:42:02 +10:00
koalyptus 9ae607d802 Re-instating colsVisibility callbacks when grid-layout on + deleting code 2017-06-27 13:38:53 +10:00
Max Guglielmi 3c07d8dcc4 Started fixing col widths undex firefox 2017-06-25 21:51:15 +10:00
koalyptus bb8b8a9d50 Merge pull request #469 from koalyptus/466-grid-layout-misalignment
Removed headers table container width when is grid-layout on
2017-06-24 21:10:45 +10:00
Max Guglielmi 08303e93ca Removed headers table container width when is grid-layout on 2017-06-24 20:54:49 +10:00
koalyptus 01bdad6368 Merge pull request #468 from koalyptus/466-grid-layout-misalignment
Modified grd_headTblCont css definitions to account scrollbar width
2017-06-23 17:11:36 +10:00
Max Guglielmi 8145ef116f Modified grd_headTblCont css definitions to account scrollbar width 2017-06-23 17:01:13 +10:00
koalyptus ab9ff96684 Merge pull request #464 from koalyptus/refactor-paging-options
Refactor paging options
2017-06-15 13:43:50 +10:00
Max Guglielmi 9858ac84c1 Fixed unit tests 2017-06-14 22:12:44 +10:00
Max Guglielmi c6b876d7f9 Initial commit 2017-06-14 13:59:04 +10:00
koalyptus 05f1c62ad0 Merge pull request #463 from koalyptus/refactor-grid-layout-options
Refactor grid layout options
2017-06-04 20:34:04 +10:00
Max Guglielmi bf631efd24 Modified an option name (2) 2017-06-04 18:22:20 +10:00
Max Guglielmi f86e73b374 Modified an option name 2017-06-03 19:57:24 +10:00
Max Guglielmi 7cd85bbd34 Fixed unit tests 2017-06-03 19:45:20 +10:00
Max Guglielmi 38424bfdca Started refactoring configuration options 2017-06-02 14:01:10 +10:00
koalyptus 9dde61e7a0 Merge pull request #462 from koalyptus/refactor-popup-filters-options
Refactor popup filters options
2017-05-31 20:55:06 +10:00
Max Guglielmi 5fc1c78d1b Expanded unit tests 2017-05-31 13:46:23 +10:00
Max Guglielmi 2cbfc0b1ec Bumped webapack version 2017-05-29 13:34:47 +10:00
Max Guglielmi 5043378c2c Refactor popup-filters options 2017-05-29 13:31:45 +10:00
Max Guglielmi 92e743a67e Merge branch 'master' into refactor-popup-filters-options 2017-05-27 22:42:03 +10:00
koalyptus 9262e7fd13 Merge pull request #461 from koalyptus/460-fix-popup-filters
Fixed tf reference in closeAll and destroy
2017-05-27 22:22:53 +10:00
Max Guglielmi 5adfa8a1be Fixed tf reference in closeAll and destroy 2017-05-27 22:15:06 +10:00
Max Guglielmi 0d64d5aa00 Bumped version 2017-05-27 21:39:25 +10:00
Max Guglielmi 11e15f0482 Enforcing eslint rule 2017-05-25 13:51:44 +10:00
koalyptus 07355d7442 Merge pull request #459 from koalyptus/refactor-help-instructions
Refactor help-instructions configuration option
2017-05-24 13:03:35 +10:00
Max Guglielmi e8392b8fa5 Refactor help-instructions configuration option 2017-05-23 13:49:21 +10:00
koalyptus bfcf221a91 Merge pull request #458 from koalyptus/refactor-loader-options
Refactor loader configuration options
2017-05-18 20:14:11 +10:00
Max Guglielmi c29cbda581 Refactor loader configuration options 2017-05-18 13:49:11 +10:00
koalyptus 5294a31e30 Merge pull request #457 from koalyptus/refactor-status-bar-options
Refactor status-bar config
2017-05-17 13:30:03 +10:00
Max Guglielmi ed7ead95d5 Removed commented out code from pagination demo 2017-05-17 13:16:57 +10:00
Max Guglielmi aee6063410 Refactor status-bar config 2017-05-16 13:55:48 +10:00
koalyptus 45e78777e9 Merge pull request #456 from koalyptus/refactor-features-instanciation
Refactor features instanciation
2017-05-13 21:12:19 +10:00
Max Guglielmi 1de6a6288c updated unit tests 2017-05-13 20:51:10 +10:00
Max Guglielmi 4b7af32eb1 Updated README 2017-05-13 11:09:21 +10:00
Max Guglielmi 955c49a2c1 Merge branch 'master' into refactor-features-instanciation 2017-05-13 10:22:00 +10:00
koalyptus eeb5afe97b Merge pull request #453 from koalyptus/greenkeeper-codecov-2.2.0
Update codecov to version 2.2.0 🚀
2017-05-10 16:10:34 +10:00
greenkeeperio-bot f5d818c91a chore(package): update codecov to version 2.2.0
https://greenkeeper.io/
2017-05-10 11:23:48 +10:00
koalyptus 0a38e422b8 Merge pull request #450 from koalyptus/greenkeeper-grunt-webpack-3.0.0
Update grunt-webpack to version 3.0.0 🚀
2017-05-09 21:03:53 +10:00
Max Guglielmi f059faecbc Added missing starter.html 2017-05-09 20:53:25 +10:00
Max Guglielmi 195918f088 Dist build 2017-05-09 20:47:05 +10:00
Max Guglielmi 022e52e31c Exploring babel settings issues 2017-05-09 14:31:29 +10:00
Max Guglielmi b249399b1d Merge branch 'master' into greenkeeper-grunt-webpack-3.0.0 2017-05-09 13:08:56 +10:00
koalyptus 132d46fed5 Merge pull request #452 from koalyptus/greenkeeper-webpack-2.5.1
chore(package): update webpack to version 2.5.1
2017-05-07 19:43:34 +10:00
koalyptus 49e16a3631 Merge pull request #451 from koalyptus/284-sort-filter-options
284 sort filter options
2017-05-07 16:47:58 +10:00
Max Guglielmi 06c3b3f025 Added base class for drop-down filter types 2017-05-07 16:05:36 +10:00
greenkeeperio-bot 39e4340dee chore(package): update webpack to version 2.5.1
https://greenkeeper.io/
2017-05-07 06:12:58 +10:00
Max Guglielmi cb3a633807 Fixed tests 2017-05-07 00:35:24 +10:00
Max Guglielmi b0bc11007f Refactor logic for sorting drop-down filter options 2017-05-06 21:32:01 +10:00
greenkeeperio-bot 7781bcfe4b chore(package): update grunt-webpack to version 3.0.0
https://greenkeeper.io/
2017-05-05 23:57:18 +10:00
koalyptus 308ea2ce25 Merge pull request #449 from koalyptus/greenkeeper-webpack-2.5.0
chore(package): update webpack to version 2.5.0
2017-05-04 20:42:30 +10:00
greenkeeperio-bot d66c7906c0 chore(package): update webpack to version 2.5.0
https://greenkeeper.io/
2017-05-04 20:22:41 +10:00
koalyptus a0bf340378 Merge pull request #448 from koalyptus/rows-counter-options-refactor
Rows counter options refactor
2017-05-03 21:48:54 +10:00
Max Guglielmi 1b8bb8a9ea Added registerExtension method 2017-05-03 21:27:44 +10:00
Max Guglielmi 25101b278a Refactored options and updated unit tests 2017-05-02 22:31:02 +10:00
koalyptus 5c4c8c0fe9 Merge pull request #446 from koalyptus/refactor-features-instanciation
Refactor features instanciation
2017-05-01 22:13:16 +10:00
Max Guglielmi 7a861eabee Added missing starter file in dist folder 2017-05-01 22:10:57 +10:00
Max Guglielmi b8f549a432 Added missing doco 2017-05-01 22:04:01 +10:00
koalyptus 5a82498d60 Merge pull request #445 from koalyptus/refactor-features-instanciation
Refactor features instanciation
2017-05-01 21:59:57 +10:00
Max Guglielmi 890d004c3c Regrouped FEATURES destructuring 2017-05-01 21:45:17 +10:00
Max Guglielmi c7c20cdacf Removed commented out code 2017-05-01 21:41:24 +10:00
Max Guglielmi 3f2bc41176 Moved features definitions in const file 2017-05-01 21:36:51 +10:00
Max Guglielmi 70779f192c Started refactoring features instn 2017-05-01 09:36:47 +10:00
koalyptus 6fc121a314 Merge pull request #442 from koalyptus/440-popup-filters-horizontal-scroll
Made popup filters element anchored to container
2017-04-26 07:44:49 +10:00
Max Guglielmi 29960cada8 Made popup filters element anchored to container 2017-04-26 07:29:08 +10:00
koalyptus 6dc1c9e53b Merge pull request #441 from koalyptus/greenkeeper-webpack-dev-server-2.4.4
chore(package): update webpack-dev-server to version 2.4.4
2017-04-25 19:47:52 +10:00
greenkeeperio-bot 5b7b1527d5 chore(package): update webpack-dev-server to version 2.4.4
https://greenkeeper.io/
2017-04-23 21:38:27 +10:00
Max Guglielmi 6bfccca291 Added missing doc comment for MarkActiveColumns class 2017-04-23 18:50:35 +10:00
koalyptus 39c8933a3f Merge pull request #439 from koalyptus/modulerise-mark-active-columns
Modulerise mark active columns
2017-04-23 18:30:33 +10:00
Max Guglielmi 5411843f9f Expanded unit tests 2017-04-23 18:22:34 +10:00
Max Guglielmi 88b0dc5215 Added final new line 2017-04-23 05:43:06 +10:00
Max Guglielmi 2a8571d940 Production build 2017-04-23 05:34:54 +10:00
Max Guglielmi 9882a99417 Merge branch 'master' into modulerise-mark-active-columns 2017-04-23 05:18:18 +10:00
Max Guglielmi 2f8fb874d8 Unit tests for mark active columns feature 2017-04-23 05:17:42 +10:00
koalyptus 5f229311f0 Merge pull request #438 from koalyptus/greenkeeper-babel-eslint-7.2.3
Update babel-eslint to version 7.2.3 🚀
2017-04-22 17:15:04 +10:00
greenkeeperio-bot 4a88f6cc56 chore(package): update babel-eslint to version 7.2.3
https://greenkeeper.io/
2017-04-22 17:02:39 +10:00
koalyptus 151ec256fa Merge pull request #437 from koalyptus/greenkeeper-babel-loader-7.0.0
Update babel-loader to version 7.0.0 🚀
2017-04-22 17:02:23 +10:00
Max Guglielmi 37c90ed12b Started modulerising mark active columns feature 2017-04-22 06:22:50 +10:00
greenkeeperio-bot c21863c71a chore(package): update babel-loader to version 7.0.0
https://greenkeeper.io/
2017-04-22 06:18:20 +10:00
Max Guglielmi 508fc8fd1c Merge branch 'master' of https://github.com/koalyptus/TableFilter 2017-04-18 03:01:16 +10:00
Max Guglielmi 9f6b3160fc Added missing extensions bundle in dist folder 2017-04-18 03:00:10 +10:00
koalyptus 650de1d7e3 add links to cotributing in readme 2017-04-16 19:38:10 +10:00
koalyptus 68ebfcd537 Merge pull request #436 from koalyptus/greenkeeper-webpack-2.4.1
chore(package): update webpack to version 2.4.1
2017-04-15 17:01:31 +10:00
koalyptus 4cc870b1bb Merge pull request #435 from koalyptus/greenkeeper-grunt-contrib-clean-1.1.0
chore(package): update grunt-contrib-clean to version 1.1.0
2017-04-15 16:55:01 +10:00
greenkeeperio-bot a15fb5719e chore(package): update webpack to version 2.4.1
https://greenkeeper.io/
2017-04-14 23:53:13 +10:00
koalyptus 6926ef3b9a Merge pull request #434 from koalyptus/dom-method
Added dom method, made tbl property private
2017-04-14 19:52:43 +10:00
Max Guglielmi 76a61d5a01 Added dom method, made tbl property private 2017-04-14 19:30:58 +10:00
greenkeeperio-bot f24c5da431 chore(package): update grunt-contrib-clean to version 1.1.0
https://greenkeeper.io/
2017-04-13 10:42:17 +10:00
koalyptus b9ab9582a8 Merge pull request #433 from koalyptus/greenkeeper-babel-eslint-7.2.2
Update babel-eslint to version 7.2.2 🚀
2017-04-13 05:40:26 +10:00
greenkeeperio-bot f9426c9ed0 chore(package): update babel-eslint to version 7.2.2
https://greenkeeper.io/
2017-04-13 02:12:02 +10:00
koalyptus 067cce1d7b Merge pull request #431 from koalyptus/358-increase-coverage
358 increase coverage
2017-04-11 02:39:12 +10:00
Max Guglielmi b03445ea46 Expanded StatusBar tests 2017-04-11 02:33:27 +10:00
Max Guglielmi 9d7f49dda9 Bumped packages versions 2017-04-11 00:56:40 +10:00
Max Guglielmi dfd78be5b3 Merge branch 'master' into 358-increase-coverage 2017-04-11 00:53:14 +10:00
koalyptus f0e2ec6a8a Merge pull request #429 from koalyptus/simplify-get-data-apis
Simplify get data apis
2017-04-02 10:49:03 +10:00
Max Guglielmi 06ed30de3b Added getColumnData and getColumnValues 2017-04-02 00:54:19 +11:00
Max Guglielmi 5cfc6c573b Uncommented code 2017-03-31 15:01:13 +11:00
Max Guglielmi ec940d428a Updated unit tests 2017-03-31 14:56:51 +11:00
Max Guglielmi 4f593cb2d3 Started fixing unit tests 2017-03-30 23:14:27 +11:00
Max Guglielmi 611fc1ba24 Continued simplyfing data retrieval APIs 2017-03-29 21:42:31 +11:00
Max Guglielmi 4f7249bfa4 Started simplying data retrieval APIs 2017-03-26 20:42:51 +11:00
koalyptus 8f8e468278 Merge pull request #425 from koalyptus/424-page-length-persistence-issue
Fixed set page length when no valid rows + added unit tests
2017-03-25 15:31:44 +11:00
Max Guglielmi 23916b753a Reverted changes to grouped headers demo 2017-03-25 15:21:32 +11:00
Max Guglielmi e8ba629217 Fixed set page length when no valid rows + added unit tests 2017-03-25 15:19:12 +11:00
koalyptus ef2c2917db Merge pull request #423 from koalyptus/greenkeeper-babel-eslint-7.2.1
Update babel-eslint to version 7.2.1 🚀
2017-03-24 07:40:32 +11:00
greenkeeperio-bot 6daed0f4a8 chore(package): update babel-eslint to version 7.2.1
https://greenkeeper.io/
2017-03-24 05:11:14 +11:00
koalyptus 8624920e2c Merge pull request #422 from koalyptus/greenkeeper-babel-eslint-7.2.0
Update babel-eslint to version 7.2.0 🚀
2017-03-21 10:06:24 +11:00
greenkeeperio-bot e303cccd2a chore(package): update babel-eslint to version 7.2.0
https://greenkeeper.io/
2017-03-21 09:07:42 +11:00
koalyptus 88c4f2d8d0 Merge pull request #421 from koalyptus/greenkeeper-codecov-2.1.0
Update codecov to version 2.1.0 🚀
2017-03-19 12:02:59 +11:00
greenkeeperio-bot 41feee7a22 chore(package): update codecov to version 2.1.0
https://greenkeeper.io/
2017-03-18 22:54:09 +11:00
koalyptus c0101f45b5 Merge pull request #420 from koalyptus/413-col-ops-result-formatting
Added results formatting to ColOps
2017-03-18 12:54:50 +11:00
Max Guglielmi c49eb2e50f Added results formatting to ColOps 2017-03-18 10:20:51 +11:00
koalyptus 238af84a97 Merge pull request #419 from koalyptus/greenkeeper-codecov-2.0.2
Update codecov to version 2.0.2 🚀
2017-03-17 09:34:35 +11:00
greenkeeperio-bot 87d166c4a4 chore(package): update codecov to version 2.0.2
https://greenkeeper.io/
2017-03-16 19:48:07 +11:00
koalyptus d05a3c4dc0 Merge pull request #418 from koalyptus/358-increase-coverage
358 increase coverage
2017-03-16 15:21:36 +11:00
Max Guglielmi a2ccc2668a Added test case for disabled enter key 2017-03-16 15:05:56 +11:00
Max Guglielmi e93df29cc0 Merge branch 'master' into 358-increase-coverage 2017-03-16 13:32:07 +11:00
koalyptus aafe5da783 Merge pull request #417 from koalyptus/greenkeeper-codecov-2.0.1
Update codecov to version 2.0.1 🚀
2017-03-15 13:29:48 +11:00
greenkeeperio-bot 35174fb849 chore(package): update codecov to version 2.0.1
https://greenkeeper.io/
2017-03-15 09:57:32 +11:00
koalyptus 1905d89a75 Merge pull request #416 from koalyptus/greenkeeper-babel-core-6.24.0
chore(package): update babel-core to version 6.24.0
2017-03-14 13:46:31 +11:00
greenkeeperio-bot d566d6a315 chore(package): update babel-core to version 6.24.0
https://greenkeeper.io/
2017-03-13 14:14:10 +11:00
koalyptus 08529d0d59 Correct pull requests section 2017-03-10 19:15:12 +11:00
koalyptus ce946b9aed Merge pull request #411 from koalyptus/358-increase-coverage
358 increase coverage
2017-03-01 22:18:32 +11:00
Max Guglielmi f7aa5cd65c Expanded statusBar tests 2017-03-01 22:09:20 +11:00
Max Guglielmi d9c0fd6d0b Merge branch 'master' into 358-increase-coverage 2017-03-01 21:12:31 +11:00
koalyptus 41db8d67df Merge pull request #409 from koalyptus/cell-parser
Cell parser
2017-02-27 13:57:20 +11:00
Max Guglielmi 7a5985ba8f Added test case 2017-02-27 13:38:19 +11:00
Max Guglielmi 574e2c3761 Removed commented out code 2017-02-26 21:45:41 +11:00
Max Guglielmi 90b5e3cdca Renamed custom_cell_data option cell_parser 2017-02-26 21:43:36 +11:00
koalyptus b062d44b87 Merge pull request #406 from koalyptus/refresh-deps-versions
Bumped various packages versions
2017-02-21 22:18:52 +11:00
Max Guglielmi ca1c801d64 Bumped various packages versions 2017-02-21 21:25:08 +11:00
koalyptus c3a6c61739 Merge pull request #405 from koalyptus/404-fix-destroy-extensions
Fixed destroyExtensions
2017-02-13 15:11:31 +11:00
Max Guglielmi 5a496f228a Fixed destroyExtensions 2017-02-13 14:52:47 +11:00
167 changed files with 20774 additions and 3757 deletions

14
.esdoc.json Normal file
View file

@ -0,0 +1,14 @@
{
"source": "src",
"destination": "docs/docs",
"plugins": [{
"name": "esdoc-standard-plugin",
"option": {
"lint": {"enable": false},
"accessor": {
"access": ["public", "protected"],
"autoPrivate": true
}
}
}]
}

View file

@ -1,18 +1,20 @@
{ {
"parser": "babel-eslint", "parser": "babel-eslint",
"parserOptions": { "parserOptions": {
"sourceType": "module" "sourceType": "module",
"ecmaFeatures": { "modules": true }
}, },
"rules": { "rules": {
"max-len": [2, 80, 2, {"ignoreUrls": true}], "max-len": [2, 80, 2, {"ignoreUrls": true}],
"indent": [2, 4, {"SwitchCase": 1}], "indent": [2, 4, {"SwitchCase": 1}],
"semi": ["error", "always"],
"no-trailing-spaces": 2, "no-trailing-spaces": 2,
"no-multi-spaces": 2, "no-multi-spaces": 2,
"array-bracket-spacing": 2, "array-bracket-spacing": 2,
"keyword-spacing": ["error", { "after": true, "before": true }], "keyword-spacing": ["error", { "after": true, "before": true }],
"max-depth": [2, 7], "max-depth": [2, 7],
"max-statements": [2, 144], "max-statements": [2, 133],
"complexity": [2, 78], "complexity": [2, 45],
"no-unused-vars": 2, "no-unused-vars": 2,
"no-eval": 2, "no-eval": 2,
"no-underscore-dangle": 0, "no-underscore-dangle": 0,
@ -24,9 +26,6 @@
"new-cap": 2, "new-cap": 2,
"radix": [2, "always"] "radix": [2, "always"]
}, },
"ecmaFeatures": {
"modules": true
},
"env": { "env": {
"es6": true, "es6": true,
"browser": true, "browser": true,

38
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View 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]

View 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
View 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/

View file

@ -1,16 +1,53 @@
language: node_js language: node_js
node_js: node_js:
- '6.3.0' - '8.9.4'
before_script: before_script:
- npm install grunt-cli -g - npm install grunt-cli -g
- npm install codecov -g - npm install codecov -g
script: script:
- npm test - npm test
- npm run codecov - npm run codecov
- npm run deploy - npm run build:all
branches: branches:
only: only:
- master - master
- /^greenkeeper/.*$/
before_deploy:
- git config --global user.email "maxgug@hotmail.com"
- git config --global user.name "koalyptus"
- export GIT_TAG=$(git describe --tags --abbrev=0)
- echo -n $GIT_TAG
- export NEW_GIT_TAG=$(node -p -e "require('./package.json').version")
- echo -n $NEW_GIT_TAG
- |
if [ $GIT_TAG != $NEW_GIT_TAG ]; then
git tag $NEW_GIT_TAG -am "Generated tag from TravisCI build $TRAVIS_BUILD_NUMBER"
fi
deploy:
- provider: releases
on:
branch: master
api_key: $GITHUB_OAUTH_ACCESS_TOKEN
skip_cleanup: true
name: $NEW_GIT_TAG
- provider: s3
on:
branch: master
access_key_id: $AWS_ACCESS_KEY_ID
secret_access_key: $AWS_SECRET_ACCESS_KEY
region: $AWS_DEFAULT_REGION
bucket: www.tablefilter.com
skip_cleanup: true
local_dir: dist
- provider: s3
on:
branch: master
access_key_id: $AWS_ACCESS_KEY_ID
secret_access_key: $AWS_SECRET_ACCESS_KEY
region: $AWS_DEFAULT_REGION
bucket: www.tablefilter.com
skip_cleanup: true
local_dir: docs
env: env:
global: global:
- secure: A1G8GvJkV0rjy7XCTVdOpTHy3xaoSZZAbMWhI+ikrqBqd8mRz+sB71FhRusouTcYdsT5VfF9Io2doS8LKAeP0TNC34Pp0uvjtsvarzn8a/oNEOuqR3Ub0ws2bmbZIZc+wOpgErKOj1H1QSJAUpd6ZjIuEAbOVXlhGBJz3zUCmcpRDh32CpFKC62oFWeGlvttxPciLLzBfKgkVKEGhPtdGP/xCHL1MCQptYVHZiXwWsaIQ5wHFO6KCVlRrPgdfOL+Yce3mT02iXH6ZjW6U6zA6vYQVQZVD873AkU5RmirYblW+jW1wdvu4UXI71lSH6Z3uXRVnrw1b0TsLVTjP9ZUbCtkTHtLbxYzeDjEukxKoCjpAppIhOtaNIxrdA8oKJAabQYp5X+QK6lkosy0zdT5u2B1+g8unZhsf0y//7lgLUe04iQ7sc1Q6AHiiEGtByaXg4BHNW53bUfKgNnbV4+IbXf8rz5wWOxL2/yWAU/GoiszjqRQfajAXCpSf6SyMjXjhhvQdeFn+Cz6FwdtaxH+tOIY0Hq9Gqy1xrLIkv/httd3O+AbhLrU1c/M0MwlFQue7GeJb7ZyF3KsK7bXvoz2dEqvzHd98NZXiQEqFXCIs77uVh4eZMoYrbEyrkOAgkUZNQYhHh9fuvfynJ/zgUvyA0v3GUvBebq3ybYKD/vqX7s= - secure: A1G8GvJkV0rjy7XCTVdOpTHy3xaoSZZAbMWhI+ikrqBqd8mRz+sB71FhRusouTcYdsT5VfF9Io2doS8LKAeP0TNC34Pp0uvjtsvarzn8a/oNEOuqR3Ub0ws2bmbZIZc+wOpgErKOj1H1QSJAUpd6ZjIuEAbOVXlhGBJz3zUCmcpRDh32CpFKC62oFWeGlvttxPciLLzBfKgkVKEGhPtdGP/xCHL1MCQptYVHZiXwWsaIQ5wHFO6KCVlRrPgdfOL+Yce3mT02iXH6ZjW6U6zA6vYQVQZVD873AkU5RmirYblW+jW1wdvu4UXI71lSH6Z3uXRVnrw1b0TsLVTjP9ZUbCtkTHtLbxYzeDjEukxKoCjpAppIhOtaNIxrdA8oKJAabQYp5X+QK6lkosy0zdT5u2B1+g8unZhsf0y//7lgLUe04iQ7sc1Q6AHiiEGtByaXg4BHNW53bUfKgNnbV4+IbXf8rz5wWOxL2/yWAU/GoiszjqRQfajAXCpSf6SyMjXjhhvQdeFn+Cz6FwdtaxH+tOIY0Hq9Gqy1xrLIkv/httd3O+AbhLrU1c/M0MwlFQue7GeJb7ZyF3KsK7bXvoz2dEqvzHd98NZXiQEqFXCIs77uVh4eZMoYrbEyrkOAgkUZNQYhHh9fuvfynJ/zgUvyA0v3GUvBebq3ybYKD/vqX7s=

View file

@ -116,15 +116,13 @@ In general, we follow the "fork-and-pull" Git workflow.
3. **Commit** changes to your own branch 3. **Commit** changes to your own branch
- 3.1. **Add** unit tests covering your change in the `test` folder - 3.1. **Add** unit tests covering your change in the `test` folder
- 3.2. **Run** the tests with the `npm run eslint test` command - 3.2. **Run** the tests with the `npm run eslint test` command
- 3.3. **Ensure** build is working with `npm run build-all` command - 3.3. **Ensure** build is working with `npm run dist` command
4. **Push** your work back up to your fork 4. **Push** your work back up to your fork
5. Submit a **Pull request** so that we can review your changes 5. Submit a **Pull request** so that we can review your changes
NOTE: Be sure to merge the latest from "upstream" before making a pull request! NOTE: Be sure to merge the latest from "upstream" before making a pull request!
## Donations ## Donations
To support this project simply locate the `Donate` button in the [project's Support this project by donating [here](http://www.tablefilter.com/donate.html).
website](http://koalyptus.github.io/TableFilter/) Thanks to all those who supported this project in the past and those who will
which points to PayPal.
Thanks to all those who supported this project in the past and to those who will
in the future! in the future!

View file

@ -1,38 +1,19 @@
module.exports = function (grunt) { module.exports = function (grunt) {
var webpackConfig = require('./webpack.config.js');
var webpackDevConfig = require('./webpack.dev.config.js');
var webpackTestConfig = require('./webpack.test.config.js');
var fs = require('fs'); var fs = require('fs');
var path = require('path'); var path = require('path');
var testDir = 'test'; var testDir = 'test';
var testHost = 'http://localhost:8000/'; var testHost = 'http://localhost:8000/';
var pkg = grunt.file.readJSON('package.json'); var pkg = grunt.file.readJSON('package.json');
var repo = 'github.com/koalyptus/TableFilter';
var styleDirDist = 'dist/tablefilter/style/';
grunt.initConfig({ grunt.initConfig({
eslint: {
options: {
configFile: '.eslintrc'
},
target: [
'Gruntfile.js',
'webpack.config.js',
'webpack.dev.config.js',
'webpack.test.config.js',
'src/**/*.js',
'test/*.js'
]
},
qunit: { qunit: {
options: { options: {
'--web-security': 'no', '--web-security': 'no',
coverage: { coverage: {
disposeCollector: true, disposeCollector: true,
src: ['dist/tablefilter/*.js'], src: ['dist/tablefilter/*.js'],
instrumentedFiles: 'temp/', instrumentedFiles: 'report/temp/',
htmlReport: 'report/coverage', htmlReport: 'report/coverage',
coberturaReport: 'report/', coberturaReport: 'report/',
lcovReport: 'report/', lcovReport: 'report/',
@ -126,24 +107,6 @@ module.exports = function (grunt) {
clean: ['demos/starter.html'], clean: ['demos/starter.html'],
'webpack-dev-server': {
options: {
webpack: webpackDevConfig,
publicPath: '/dist/'
},
start: {
webpack: {
devtool: 'eval'
}
}
},
webpack: {
build: webpackConfig,
dev: webpackDevConfig,
test: webpackTestConfig
},
watch: { watch: {
app: { app: {
files: ['src/**/*', 'static/style/**/*'], files: ['src/**/*', 'static/style/**/*'],
@ -161,168 +124,49 @@ module.exports = function (grunt) {
} }
}, },
babel: { // temporary shell commands while decommissioning grunt
options: { shell: {
sourceMap: true, eslint: {
modules: 'amd', command: 'npm run lint'
compact: false,
presets: ['es2015']
}, },
dist: {
files: [{
expand: true,
cwd: 'src',
src: ['**/*.js'],
dest: 'dist/tablefilter'
}]
}
},
esdoc: { esdoc: {
dist: { command: 'npm run esdoc'
options: { },
source: 'src', build: {
destination: 'docs/docs', command: 'npm run build'
title: pkg.name + ' v' + pkg.version },
dev: {
command: 'npm run dev'
},
test: {
command: 'npm run build:test'
},
'build-css': {
command: 'npm run build:css'
} }
} }
},
stylus: {
compile: {
options: {
banner: '/** \n' +
' *\t ' + pkg.name + ' v' + pkg.version +
' by ' + pkg.author.name + ' \n' +
' *\t build date: ' + new Date().toISOString() + ' \n' +
' *\t MIT License \n' +
' */ \n'
},
files: [
{
src: ['static/style/*.styl'],
dest: styleDirDist + 'tablefilter.css'
}, {
src: ['static/style/extensions/colsVisibility.styl'],
dest: styleDirDist + 'colsVisibility.css'
}, {
src: ['static/style/extensions/filtersVisibility.styl'],
dest: styleDirDist + 'filtersVisibility.css'
}, {
src: ['static/style/themes/default/*.styl'],
dest: styleDirDist + 'themes/default/default.css'
}, {
src: ['static/style/themes/mytheme/*.styl'],
dest: styleDirDist + 'themes/mytheme/mytheme.css'
}, {
src: ['static/style/themes/skyblue/*.styl'],
dest: styleDirDist + 'themes/skyblue/skyblue.css'
}, {
src: ['static/style/themes/transparent/*.styl'],
dest:
styleDirDist + 'themes/transparent/transparent.css'
}
]
}
},
'gh-pages': {
options: {
branch: 'gh-pages',
add: true
},
'publish-lib': {
options: {
base: 'dist',
repo: 'https://' + repo,
message: 'publish TableFilter lib to gh-pages (cli)'
},
src: ['**/*']
},
'publish-readme': {
options: {
base: './',
repo: 'https://' + repo,
message: 'publish README and LICENSE to gh-pages (cli)'
},
src: ['README.md', 'LICENSE']
},
'publish-docs': {
options: {
base: 'docs',
repo: 'https://' + repo,
message: 'publish Docs to gh-pages (cli)'
},
src: ['**/*']
},
'deploy-lib': {
options: {
user: {
name: 'koalyptus'
},
base: 'dist',
repo: 'https://' + process.env.GH_TOKEN + '@' + repo,
message: 'publish TableFilter to gh-pages (auto)' +
getDeployMessage(),
silent: true
},
src: ['**/*']
},
'deploy-readme': {
options: {
user: {
name: 'koalyptus'
},
base: './',
repo: 'https://' + process.env.GH_TOKEN + '@' + repo,
message: 'publish README to gh-pages (auto)' +
getDeployMessage(),
silent: true
},
src: ['README.md', 'LICENSE']
},
'deploy-docs': {
options: {
user: {
name: 'koalyptus'
},
base: 'docs',
repo: 'https://' + process.env.GH_TOKEN + '@' + repo,
message: 'publish Docs to gh-pages (auto)' +
getDeployMessage(),
silent: true
},
src: ['**/*']
}
}
}); });
grunt.loadNpmTasks('grunt-eslint');
grunt.loadNpmTasks('grunt-contrib-copy'); grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-clean'); grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-string-replace'); grunt.loadNpmTasks('grunt-string-replace');
grunt.loadNpmTasks('grunt-contrib-connect'); grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-webpack'); grunt.loadNpmTasks('grunt-shell');
grunt.loadNpmTasks('grunt-babel');
grunt.loadNpmTasks('grunt-esdoc');
grunt.loadNpmTasks('grunt-qunit-istanbul'); grunt.loadNpmTasks('grunt-qunit-istanbul');
grunt.loadNpmTasks('grunt-contrib-stylus');
grunt.loadNpmTasks('grunt-gh-pages'); grunt.registerTask('eslint', ['shell:eslint']);
grunt.registerTask('esdoc', ['shell:esdoc']);
grunt.registerTask('default', ['test', 'build', 'build-demos']); grunt.registerTask('default', ['test', 'build', 'build-demos']);
// Development server
grunt.registerTask('server', ['webpack-dev-server:start']);
// Dev dev/build/watch cycle // Dev dev/build/watch cycle
grunt.registerTask('dev', grunt.registerTask('dev',
['eslint', 'webpack:dev', 'copy:dist', 'stylus:compile', 'watch:app']); ['eslint', 'shell:dev', 'copy:dist', 'shell:build-css', 'watch:app']);
// Production build // Production build
grunt.registerTask('build', grunt.registerTask('build',
['eslint', 'webpack:build', 'copy:dist', 'stylus:compile']); ['eslint', 'shell:build', 'copy:dist', 'shell:build-css']);
// Build demos // Build demos
grunt.registerTask('dev-demos', ['build-demos', 'watch:templates']); grunt.registerTask('dev-demos', ['build-demos', 'watch:templates']);
@ -331,23 +175,14 @@ module.exports = function (grunt) {
// Build tests // Build tests
grunt.registerTask('build-test', grunt.registerTask('build-test',
['eslint', 'webpack:test', 'copy:dist', 'stylus:compile']); ['eslint', 'shell:test', 'copy:dist', 'shell:build-css']);
// Transpile with Babel
grunt.registerTask('dev-modules', ['babel', 'copy:dist']);
// Tests with coverage // Tests with coverage
grunt.registerTask('test', ['build-test', 'connect', 'qunit:all']); grunt.registerTask('test', ['build-test', 'connect', 'qunit:all']);
// Publish to gh-pages // Build all for deployment from travis
grunt.registerTask('publish', 'Publish from CLI', [ grunt.registerTask('build-all', 'Prepare for deployment', [
'build', 'build-demos', 'esdoc', 'gh-pages:publish-lib', 'build', 'build-demos', 'esdoc'
'gh-pages:publish-readme', 'gh-pages:publish-docs'
]);
// Deploy to gh-pages
grunt.registerTask('deploy', 'Publish from Travis', [
'build', 'esdoc', 'check-deploy'
]); ]);
// Custom task running QUnit tests for specified files. // Custom task running QUnit tests for specified files.
@ -414,43 +249,4 @@ module.exports = function (grunt) {
return getFiles(testDir, host); return getFiles(testDir, host);
} }
grunt.registerTask('check-deploy', function () {
var env = process.env;
// need this
this.requires(['build', 'esdoc']);
// only deploy under these conditions
if (env.TRAVIS === 'true' &&
env.TRAVIS_SECURE_ENV_VARS === 'true' &&
env.TRAVIS_PULL_REQUEST === 'false') {
grunt.log.writeln('executing deployment');
// queue deploy
grunt.task.run([
'gh-pages:deploy-lib',
'gh-pages:deploy-readme',
'gh-pages:deploy-docs'
]);
} else {
grunt.log.writeln('skipped deployment');
}
});
// Get a formatted commit message to review changes from the commit log
// github will turn some of these into clickable links
function getDeployMessage() {
var ret = '\n\n';
var env = process.env;
if (env.TRAVIS !== 'true') {
ret += 'missing env vars for travis-ci';
return ret;
}
ret += 'branch: ' + env.TRAVIS_BRANCH + '\n';
ret += 'SHA: ' + env.TRAVIS_COMMIT + '\n';
ret += 'range SHA: ' + env.TRAVIS_COMMIT_RANGE + '\n';
ret += 'build id: ' + env.TRAVIS_BUILD_ID + '\n';
ret += 'build number: ' + env.TRAVIS_BUILD_NUMBER + '\n';
return ret;
}
}; };

24
PULL_REQUEST_TEMPLATE.md Normal file
View file

@ -0,0 +1,24 @@
# Description
Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context.
Fixes # (issue)
## Type of change
Please delete options that are not relevant.
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update
- [ ] Development tool configuration change
# Checklist:
- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes do not lower current test coverage
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes

View file

@ -1,6 +1,8 @@
[![Build Status](https://api.travis-ci.org/koalyptus/TableFilter.svg?branch=master)](https://travis-ci.org/koalyptus/TableFilter) [![Build Status](https://api.travis-ci.org/koalyptus/TableFilter.svg?branch=master)](https://travis-ci.org/koalyptus/TableFilter)
[![Document](http://koalyptus.github.io/TableFilter/docs/badge.svg)](https://koalyptus.github.io/TableFilter/docs/source) [![Document](https://www.tablefilter.com/docs/badge.svg)](https://www.tablefilter.com/docs/source.html)
[![codecov](https://codecov.io/gh/koalyptus/TableFilter/branch/master/graph/badge.svg)](https://codecov.io/gh/koalyptus/TableFilter) [![codecov](https://codecov.io/gh/koalyptus/TableFilter/branch/master/graph/badge.svg)](https://codecov.io/gh/koalyptus/TableFilter)
[![Greenkeeper badge](https://badges.greenkeeper.io/koalyptus/TableFilter.svg)](https://greenkeeper.io/)
[![Donate](https://img.shields.io/badge/donate-%24-green.svg)](https://www.tablefilter.com/donate.html)
# TableFilter # TableFilter
@ -22,7 +24,7 @@ users to filter and limit the data displayed within a long table. By default, th
* Attach to an existing HTML table * Attach to an existing HTML table
* Integration with any server-side technology as this is a pure client-side * Integration with any server-side technology as this is a pure client-side
solution solution
* Exhaustive documentation and poweful API * Exhaustive documentation and powerful API
## Getting started ## Getting started
* Clone the repo using Git: * Clone the repo using Git:
@ -32,7 +34,7 @@ git clone https://github.com/koalyptus/TableFilter.git
* You can [download](https://github.com/koalyptus/TableFilter/archive/master.zip) this repository. * You can [download](https://github.com/koalyptus/TableFilter/archive/master.zip) this repository.
* Alternatively, install TableFilter files in your npm enabled project using: * TableFilter is available on [npm repository](https://www.npmjs.com/package/tablefilter), you can install it from the command line using the following command:
```shell ```shell
npm install tablefilter --save-dev npm install tablefilter --save-dev
``` ```
@ -40,15 +42,32 @@ npm install tablefilter --save-dev
```shell ```shell
npm install tablefilter@next --save-dev npm install tablefilter@next --save-dev
``` ```
* If you don't use `npm`, you can also * Alternatively you can also [access these files from unpkg CDN](https://unpkg.com/tablefilter/), download them or point your package manager to them.
[access these files on unpkg](https://unpkg.com/tablefilter/), download them
or point your package manager to them.
## Setup ## Setup
### Using modules
Require `TableFilter`:
```javascript
// ES2015 modules
import TableFilter from 'tablefilter';
// CommonJS or AMD modules
var TableFilter = require('tablefilter');
```
### Using distribution scripts
If you are not using a module system, you can reference the distribution scripts directly in your html pages:
```html
<script src="path_to/node_modules/tablefilter/dist/tablefilter/tablefilter.js"></script>
```
### Placing manually the distribution scripts in your project
Copy the ``tablefilter`` directory under ``dist`` and place it at desired location in your project. Then include the main js file in your page: Copy the ``tablefilter`` directory under ``dist`` and place it at desired location in your project. Then include the main js file in your page:
```shell ```shell
<script src="path/to/my/scripts/tablefilter/tablefilter.js"></script> <script src="path/to/my/scripts/tablefilter/tablefilter.js"></script>
``` ```
### Usage
Place the following snippet just under the HTML table and always define a ``base_path`` property in the configuration object to reflect the path to the script Place the following snippet just under the HTML table and always define a ``base_path`` property in the configuration object to reflect the path to the script
```shell ```shell
<script> <script>
@ -66,7 +85,7 @@ your-page.html
## Development ## Development
This project requires node.js and Grunt to be installed: This project requires node.js and Grunt to be installed:
- install [node.js](https://nodejs.org/) - install [node.js](https://nodejs.org/) v8.9.4 or higher
- install [Grunt](http://gruntjs.com/getting-started) from the command line using npm (comes with node.js): - install [Grunt](http://gruntjs.com/getting-started) from the command line using npm (comes with node.js):
```shell ```shell
npm install -g grunt-cli npm install -g grunt-cli
@ -115,7 +134,7 @@ to view the coverage report(s), open the `index.html` under the
[online](https://codecov.io/gh/koalyptus/TableFilter). [online](https://codecov.io/gh/koalyptus/TableFilter).
## Demos ## Demos
Check out the online [examples](http://koalyptus.github.io/TableFilter/examples) Check out the online [examples](http://www.tablefilter.com/examples.html)
or generate the demos locally: or generate the demos locally:
```shell ```shell
npm run build:demos npm run build:demos
@ -132,7 +151,7 @@ http://localhost:8080/demos/
## Documentation ## Documentation
Find exhaustive documentation on the configuration options in the [WIKI](https://github.com/koalyptus/TableFilter/wiki) section. Find exhaustive documentation on the configuration options in the [WIKI](https://github.com/koalyptus/TableFilter/wiki) section.
Autogenerated documentation of the ES6 modules is available on the website: [docs](http://koalyptus.github.io/TableFilter/docs) Autogenerated documentation of the ES6 modules is available on the website: [docs](http://www.tablefilter.com/docs)
If you previously used the HTML Table Filter Generator plugin, verify the configuration If you previously used the HTML Table Filter Generator plugin, verify the configuration
options you are using are still supported: [Obsolete](https://github.com/koalyptus/TableFilter/wiki/Obsolete) options you are using are still supported: [Obsolete](https://github.com/koalyptus/TableFilter/wiki/Obsolete)
@ -143,7 +162,7 @@ npm run esdoc
``` ```
## Support ## Support
* GitHub for reporting bugs and feature requests. * GitHub for [reporting bugs](https://github.com/koalyptus/TableFilter/blob/master/CONTRIBUTING.md#reporting-bugs) and [feature requests](https://github.com/koalyptus/TableFilter/blob/master/CONTRIBUTING.md#suggesting-enhancements-and-features).
## License ## License
[MIT](LICENSE) [MIT](LICENSE)

6
dist/starter.html vendored
View file

@ -1,10 +1,10 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<title>tablefilter v0.4.40 - Starter</title> <title>tablefilter v0.7.3 - Starter</title>
</head> </head>
<body> <body>
<h1>tablefilter v0.4.40</h1> <h1>tablefilter v0.7.3</h1>
@ -479,7 +479,7 @@
}, },
col_widths: [ col_widths: [
'150px', '100px', '100px', '150px', '100px', '100px',
'70px', '70px', '70px', '100px', '100px', '100px',
'70px', '60px', '60px' '70px', '60px', '60px'
], ],
extensions:[{ name: 'sort' }] extensions:[{ name: 'sort' }]

View file

@ -1,6 +1 @@
/** span.colVisSpan{text-align:left;}span.colVisSpan a.colVis{display:inline-block;padding:7px 5px 0;font-size:inherit;font-weight:inherit;vertical-align:top}div.colVisCont{position:relative;background:#fff;-webkit-box-shadow:3px 3px 2px #888;-moz-box-shadow:3px 3px 2px #888;box-shadow:3px 3px 2px #888;position:absolute;display:none;border:1px solid #ccc;height:auto;width:250px;background-color:#fff;margin:35px 0 0 -100px;z-index:10000;padding:10px 10px 10px 10px;text-align:left;font-size:inherit;}div.colVisCont:after,div.colVisCont:before{bottom:100%;left:50%;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}div.colVisCont:after{border-color:rgba(255,255,255,0);border-bottom-color:#fff;border-width:10px;margin-left:-10px}div.colVisCont:before{border-color:rgba(255,255,255,0);border-bottom-color:#ccc;border-width:12px;margin-left:-12px}div.colVisCont p{margin:6px auto 6px auto}div.colVisCont a.colVis{display:initial;font-weight:inherit}ul.cols_checklist{padding:0;margin:0;list-style-type:none;}ul.cols_checklist label{display:block}ul.cols_checklist input{vertical-align:middle;margin:2px 5px 2px 1px}li.cols_checklist_item{padding:4px;margin:0;}li.cols_checklist_item:hover{background-color:#335ea8;color:#fff}.cols_checklist_slc_item{background-color:#335ea8;color:#fff}
* tablefilter v0.4.40 by Max Guglielmi
* build date: 2017-02-11T12:40:33.756Z
* MIT License
*/
span.colVisSpan{text-align:left;}span.colVisSpan a.colVis{display:inline-block;padding:7px 5px 0;font-size:inherit;font-weight:inherit;vertical-align:top}div.colVisCont{position:relative;background:#fff;-webkit-box-shadow:3px 3px 2px #888;-moz-box-shadow:3px 3px 2px #888;box-shadow:3px 3px 2px #888;position:absolute;display:none;border:1px solid #ccc;height:auto;width:250px;background-color:#fff;margin:35px 0 0 -100px;z-index:10000;padding:10px 10px 10px 10px;text-align:left;font-size:12px;}div.colVisCont:after,div.colVisCont:before{bottom:100%;left:50%;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}div.colVisCont:after{border-color:rgba(255,255,255,0);border-bottom-color:#fff;border-width:10px;margin-left:-10px}div.colVisCont:before{border-color:rgba(255,255,255,0);border-bottom-color:#ccc;border-width:12px;margin-left:-12px}div.colVisCont p{margin:6px auto 6px auto}div.colVisCont a.colVis{display:initial;font-weight:inherit}ul.cols_checklist{padding:0;margin:0;list-style:none;}ul.cols_checklist label{display:block}ul.cols_checklist input{vertical-align:middle;margin:2px 5px 2px 1px}li.cols_checklist_item{padding:4px;margin:0;}li.cols_checklist_item:hover{background-color:#335ea8;color:#fff}.cols_checklist_slc_item{background-color:#335ea8;color:#fff}

View file

@ -1,6 +1 @@
/**
* tablefilter v0.4.40 by Max Guglielmi
* build date: 2017-02-11T12:40:33.756Z
* MIT License
*/
span.expClpFlt a.btnExpClpFlt{width:35px;height:35px;display:inline-block;}span.expClpFlt a.btnExpClpFlt:hover{background-color:#f4f4f4}span.expClpFlt img{padding:8px 11px 11px 11px} span.expClpFlt a.btnExpClpFlt{width:35px;height:35px;display:inline-block;}span.expClpFlt a.btnExpClpFlt:hover{background-color:#f4f4f4}span.expClpFlt img{padding:8px 11px 11px 11px}

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1 @@
/**
* tablefilter v0.4.40 by Max Guglielmi
* build date: 2017-02-11T12:40:33.756Z
* MIT License
*/
table.TF{border-left:1px solid #ccc;border-top:none;border-right:none;border-bottom:none;}table.TF th{background:#ebecee url("images/bg_th.jpg") left top repeat-x;border-bottom:1px solid #d0d0d0;border-right:1px solid #d0d0d0;border-left:1px solid #fff;border-top:1px solid #fff;color:#333}table.TF td{border-bottom:1px dotted #999;padding:5px}.fltrow{background-color:#ebecee !important;}.fltrow th,.fltrow td{border-bottom:1px dotted #666 !important;padding:1px 3px 1px 3px !important}.flt,select.flt,select.flt_multi,.flt_s,.single_flt,.div_checklist{border:1px solid #999 !important}input.flt{width:99% !important}.inf{height:$min-height;background:#d7d7d7 url("images/bg_infDiv.jpg") 0 0 repeat-x !important}input.reset{background:transparent url("images/btn_eraser.gif") center center no-repeat !important}.helpBtn:hover{background-color:transparent}.nextPage{background:transparent url("images/btn_next_page.gif") center center no-repeat !important;}.nextPage:hover{background:transparent url("images/btn_over_next_page.gif") center center no-repeat !important}.previousPage{background:transparent url("images/btn_previous_page.gif") center center no-repeat !important;}.previousPage:hover{background:transparent url("images/btn_over_previous_page.gif") center center no-repeat !important}.firstPage{background:transparent url("images/btn_first_page.gif") center center no-repeat !important;}.firstPage:hover{background:transparent url("images/btn_over_first_page.gif") center center no-repeat !important}.lastPage{background:transparent url("images/btn_last_page.gif") center center no-repeat !important;}.lastPage:hover{background:transparent url("images/btn_over_last_page.gif") center center no-repeat !important}div.grd_Cont{background-color:#ebecee !important;border:1px solid #ccc !important;padding:0 !important;}div.grd_Cont .even{background-color:#fff}div.grd_Cont .odd{background-color:#d5d5d5}div.grd_headTblCont{background-color:#ebecee !important;border-bottom:none !important;}div.grd_headTblCont table{border-right:none !important}div.grd_tblCont table th,div.grd_headTblCont table th,div.grd_headTblCont table td{background:#ebecee url("images/bg_th.jpg") left top repeat-x !important;border-bottom:1px solid #d0d0d0 !important;border-right:1px solid #d0d0d0 !important;border-left:1px solid #fff !important;border-top:1px solid #fff !important}div.grd_tblCont table td{border-bottom:1px solid #999 !important}.grd_inf{background:#d7d7d7 url("images/bg_infDiv.jpg") 0 0 repeat-x !important;border-top:1px solid #d0d0d0 !important}.loader{border:1px solid #999}.defaultLoader{width:32px;height:32px;background:transparent url("images/img_loading.gif") 0 0 no-repeat !important}.even{background-color:#fff}.odd{background-color:#d5d5d5}span.expClpFlt a.btnExpClpFlt:hover{background-color:transparent !important}.activeHeader{background:#999 !important} table.TF{border-left:1px solid #ccc;border-top:none;border-right:none;border-bottom:none;}table.TF th{background:#ebecee url("images/bg_th.jpg") left top repeat-x;border-bottom:1px solid #d0d0d0;border-right:1px solid #d0d0d0;border-left:1px solid #fff;border-top:1px solid #fff;color:#333}table.TF td{border-bottom:1px dotted #999;padding:5px}.fltrow{background-color:#ebecee !important;}.fltrow th,.fltrow td{border-bottom:1px dotted #666 !important;padding:1px 3px 1px 3px !important}.flt,select.flt,select.flt_multi,.flt_s,.single_flt,.div_checklist{border:1px solid #999 !important}input.flt{width:99% !important}.inf{height:$min-height;background:#d7d7d7 url("images/bg_infDiv.jpg") 0 0 repeat-x !important}input.reset{background:transparent url("images/btn_eraser.gif") center center no-repeat !important}.helpBtn:hover{background-color:transparent}.nextPage{background:transparent url("images/btn_next_page.gif") center center no-repeat !important;}.nextPage:hover{background:transparent url("images/btn_over_next_page.gif") center center no-repeat !important}.previousPage{background:transparent url("images/btn_previous_page.gif") center center no-repeat !important;}.previousPage:hover{background:transparent url("images/btn_over_previous_page.gif") center center no-repeat !important}.firstPage{background:transparent url("images/btn_first_page.gif") center center no-repeat !important;}.firstPage:hover{background:transparent url("images/btn_over_first_page.gif") center center no-repeat !important}.lastPage{background:transparent url("images/btn_last_page.gif") center center no-repeat !important;}.lastPage:hover{background:transparent url("images/btn_over_last_page.gif") center center no-repeat !important}div.grd_Cont{background-color:#ebecee !important;border:1px solid #ccc !important;padding:0 !important;}div.grd_Cont .even{background-color:#fff}div.grd_Cont .odd{background-color:#d5d5d5}div.grd_headTblCont{background-color:#ebecee !important;border-bottom:none !important;}div.grd_headTblCont table{border-right:none !important}div.grd_tblCont table th,div.grd_headTblCont table th,div.grd_headTblCont table td{background:#ebecee url("images/bg_th.jpg") left top repeat-x !important;border-bottom:1px solid #d0d0d0 !important;border-right:1px solid #d0d0d0 !important;border-left:1px solid #fff !important;border-top:1px solid #fff !important}div.grd_tblCont table td{border-bottom:1px solid #999 !important}.grd_inf{background:#d7d7d7 url("images/bg_infDiv.jpg") 0 0 repeat-x !important;border-top:1px solid #d0d0d0 !important}.loader{border:1px solid #999}.defaultLoader{width:32px;height:32px;background:transparent url("images/img_loading.gif") 0 0 no-repeat !important}.even{background-color:#fff}.odd{background-color:#d5d5d5}span.expClpFlt a.btnExpClpFlt:hover{background-color:transparent !important}.activeHeader{background:#999 !important}

View file

@ -1,6 +1 @@
/**
* tablefilter v0.4.40 by Max Guglielmi
* build date: 2017-02-11T12:40:33.756Z
* MIT License
*/
table.TF{border-left:1px dotted #81963b;border-top:none;border-right:0;border-bottom:none;}table.TF th{background:#39424b url("images/bg_headers.jpg") left top repeat-x;border-bottom:0;border-right:1px dotted #d0d0d0;border-left:0;border-top:0;color:#fff}table.TF td{border-bottom:1px dotted #81963b;border-right:1px dotted #81963b;padding:5px}.fltrow{background-color:#81963b !important;}.fltrow th,.fltrow td{border-bottom:1px dotted #39424b !important;border-right:1px dotted #fff !important;border-left:0 !important;border-top:0 !important;padding:1px 3px 1px 3px !important}.flt,select.flt,select.flt_multi,.flt_s,.single_flt,.div_checklist{border:1px solid #687830 !important}input.flt{width:99% !important}.inf{background:#d8d8d8;height:$min-height}input.reset{width:53px;background:transparent url("images/btn_filter.png") center center no-repeat !important}.helpBtn:hover{background-color:transparent}.nextPage{background:transparent url("images/btn_next_page.gif") center center no-repeat !important}.previousPage{background:transparent url("images/btn_previous_page.gif") center center no-repeat !important}.firstPage{background:transparent url("images/btn_first_page.gif") center center no-repeat !important}.lastPage{background:transparent url("images/btn_last_page.gif") center center no-repeat !important}div.grd_Cont{background:#81963b url("images/bg_headers.jpg") left top repeat-x !important;border:1px solid #ccc !important;padding:0 1px 1px 1px !important;}div.grd_Cont .even{background-color:#bccd83}div.grd_Cont .odd{background-color:#fff}div.grd_headTblCont{background-color:#ebecee !important;border-bottom:none !important}div.grd_tblCont table{border-right:none !important;}div.grd_tblCont table td{border-bottom:1px dotted #81963b;border-right:1px dotted #81963b}div.grd_tblCont table th,div.grd_headTblCont table th{background:transparent url("images/bg_headers.jpg") 0 0 repeat-x !important;border-bottom:0 !important;border-right:1px dotted #d0d0d0 !important;border-left:0 !important;border-top:0 !important;padding:0 4px 0 4px !important;color:#fff !important;height:35px !important}div.grd_headTblCont table td{border-bottom:1px dotted #39424b !important;border-right:1px dotted #fff !important;border-left:0 !important;border-top:0 !important;background-color:#81963b !important;padding:1px 3px 1px 3px !important}.grd_inf{background-color:#d8d8d8;border-top:1px solid #d0d0d0 !important}.loader{border:0 !important;background:#81963b !important}.defaultLoader{width:32px;height:32px;background:transparent url("images/img_loading.gif") 0 0 no-repeat !important}.even{background-color:#bccd83}.odd{background-color:#fff}span.expClpFlt a.btnExpClpFlt:hover{background-color:transparent !important}.activeHeader{background:#81963b !important} table.TF{border-left:1px dotted #81963b;border-top:none;border-right:0;border-bottom:none;}table.TF th{background:#39424b url("images/bg_headers.jpg") left top repeat-x;border-bottom:0;border-right:1px dotted #d0d0d0;border-left:0;border-top:0;color:#fff}table.TF td{border-bottom:1px dotted #81963b;border-right:1px dotted #81963b;padding:5px}.fltrow{background-color:#81963b !important;}.fltrow th,.fltrow td{border-bottom:1px dotted #39424b !important;border-right:1px dotted #fff !important;border-left:0 !important;border-top:0 !important;padding:1px 3px 1px 3px !important}.flt,select.flt,select.flt_multi,.flt_s,.single_flt,.div_checklist{border:1px solid #687830 !important}input.flt{width:99% !important}.inf{background:#d8d8d8;height:$min-height}input.reset{width:53px;background:transparent url("images/btn_filter.png") center center no-repeat !important}.helpBtn:hover{background-color:transparent}.nextPage{background:transparent url("images/btn_next_page.gif") center center no-repeat !important}.previousPage{background:transparent url("images/btn_previous_page.gif") center center no-repeat !important}.firstPage{background:transparent url("images/btn_first_page.gif") center center no-repeat !important}.lastPage{background:transparent url("images/btn_last_page.gif") center center no-repeat !important}div.grd_Cont{background:#81963b url("images/bg_headers.jpg") left top repeat-x !important;border:1px solid #ccc !important;padding:0 1px 1px 1px !important;}div.grd_Cont .even{background-color:#bccd83}div.grd_Cont .odd{background-color:#fff}div.grd_headTblCont{background-color:#ebecee !important;border-bottom:none !important}div.grd_tblCont table{border-right:none !important;}div.grd_tblCont table td{border-bottom:1px dotted #81963b;border-right:1px dotted #81963b}div.grd_tblCont table th,div.grd_headTblCont table th{background:transparent url("images/bg_headers.jpg") 0 0 repeat-x !important;border-bottom:0 !important;border-right:1px dotted #d0d0d0 !important;border-left:0 !important;border-top:0 !important;padding:0 4px 0 4px !important;color:#fff !important;height:35px !important}div.grd_headTblCont table td{border-bottom:1px dotted #39424b !important;border-right:1px dotted #fff !important;border-left:0 !important;border-top:0 !important;background-color:#81963b !important;padding:1px 3px 1px 3px !important}.grd_inf{background-color:#d8d8d8;border-top:1px solid #d0d0d0 !important}.loader{border:0 !important;background:#81963b !important}.defaultLoader{width:32px;height:32px;background:transparent url("images/img_loading.gif") 0 0 no-repeat !important}.even{background-color:#bccd83}.odd{background-color:#fff}span.expClpFlt a.btnExpClpFlt:hover{background-color:transparent !important}.activeHeader{background:#81963b !important}

View file

@ -1,6 +1 @@
/**
* tablefilter v0.4.40 by Max Guglielmi
* build date: 2017-02-11T12:40:33.756Z
* MIT License
*/
table.TF{padding:0;color:#000;border-right:1px solid #a4bed4;border-top:1px solid #a4bed4;border-left:1px solid #a4bed4;border-bottom:0;}table.TF th{margin:0;color:inherit;background:#d1e5fe url("images/bg_skyblue.gif") 0 0 repeat-x;border-color:#fdfdfd #a4bed4 #a4bed4 #fdfdfd;border-width:1px;border-style:solid}table.TF td{margin:0;padding:5px;color:inherit;border-bottom:1px solid #a4bed4;border-left:0;border-top:0;border-right:0}.fltrow{background-color:#d1e5fe !important;}.fltrow th,.fltrow td{padding:1px 3px 1px 3px !important}.flt,select.flt,select.flt_multi,.flt_s,.single_flt,.div_checklist{border:1px solid #a4bed4 !important}input.flt{width:99% !important}.inf{background-color:#e3efff !important;border:1px solid #a4bed4;height:$min-height;color:#004a6f}div.tot,div.status{border-right:0 !important}.helpBtn:hover{background-color:transparent}input.reset{background:transparent url("images/icn_clear_filters.png") center center no-repeat !important}.nextPage{background:transparent url("images/btn_next_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.nextPage:hover{background:#ffe4ab url("images/btn_next_page.gif") center center no-repeat !important;border:1px solid #ffb552 !important}.previousPage{background:transparent url("images/btn_prev_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.previousPage:hover{background:#ffe4ab url("images/btn_prev_page.gif") center center no-repeat !important;border:1px solid #ffb552 !important}.firstPage{background:transparent url("images/btn_first_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.firstPage:hover{background:#ffe4ab url("images/btn_first_page.gif") center center no-repeat !important;border:1px solid #ffb552 !important}.lastPage{background:transparent url("images/btn_last_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.lastPage:hover{background:#ffe4ab url("images/btn_last_page.gif") center center no-repeat !important;border:1px solid #ffb552 !important}.activeHeader{background:#ffe4ab !important;border:1px solid #ffb552 !important;color:inherit !important}div.grd_Cont{background-color:#d9eaed !important;border:1px solid #9cc !important;padding:0 !important;}div.grd_Cont .even{background-color:#fff}div.grd_Cont .odd{background-color:#e3efff}div.grd_headTblCont{background-color:#d9eaed !important;border-bottom:none !important}div.grd_tblCont table{border-right:none !important}div.grd_tblCont table th,div.grd_headTblCont table th,div.grd_headTblCont table td{background:#d9eaed url("images/bg_skyblue.gif") left top repeat-x;border-bottom:1px solid #a4bed4;border-right:1px solid #a4bed4 !important;border-left:1px solid #fff !important;border-top:1px solid #fff !important}div.grd_tblCont table td{border-bottom:1px solid #a4bed4 !important;border-right:0 !important;border-left:0 !important;border-top:0 !important}.grd_inf{background-color:#cce2fe;color:#004a6f;border-top:1px solid #9cc !important;}.grd_inf a{text-decoration:none;font-weight:bold}.loader{background-color:#2d8eef;border:1px solid #cce2fe;border-radius:5px}.even{background-color:#fff}.odd{background-color:#e3efff}span.expClpFlt a.btnExpClpFlt:hover{background-color:transparent !important}.ezActiveRow{background-color:#ffdc61 !important;color:inherit}.ezSelectedRow{background-color:#ffe4ab !important;color:inherit}.ezActiveCell{background-color:#fff !important;color:#000 !important;font-weight:bold}.ezETSelectedCell{background-color:#fff !important;font-weight:bold;color:#000 !important} table.TF{padding:0;color:#000;border-right:1px solid #a4bed4;border-top:1px solid #a4bed4;border-left:1px solid #a4bed4;border-bottom:0;}table.TF th{margin:0;color:inherit;background:#d1e5fe url("images/bg_skyblue.gif") 0 0 repeat-x;border-color:#fdfdfd #a4bed4 #a4bed4 #fdfdfd;border-width:1px;border-style:solid}table.TF td{margin:0;padding:5px;color:inherit;border-bottom:1px solid #a4bed4;border-left:0;border-top:0;border-right:0}.fltrow{background-color:#d1e5fe !important;}.fltrow th,.fltrow td{padding:1px 3px 1px 3px !important}.flt,select.flt,select.flt_multi,.flt_s,.single_flt,.div_checklist{border:1px solid #a4bed4 !important}input.flt{width:99% !important}.inf{background-color:#e3efff !important;border:1px solid #a4bed4;height:$min-height;color:#004a6f}div.tot,div.status{border-right:0 !important}.helpBtn:hover{background-color:transparent}input.reset{background:transparent url("images/icn_clear_filters.png") center center no-repeat !important}.nextPage{background:transparent url("images/btn_next_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.nextPage:hover{background:#ffe4ab url("images/btn_next_page.gif") center center no-repeat !important;border:1px solid #ffb552 !important}.previousPage{background:transparent url("images/btn_prev_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.previousPage:hover{background:#ffe4ab url("images/btn_prev_page.gif") center center no-repeat !important;border:1px solid #ffb552 !important}.firstPage{background:transparent url("images/btn_first_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.firstPage:hover{background:#ffe4ab url("images/btn_first_page.gif") center center no-repeat !important;border:1px solid #ffb552 !important}.lastPage{background:transparent url("images/btn_last_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.lastPage:hover{background:#ffe4ab url("images/btn_last_page.gif") center center no-repeat !important;border:1px solid #ffb552 !important}.activeHeader{background:#ffe4ab !important;border:1px solid #ffb552 !important;color:inherit !important}div.grd_Cont{background-color:#d9eaed !important;border:1px solid #9cc !important;padding:0 !important;}div.grd_Cont .even{background-color:#fff}div.grd_Cont .odd{background-color:#e3efff}div.grd_headTblCont{background-color:#d9eaed !important;border-bottom:none !important}div.grd_tblCont table{border-right:none !important}div.grd_tblCont table th,div.grd_headTblCont table th,div.grd_headTblCont table td{background:#d9eaed url("images/bg_skyblue.gif") left top repeat-x;border-bottom:1px solid #a4bed4;border-right:1px solid #a4bed4 !important;border-left:1px solid #fff !important;border-top:1px solid #fff !important}div.grd_tblCont table td{border-bottom:1px solid #a4bed4 !important;border-right:0 !important;border-left:0 !important;border-top:0 !important}.grd_inf{background-color:#cce2fe;color:#004a6f;border-top:1px solid #9cc !important;}.grd_inf a{text-decoration:none;font-weight:bold}.loader{background-color:#2d8eef;border:1px solid #cce2fe;border-radius:5px}.even{background-color:#fff}.odd{background-color:#e3efff}span.expClpFlt a.btnExpClpFlt:hover{background-color:transparent !important}.ezActiveRow{background-color:#ffdc61 !important;color:inherit}.ezSelectedRow{background-color:#ffe4ab !important;color:inherit}.ezActiveCell{background-color:#fff !important;color:#000 !important;font-weight:bold}.ezETSelectedCell{background-color:#fff !important;font-weight:bold;color:#000 !important}

View file

@ -1,6 +1 @@
/**
* tablefilter v0.4.40 by Max Guglielmi
* build date: 2017-02-11T12:40:33.756Z
* MIT License
*/
table.TF{padding:0;color:inherit;border-right:1px solid transparent;border-top:1px solid transparent;border-left:1px solid transparent;border-bottom:0;}table.TF th{margin:0;color:inherit;background-color:transparent;border-color:transparent;border-width:1px;border-style:solid;}table.TF th:last-child{border-right:1px solid transparent}table.TF td{margin:0;padding:5px;color:inherit;border-bottom:1px solid transparent;border-left:0;border-top:0;border-right:0}.fltrow{background-color:transparent;}.fltrow th,.fltrow td{padding:1px 3px 1px 3px;border-bottom:1px solid transparent !important;}.fltrow th:last-child,.fltrow td:last-child{border-right:1px solid transparent}.flt,select.flt,select.flt_multi,.flt_s,.single_flt,.div_checklist{border:1px solid #a4bed4}input.flt{width:99% !important}.inf{background-color:transparent;border:1px solid transparent;height:$min-height;color:inherit}div.tot,div.status{border-right:0 !important}.helpBtn:hover{background-color:transparent}input.reset{background:transparent url("images/icn_clear_filters.png") center center no-repeat !important}.nextPage{background:transparent url("images/btn_next_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.nextPage:hover{background:#f7f7f7 url("images/btn_next_page.gif") center center no-repeat !important;border:1px solid #f7f7f7 !important}.previousPage{background:transparent url("images/btn_prev_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.previousPage:hover{background:#f7f7f7 url("images/btn_prev_page.gif") center center no-repeat !important;border:1px solid #f7f7f7 !important}.firstPage{background:transparent url("images/btn_first_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.firstPage:hover{background:#f7f7f7 url("images/btn_first_page.gif") center center no-repeat !important;border:1px solid #f7f7f7 !important}.lastPage{background:transparent url("images/btn_last_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.lastPage:hover{background:#f7f7f7 url("images/btn_last_page.gif") center center no-repeat !important;border:1px solid #f7f7f7 !important}.activeHeader{background:#f7f7f7 !important;border:1px solid transparent;color:inherit !important}div.grd_Cont{-webkit-box-shadow:0 0 0 0 rgba(50,50,50,0.75);-moz-box-shadow:0 0 0 0 rgba(50,50,50,0.75);box-shadow:0 0 0 0 rgba(50,50,50,0.75);background-color:transparent;border:1px solid transparent;padding:0 !important;}div.grd_Cont .even{background-color:transparent}div.grd_Cont .odd{background-color:#f7f7f7}div.grd_headTblCont{background-color:transparent;border-bottom:none !important}div.grd_tblCont table{border-right:none !important}div.grd_tblCont table th,div.grd_headTblCont table th,div.grd_headTblCont table td{background:transparent;border-bottom:1px solid transparent;border-right:1px solid transparent !important;border-left:1px solid transparent;border-top:1px solid transparent}div.grd_tblCont table td{border-bottom:1px solid transparent;border-right:0 !important;border-left:0 !important;border-top:0 !important}.grd_inf{background-color:transparent;color:inherit;border-top:1px solid transparent;}.grd_inf a{text-decoration:none;font-weight:bold}.loader{background-color:#f7f7f7;border:1px solid #f7f7f7;border-radius:5px;color:#000;text-shadow:none}.even{background-color:transparent}.odd{background-color:#f7f7f7}span.expClpFlt a.btnExpClpFlt:hover{background-color:transparent !important}.ezActiveRow{background-color:#ccc !important;color:inherit}.ezSelectedRow{background-color:#ccc !important;color:inherit}.ezActiveCell{background-color:transparent;color:inherit;font-weight:bold}.ezETSelectedCell{background-color:transparent;font-weight:bold;color:inherit} table.TF{padding:0;color:inherit;border-right:1px solid transparent;border-top:1px solid transparent;border-left:1px solid transparent;border-bottom:0;}table.TF th{margin:0;color:inherit;background-color:transparent;border-color:transparent;border-width:1px;border-style:solid;}table.TF th:last-child{border-right:1px solid transparent}table.TF td{margin:0;padding:5px;color:inherit;border-bottom:1px solid transparent;border-left:0;border-top:0;border-right:0}.fltrow{background-color:transparent;}.fltrow th,.fltrow td{padding:1px 3px 1px 3px;border-bottom:1px solid transparent !important;}.fltrow th:last-child,.fltrow td:last-child{border-right:1px solid transparent}.flt,select.flt,select.flt_multi,.flt_s,.single_flt,.div_checklist{border:1px solid #a4bed4}input.flt{width:99% !important}.inf{background-color:transparent;border:1px solid transparent;height:$min-height;color:inherit}div.tot,div.status{border-right:0 !important}.helpBtn:hover{background-color:transparent}input.reset{background:transparent url("images/icn_clear_filters.png") center center no-repeat !important}.nextPage{background:transparent url("images/btn_next_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.nextPage:hover{background:#f7f7f7 url("images/btn_next_page.gif") center center no-repeat !important;border:1px solid #f7f7f7 !important}.previousPage{background:transparent url("images/btn_prev_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.previousPage:hover{background:#f7f7f7 url("images/btn_prev_page.gif") center center no-repeat !important;border:1px solid #f7f7f7 !important}.firstPage{background:transparent url("images/btn_first_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.firstPage:hover{background:#f7f7f7 url("images/btn_first_page.gif") center center no-repeat !important;border:1px solid #f7f7f7 !important}.lastPage{background:transparent url("images/btn_last_page.gif") center center no-repeat !important;border:1px solid transparent !important;}.lastPage:hover{background:#f7f7f7 url("images/btn_last_page.gif") center center no-repeat !important;border:1px solid #f7f7f7 !important}.activeHeader{background:#f7f7f7 !important;border:1px solid transparent;color:inherit !important}div.grd_Cont{-webkit-box-shadow:0 0 0 0 rgba(50,50,50,0.75);-moz-box-shadow:0 0 0 0 rgba(50,50,50,0.75);box-shadow:0 0 0 0 rgba(50,50,50,0.75);background-color:transparent;border:1px solid transparent;padding:0 !important;}div.grd_Cont .even{background-color:transparent}div.grd_Cont .odd{background-color:#f7f7f7}div.grd_headTblCont{background-color:transparent;border-bottom:none !important}div.grd_tblCont table{border-right:none !important}div.grd_tblCont table th,div.grd_headTblCont table th,div.grd_headTblCont table td{background:transparent;border-bottom:1px solid transparent;border-right:1px solid transparent !important;border-left:1px solid transparent;border-top:1px solid transparent}div.grd_tblCont table td{border-bottom:1px solid transparent;border-right:0 !important;border-left:0 !important;border-top:0 !important}.grd_inf{background-color:transparent;color:inherit;border-top:1px solid transparent;}.grd_inf a{text-decoration:none;font-weight:bold}.loader{background-color:#f7f7f7;border:1px solid #f7f7f7;border-radius:5px;color:#000;text-shadow:none}.even{background-color:transparent}.odd{background-color:#f7f7f7}span.expClpFlt a.btnExpClpFlt:hover{background-color:transparent !important}.ezActiveRow{background-color:#ccc !important;color:inherit}.ezSelectedRow{background-color:#ccc !important;color:inherit}.ezActiveCell{background-color:transparent;color:inherit;font-weight:bold}.ezETSelectedCell{background-color:transparent;font-weight:bold;color:inherit}

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

12319
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{ {
"name": "tablefilter", "name": "tablefilter",
"version": "0.4.40", "version": "0.7.3",
"description": "A Javascript library making HTML tables filterable and a bit more", "description": "A Javascript library making HTML tables filterable and a bit more",
"license": "MIT", "license": "MIT",
"author": { "author": {
@ -22,54 +22,58 @@
"pagination" "pagination"
], ],
"scripts": { "scripts": {
"dev": "grunt dev", "lint": "eslint src/**/*.js test/*.js *.js",
"build": "grunt build", "dev": "webpack --colors --config webpack.dev.config.js",
"build": "webpack --colors --config webpack.config.js",
"build:css": "stylus -c static/style/tablefilter.styl -o dist/tablefilter/style && stylus -c static/style/extensions -o dist/tablefilter/style && stylus -c static/style/themes/default -o dist/tablefilter/style/themes/default && stylus -c static/style/themes/mytheme -o dist/tablefilter/style/themes/mytheme && stylus -c static/style/themes/skyblue -o dist/tablefilter/style/themes/skyblue && stylus -c static/style/themes/transparent -o dist/tablefilter/style/themes/transparent",
"build:demos": "grunt build-demos", "build:demos": "grunt build-demos",
"server": "grunt server", "build:test": "webpack --colors --config webpack.test.config.js",
"eslint": "grunt eslint", "server": "webpack-dev-server --colors --hot --config ./webpack.dev.config.js",
"test": "grunt test", "test": "grunt test",
"codecov": "./node_modules/.bin/codecov", "codecov": "./node_modules/.bin/codecov",
"esdoc": "grunt esdoc", "esdoc": "esdoc",
"dist": "grunt", "dist": "grunt",
"deploy": "grunt deploy", "build:all": "grunt build-all",
"start": "npm run server" "start": "npm run server"
}, },
"publishConfig": { "publishConfig": {
"tag": "next" "tag": "next"
}, },
"devDependencies": { "devDependencies": {
"babel-core": "^6.22.1", "@babel/core": "7.10.0",
"babel-eslint": "7.1.1", "@babel/preset-env": "7.10.0",
"babel-loader": "^6.2.9", "babel-eslint": "10.1.0",
"babel-plugin-transform-es2015-classes": "^6.22.0", "babel-loader": "^8.0.2",
"babel-preset-es2015": "^6.22.0", "babel-preset-env": "1.7.0",
"clean-webpack-plugin": "^0.1.15", "clean-webpack-plugin": "^3.0.0",
"codecov": "1.0.1", "codecov": "3.7.1",
"diacritics": "1.3.0", "diacritics": "1.3.0",
"esdoc": "1.1.0",
"esdoc-standard-plugin": "1.0.0",
"eslint": "6.5.0",
"format-number": "3.0.0",
"grunt": "^1.0.1", "grunt": "^1.0.1",
"grunt-babel": "^6.0.0", "grunt-cli": "1.3.2",
"grunt-cli": "1.2.0", "grunt-contrib-clean": "^2.0.0",
"grunt-contrib-clean": "^1.0.0", "grunt-contrib-connect": "^2.0.0",
"grunt-contrib-connect": "^1.0.2",
"grunt-contrib-copy": "^1.0.0", "grunt-contrib-copy": "^1.0.0",
"grunt-contrib-stylus": "^1.2.0",
"grunt-contrib-watch": "^1.0.0", "grunt-contrib-watch": "^1.0.0",
"grunt-esdoc": "^0.0.4", "grunt-qunit-istanbul": "1.1.0",
"grunt-eslint": "19.0.0", "grunt-shell": "3.0.0",
"grunt-gh-pages": "^2.0.0",
"grunt-qunit-istanbul": "1.0.0",
"grunt-string-replace": "^1.3.1", "grunt-string-replace": "^1.3.1",
"grunt-webpack": "^2.0.1",
"isparta-loader": "2.0.0", "isparta-loader": "2.0.0",
"script-loader": "^0.7.0", "script-loader": "^0.7.0",
"string-replace-webpack-plugin": "^0.0.5", "string-replace-webpack-plugin": "^0.1.3",
"sugar-date": "2.0.4", "stylus": "^0.54.5",
"webpack": "^2.2.1", "sugar-date": "2.0.6",
"webpack-dev-server": "^2.3.0" "uglifyjs-webpack-plugin": "2.2.0",
"webpack": "^4.38.0",
"webpack-cli": "^3.0.8",
"webpack-dev-server": "^3.1.11"
}, },
"dependencies": {}, "dependencies": {},
"bugs": { "bugs": {
"url": "https://github.com/koalyptus/TableFilter/issues" "url": "https://github.com/koalyptus/TableFilter/issues"
}, },
"homepage": "http://koalyptus.github.io/TableFilter" "homepage": "https://www.tablefilter.com"
} }

View file

@ -19,4 +19,4 @@ export const has = (arr, val, caseSensitive) => {
} }
} }
return false; return false;
} };

View file

@ -18,7 +18,7 @@ export const getText = (node) => {
return trim(node.innerText); return trim(node.innerText);
} }
return trim(node.textContent); return trim(node.textContent);
} };
/** /**
* Returns the first text node contained in the supplied node * Returns the first text node contained in the supplied node
@ -32,11 +32,11 @@ export const getFirstTextNode = (node) => {
return n.data; return n.data;
} }
} }
} };
/** /**
* Creates an html element with given collection of attributes * Creates an html element with given collection of attributes
* @param {String} tag a string of the html tag to create * @param {String} tag html tag name
* @param {Array} an undetermined number of arrays containing the with 2 * @param {Array} an undetermined number of arrays containing the with 2
* items, the attribute name and its value ['id','myId'] * items, the attribute name and its value ['id','myId']
* @return {Object} created element * @return {Object} created element
@ -55,9 +55,8 @@ export const createElm = (...args) => {
el.setAttribute(arg[0], arg[1]); el.setAttribute(arg[0], arg[1]);
} }
} }
return el; return el;
} };
/** /**
* Removes passed node from DOM * Removes passed node from DOM
@ -88,7 +87,7 @@ export const hasClass = (ele, cls) => {
return ele.classList.contains(cls); return ele.classList.contains(cls);
} }
return ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')); return ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
} };
/** /**
* Adds the specified class to the passed element * Adds the specified class to the passed element
@ -111,7 +110,7 @@ export const addClass = (ele, cls) => {
else if (!hasClass(ele, cls)) { else if (!hasClass(ele, cls)) {
ele.className += ' ' + cls; ele.className += ' ' + cls;
} }
} };
/** /**
* Removes the specified class to the passed element * Removes the specified class to the passed element
@ -129,7 +128,7 @@ export const removeClass = (ele, cls) => {
} }
let reg = new RegExp('(\\s|^)' + cls + '(\\s|$)', 'g'); let reg = new RegExp('(\\s|^)' + cls + '(\\s|$)', 'g');
ele.className = ele.className.replace(reg, ''); ele.className = ele.className.replace(reg, '');
} };
/** /**
* Creates and returns an option element * Creates and returns an option element
@ -145,23 +144,25 @@ export const createOpt = (text, value, isSel) => {
createElm('option', ['value', value]); createElm('option', ['value', value]);
opt.appendChild(createText(text)); opt.appendChild(createText(text));
return opt; return opt;
} };
/** /**
* Creates and returns a checklist item * Creates and returns a checklist item
* @param {String} id index of check item * @param {String} id index of check item
* @param {String} chkValue check item value * @param {String} chkValue check item value
* @param {String} labelText check item label text * @param {String} labelText check item label text
* @param {Array} extraAttr array containing attribute name and its value
* @return {Object} li DOM element * @return {Object} li DOM element
*/ */
export const createCheckItem = (id, chkValue, labelText) => { export const createCheckItem = (id, chkValue, labelText, extraAttr = []) => {
let li = createElm('li'); let li = createElm('li');
let label = createElm('label', ['for', id]); let label = createElm('label', ['for', id]);
let check = createElm('input', let check = createElm('input',
['id', id], ['id', id],
['name', id], ['name', id],
['type', 'checkbox'], ['type', 'checkbox'],
['value', chkValue] ['value', chkValue],
extraAttr
); );
label.appendChild(check); label.appendChild(check);
label.appendChild(createText(labelText)); label.appendChild(createText(labelText));
@ -169,7 +170,7 @@ export const createCheckItem = (id, chkValue, labelText) => {
li.label = label; li.label = label;
li.check = check; li.check = check;
return li; return li;
} };
/** /**
* Returns the element matching the supplied Id * Returns the element matching the supplied Id

View file

@ -99,3 +99,26 @@ export const keyCode = (evt) => {
return evt.charCode ? evt.charCode : return evt.charCode ? evt.charCode :
(evt.keyCode ? evt.keyCode : (evt.which ? evt.which : 0)); (evt.keyCode ? evt.keyCode : (evt.which ? evt.which : 0));
}; };
/**
* Check code of pressed key is one of the expected key codes
*
* @param {Event} evt key event
* @param {Array} keyCodes list of keycodes to check
*/
export const isKeyPressed = (evt, keyCodes = []) => {
return keyCodes.indexOf(keyCode(evt)) !== -1;
};
/**
* Bind passed function to passed scope
* @param {Function} fn function
* @param {Object} scope object instance
*/
export function bound(fn, scope) {
let boundFnName = `${fn.name}_bound`;
if (!scope[boundFnName]) {
scope[boundFnName] = fn.bind(scope);
}
return scope[boundFnName];
}

View file

@ -1,6 +1,7 @@
import {Feature} from '../../feature'; import {Feature} from '../../feature';
import {tag} from '../../dom'; import {tag} from '../../dom';
import {INPUT} from '../../const'; import {INPUT} from '../../const';
import {defaultsStr} from '../../settings';
import {root} from '../../root'; import {root} from '../../root';
const INSTANTIATION_ERROR = `Failed to instantiate EditTable object. const INSTANTIATION_ERROR = `Failed to instantiate EditTable object.
@ -20,19 +21,19 @@ export default class AdapterEzEditTable extends Feature {
* @param {Object} cfg Configuration options for ezEditTable library * @param {Object} cfg Configuration options for ezEditTable library
*/ */
constructor(tf, cfg) { constructor(tf, cfg) {
super(tf, cfg.name); super(tf, AdapterEzEditTable);
/** /**
* Module description * Module description
* @type {String} * @type {String}
*/ */
this.desc = cfg.description || 'ezEditTable adapter'; this.desc = defaultsStr(cfg.description, 'ezEditTable adapter');
/** /**
* Filename of ezEditTable library * Filename of ezEditTable library
* @type {String} * @type {String}
*/ */
this.filename = cfg.filename || 'ezEditTable.js'; this.filename = defaultsStr(cfg.filename, 'ezEditTable.js');
/** /**
* Path to ezEditTable library * Path to ezEditTable library
@ -50,13 +51,15 @@ export default class AdapterEzEditTable extends Feature {
* Path to ezEditTable stylesheet * Path to ezEditTable stylesheet
* @type {String} * @type {String}
*/ */
this.stylesheet = cfg.stylesheet || this.vendorPath + 'ezEditTable.css'; this.stylesheet = defaultsStr(cfg.stylesheet,
this.vendorPath + 'ezEditTable.css');
/** /**
* Name of ezEditTable stylesheet * Name of ezEditTable stylesheet
* @type {String} * @type {String}
*/ */
this.stylesheetName = cfg.stylesheet_name || 'ezEditTableCss'; this.stylesheetName = defaultsStr(cfg.stylesheet_name,
'ezEditTableCss');
// Enable the ezEditTable's scroll into view behaviour if grid layout on // Enable the ezEditTable's scroll into view behaviour if grid layout on
cfg.scroll_into_view = cfg.scroll_into_view === false ? cfg.scroll_into_view = cfg.scroll_into_view === false ?
@ -117,7 +120,7 @@ export default class AdapterEzEditTable extends Feature {
//start row for EditTable constructor needs to be calculated //start row for EditTable constructor needs to be calculated
let startRow, let startRow,
cfg = this.cfg, cfg = this.cfg,
thead = tag(tf.tbl, 'thead'); thead = tag(tf.dom(), 'thead');
//if thead exists and startRow not specified, startRow is calculated //if thead exists and startRow not specified, startRow is calculated
//automatically by EditTable //automatically by EditTable
@ -158,7 +161,7 @@ export default class AdapterEzEditTable extends Feature {
et.ClearSelections(); et.ClearSelections();
/* eslint-enable */ /* eslint-enable */
let cellIndex = selectedElm.cellIndex, let cellIndex = selectedElm.cellIndex,
row = tf.tbl.rows[nextRowIndex]; row = tf.dom().rows[nextRowIndex];
if (et.defaultSelection === 'both') { if (et.defaultSelection === 'both') {
/* eslint-disable */ /* eslint-disable */
slc.SelectRowByIndex(nextRowIndex); slc.SelectRowByIndex(nextRowIndex);
@ -172,7 +175,7 @@ export default class AdapterEzEditTable extends Feature {
} }
//Table is filtered //Table is filtered
if (tf.validRowsIndex.length !== tf.getRowsNb()) { if (tf.validRowsIndex.length !== tf.getRowsNb()) {
let r = tf.tbl.rows[nextRowIndex]; let r = tf.dom().rows[nextRowIndex];
if (r) { if (r) {
r.scrollIntoView(false); r.scrollIntoView(false);
} }
@ -208,7 +211,7 @@ export default class AdapterEzEditTable extends Feature {
paging = tf.feature('paging'), paging = tf.feature('paging'),
//pgup/pgdown keys //pgup/pgdown keys
d = keyCode === 34 || keyCode === 33 ? d = keyCode === 34 || keyCode === 33 ?
(paging && paging.pagingLength || et.nbRowsPerPage) : (paging && paging.pageLength || et.nbRowsPerPage) :
1; 1;
//If next row is not valid, next valid filtered row needs to be //If next row is not valid, next valid filtered row needs to be
@ -278,11 +281,11 @@ export default class AdapterEzEditTable extends Feature {
if (tf.feature('paging').nbPages > 1) { if (tf.feature('paging').nbPages > 1) {
let paging = tf.feature('paging'); let paging = tf.feature('paging');
//page length is re-assigned in case it has changed //page length is re-assigned in case it has changed
et.nbRowsPerPage = paging.pagingLength; et.nbRowsPerPage = paging.pageLength;
let validIndexes = tf.validRowsIndex, let validIndexes = tf.validRowsIndex,
validIdxLen = validIndexes.length, validIdxLen = validIndexes.length,
pagingEndRow = parseInt(paging.startPagingRow, 10) + pagingEndRow = parseInt(paging.startPagingRow, 10) +
parseInt(paging.pagingLength, 10); parseInt(paging.pageLength, 10);
let rowIndex = row.rowIndex; let rowIndex = row.rowIndex;
if ((rowIndex === validIndexes[validIdxLen - 1]) && if ((rowIndex === validIndexes[validIdxLen - 1]) &&
@ -502,3 +505,5 @@ export default class AdapterEzEditTable extends Feature {
this.initialized = false; this.initialized = false;
} }
} }
AdapterEzEditTable.meta = {altName: 'advancedGrid'};

View file

@ -1,7 +1,11 @@
import {Feature} from '../../feature'; import {Feature} from '../../feature';
import {createText, elm} from '../../dom'; import {createText, elm} from '../../dom';
import {isArray, isFn, isUndef, isEmpty, EMPTY_FN} from '../../types'; import {isArray, isEmpty, EMPTY_FN} from '../../types';
import {numSortAsc} from '../../sort'; import {numSortAsc} from '../../sort';
import {FORMATTED_NUMBER} from '../../const';
import formatNumber from 'format-number';
import {defaultsFn, defaultsArr} from '../../settings';
import {bound} from '../../event';
const EVENTS = [ const EVENTS = [
'after-filtering', 'after-filtering',
@ -29,21 +33,19 @@ export default class ColOps extends Feature {
* @param {Object} opts Configuration object * @param {Object} opts Configuration object
*/ */
constructor(tf, opts) { constructor(tf, opts) {
super(tf, opts.name); super(tf, ColOps);
/** /**
* Callback fired before columns operations start * Callback fired before columns operations start
* @type {Function} * @type {Function}
*/ */
this.onBeforeOperation = isFn(opts.on_before_operation) ? this.onBeforeOperation = defaultsFn(opts.on_before_operation, EMPTY_FN);
opts.on_before_operation : EMPTY_FN;
/** /**
* Callback fired after columns operations are completed * Callback fired after columns operations are completed
* @type {Function} * @type {Function}
*/ */
this.onAfterOperation = isFn(opts.on_after_operation) ? this.onAfterOperation = defaultsFn(opts.on_after_operation, EMPTY_FN);
opts.on_after_operation : EMPTY_FN;
/** /**
* Configuration options * Configuration options
@ -55,46 +57,53 @@ export default class ColOps extends Feature {
* List of DOM element IDs containing column's calculation result * List of DOM element IDs containing column's calculation result
* @type {Array} * @type {Array}
*/ */
this.labelIds = opts.id || []; this.labelIds = defaultsArr(opts.id, []);
/** /**
* List of columns' indexes for calculations * List of columns' indexes for calculations
* @type {Array} * @type {Array}
*/ */
this.colIndexes = opts.col || []; this.colIndexes = defaultsArr(opts.col, []);
/** /**
* List of operations - possible values: 'sum', 'mean', 'min', 'max', * List of operations - possible values: 'sum', 'mean', 'min', 'max',
* 'median', 'q1', 'q3' * 'median', 'q1', 'q3'
* @type {Array} * @type {Array}
*/ */
this.operations = opts.operation || []; this.operations = defaultsArr(opts.operation, []);
/** /**
* List of write methods used to write the result - possible values: * List of write methods used to write the result - possible values:
* 'innerHTML', 'setValue', 'createTextNode' * 'innerHTML', 'setValue', 'createTextNode'
* @type {Array} * @type {Array}
*/ */
this.outputTypes = opts.write_method || []; this.outputTypes = defaultsArr(opts.write_method, []);
/**
* List of format objects used for formatting the result -
* refer to https://github.com/componitable/format-number to check
* configuration options
* @type {Array}
*/
this.formatResults = defaultsArr(opts.format_result, []);
/** /**
* List of row indexes displaying the results * List of row indexes displaying the results
* @type {Array} * @type {Array}
*/ */
this.totRowIndexes = opts.tot_row_index || []; this.totRowIndexes = defaultsArr(opts.tot_row_index, []);
/** /**
* List of row indexes excluded from calculations * List of row indexes excluded from calculations
* @type {Array} * @type {Array}
*/ */
this.excludeRows = opts.exclude_row || []; this.excludeRows = defaultsArr(opts.exclude_row, []);
/** /**
* List of decimal precision for calculation results * List of decimal precision for calculation results
* @type {Array} * @type {Array}
*/ */
this.decimalPrecisions = isUndef(opts.decimal_precision) ? this.decimalPrecisions = defaultsArr(opts.decimal_precision, 2);
2 : opts.decimal_precision;
this.enable(); this.enable();
} }
@ -107,7 +116,7 @@ export default class ColOps extends Feature {
return; return;
} }
// subscribe to events // subscribe to events
this.emitter.on(EVENTS, () => this.calcAll()); this.emitter.on(EVENTS, bound(this.calcAll, this));
this.calcAll(); this.calcAll();
@ -140,13 +149,9 @@ export default class ColOps extends Feature {
this.onBeforeOperation(tf, this); this.onBeforeOperation(tf, this);
this.emitter.emit('before-column-operation', tf, this); this.emitter.emit('before-column-operation', tf, this);
let colIndexes = this.colIndexes, let { colIndexes, operations: colOperations, outputTypes,
colOperations = this.operations, totRowIndexes, excludeRows, formatResults,
outputTypes = this.outputTypes, decimalPrecisions } = this;
totRowIndexes = this.totRowIndexes,
excludeRows = this.excludeRows,
decimalPrecisions = isUndef(this.decimalPrecisions) ?
2 : this.decimalPrecisions;
//nuovella: determine unique list of columns to operate on //nuovella: determine unique list of columns to operate on
let uIndexes = []; let uIndexes = [];
@ -157,7 +162,7 @@ export default class ColOps extends Feature {
}); });
let nbCols = uIndexes.length, let nbCols = uIndexes.length,
rows = tf.tbl.rows, rows = tf.dom().rows,
colValues = []; colValues = [];
for (let u = 0; u < nbCols; u++) { for (let u = 0; u < nbCols; u++) {
@ -165,7 +170,7 @@ export default class ColOps extends Feature {
//use uIndexes because we only want to pass through this loop //use uIndexes because we only want to pass through this loop
//once for each column get the values in this unique column //once for each column get the values in this unique column
colValues.push( colValues.push(
tf.getFilteredDataCol(uIndexes[u], false, true, excludeRows) tf.getVisibleColumnData(uIndexes[u], false, excludeRows)
); );
let curValues = colValues[u]; let curValues = colValues[u];
@ -176,6 +181,7 @@ export default class ColOps extends Feature {
precisions = [], precisions = [],
labels = [], labels = [],
writeType, writeType,
formatResult = [],
idx = 0; idx = 0;
for (let k = 0; k < colIndexes.length; k++) { for (let k = 0; k < colIndexes.length; k++) {
@ -186,6 +192,8 @@ export default class ColOps extends Feature {
precisions[idx] = decimalPrecisions[k]; precisions[idx] = decimalPrecisions[k];
labels[idx] = this.labelIds[k]; labels[idx] = this.labelIds[k];
writeType = isArray(outputTypes) ? outputTypes[k] : null; writeType = isArray(outputTypes) ? outputTypes[k] : null;
formatResult[idx] =
this.configureFormat(uIndexes[u], formatResults[k]);
idx++; idx++;
} }
@ -219,7 +227,8 @@ export default class ColOps extends Feature {
result, result,
labels[i], labels[i],
writeType, writeType,
precisions[i] precisions[i],
formatResult[i]
); );
}//for i }//for i
@ -245,8 +254,8 @@ export default class ColOps extends Feature {
*/ */
columnCalc(colIndex, operation = SUM, precision) { columnCalc(colIndex, operation = SUM, precision) {
let excludeRows = this.excludeRows || []; let excludeRows = this.excludeRows || [];
let colValues = let colValues = tf.getVisibleColumnData(colIndex, false, excludeRows);
this.tf.getFilteredDataCol(colIndex, false, true, excludeRows);
return Number(this.calc(colValues, operation, precision)); return Number(this.calc(colValues, operation, precision));
} }
@ -402,7 +411,8 @@ export default class ColOps extends Feature {
* @param {Number} [precision=2] Applied decimal precision * @param {Number} [precision=2] Applied decimal precision
* @private * @private
*/ */
writeResult(result = 0, label, writeType = 'innerhtml', precision = 2) { writeResult(result = 0, label, writeType = 'innerhtml',
precision = 2, format = {}) {
let labelElm = elm(label); let labelElm = elm(label);
if (!labelElm) { if (!labelElm) {
@ -412,6 +422,8 @@ export default class ColOps extends Feature {
result = result.toFixed(precision); result = result.toFixed(precision);
if (isNaN(result) || !isFinite(result)) { if (isNaN(result) || !isFinite(result)) {
result = ''; result = '';
} else {
result = formatNumber(format)(result);
} }
switch (writeType.toLowerCase()) { switch (writeType.toLowerCase()) {
@ -429,13 +441,38 @@ export default class ColOps extends Feature {
} }
} }
/**
* Configure the format options used to format the operation result based
* on column type.
* @param {Number} colIndex Column index
* @param {Object} [format={}] Format object
* @returns {Object}
* @private
*/
configureFormat(colIndex, format = {}) {
let tf = this.tf;
if (tf.hasType(colIndex, [FORMATTED_NUMBER])) {
let colType = tf.colTypes[colIndex];
if (colType.decimal && !format.decimal) {
format.decimal = colType.decimal;
}
if (colType.thousands && !format.integerSeparator) {
format.integerSeparator = colType.thousands;
}
} else {
format.decimal = format.decimal || '';
format.integerSeparator = format.integerSeparator || '';
}
return format;
}
/** Remove extension */ /** Remove extension */
destroy() { destroy() {
if (!this.initialized) { if (!this.initialized) {
return; return;
} }
// unsubscribe to events // unsubscribe to events
this.emitter.off(EVENTS, () => this.calcAll()); this.emitter.off(EVENTS, bound(this.calcAll, this));
this.initialized = false; this.initialized = false;
} }

View file

@ -1,11 +1,16 @@
import {Feature} from '../../feature'; import {Feature} from '../../feature';
import { import {
addClass, removeClass, createCheckItem, createElm, elm, removeElm, addClass, removeClass, createCheckItem, createElm, elm, removeElm,
getText getText, tag
} from '../../dom'; } from '../../dom';
import {isFn, EMPTY_FN} from '../../types'; import {isUndef, EMPTY_FN, isNull} from '../../types';
import {addEvt, targetEvt, removeEvt} from '../../event'; import {addEvt, targetEvt, removeEvt} from '../../event';
import {root} from '../../root'; import {root} from '../../root';
import {NONE} from '../../const';
import {
defaultsBool, defaultsStr, defaultsFn, defaultsNb, defaultsArr
} from '../../settings';
import {RIGHT} from '../../modules/toolbar';
/** /**
* Columns Visibility extension * Columns Visibility extension
@ -18,7 +23,7 @@ export default class ColsVisibility extends Feature {
* @param {Object} Configuration object * @param {Object} Configuration object
*/ */
constructor(tf, f) { constructor(tf, f) {
super(tf, f.name); super(tf, ColsVisibility);
// Configuration object // Configuration object
let cfg = this.config; let cfg = this.config;
@ -33,7 +38,7 @@ export default class ColsVisibility extends Feature {
* Module description * Module description
* @type {String} * @type {String}
*/ */
this.desc = f.description || 'Columns visibility manager'; this.desc = defaultsStr(f.description, 'Columns visibility manager');
/** /**
* show/hide columns container element * show/hide columns container element
@ -57,13 +62,13 @@ export default class ColsVisibility extends Feature {
* Enable tick to hide a column, defaults to true * Enable tick to hide a column, defaults to true
* @type {Boolean} * @type {Boolean}
*/ */
this.tickToHide = f.tick_to_hide === false ? false : true; this.tickToHide = defaultsBool(f.tick_to_hide, true);
/** /**
* Enable columns manager UI, defaults to true * Enable columns manager UI, defaults to true
* @type {Boolean} * @type {Boolean}
*/ */
this.manager = f.manager === false ? false : true; this.manager = defaultsBool(f.manager, true);
/** /**
* Headers HTML table reference only if headers are external * Headers HTML table reference only if headers are external
@ -75,112 +80,115 @@ export default class ColsVisibility extends Feature {
* Headers row index only if headers are external * Headers row index only if headers are external
* @type {Number} * @type {Number}
*/ */
this.headersIndex = f.headers_index || 1; this.headersIndex = defaultsNb(f.headers_index, 1);
/** /**
* ID of main container element * ID of main container element
* @type {String} * @type {String}
*/ */
this.contElTgtId = f.container_target_id || null; this.contElTgtId = defaultsStr(f.container_target_id, null);
/** /**
* Alternative text for column headers in column manager UI * Alternative text for column headers in column manager UI
* @type {Array} * @type {Array}
*/ */
this.headersText = f.headers_text || null; this.headersText = defaultsArr(f.headers_text, []);
/** /**
* ID of button's container element * ID of button's container element
* @type {String} * @type {String}
*/ */
this.btnTgtId = f.btn_target_id || null; this.btnTgtId = defaultsStr(f.btn_target_id, null);
/** /**
* Button's text, defaults to Columns&#9660; * Button's text, defaults to Columns&#9660;
* @type {String} * @type {String}
*/ */
this.btnText = f.btn_text || 'Columns&#9660;'; this.btnText = defaultsStr(f.btn_text, 'Columns&#9660;');
/** /**
* Button's inner HTML * Button's inner HTML
* @type {String} * @type {String}
*/ */
this.btnHtml = f.btn_html || null; this.btnHtml = defaultsStr(f.btn_html, null);
/** /**
* Css class for button * Css class for button
* @type {String} * @type {String}
*/ */
this.btnCssClass = f.btn_css_class || 'colVis'; this.btnCssClass = defaultsStr(f.btn_css_class, 'colVis');
/** /**
* Columns manager UI close link text, defaults to 'Close' * Columns manager UI close link text, defaults to 'Close'
* @type {String} * @type {String}
*/ */
this.btnCloseText = f.btn_close_text || 'Close'; this.btnCloseText = defaultsStr(f.btn_close_text, 'Close');
/** /**
* Columns manager UI close link HTML * Columns manager UI close link HTML
* @type {String} * @type {String}
*/ */
this.btnCloseHtml = f.btn_close_html || null; this.btnCloseHtml = defaultsStr(f.btn_close_html, null);
/** /**
* Css for columns manager UI close link * Css for columns manager UI close link
* @type {String} * @type {String}
*/ */
this.btnCloseCssClass = f.btn_close_css_class || this.btnCssClass; this.btnCloseCssClass = defaultsStr(f.btn_close_css_class,
this.btnCssClass);
/** /**
* Extension's stylesheet filename * Extension's stylesheet filename
* @type {String} * @type {String}
*/ */
this.stylesheet = f.stylesheet || 'colsVisibility.css'; this.stylesheet = defaultsStr(f.stylesheet, 'colsVisibility.css');
/** /**
* Css for columns manager UI span * Css for columns manager UI span
* @type {String} * @type {String}
*/ */
this.spanCssClass = f.span_css_class || 'colVisSpan'; this.spanCssClass = defaultsStr(f.span_css_class, 'colVisSpan');
/** /**
* Css for columns manager UI main container * Css for columns manager UI main container
* @type {String} * @type {String}
*/ */
this.contCssClass = f.cont_css_class || 'colVisCont'; this.contCssClass = defaultsStr(f.cont_css_class, 'colVisCont');
/** /**
* Css for columns manager UI checklist (ul) * Css for columns manager UI checklist (ul)
* @type {String} * @type {String}
*/ */
this.listCssClass = cfg.list_css_class || 'cols_checklist'; this.listCssClass = defaultsStr(cfg.list_css_class, 'cols_checklist');
/** /**
* Css for columns manager UI checklist item (li) * Css for columns manager UI checklist item (li)
* @type {String} * @type {String}
*/ */
this.listItemCssClass = cfg.checklist_item_css_class || this.listItemCssClass = defaultsStr(cfg.checklist_item_css_class,
'cols_checklist_item'; 'cols_checklist_item');
/** /**
* Css for columns manager UI checklist item selected state (li) * Css for columns manager UI checklist item selected state (li)
* @type {String} * @type {String}
*/ */
this.listSlcItemCssClass = cfg.checklist_selected_item_css_class || this.listSlcItemCssClass = defaultsStr(
'cols_checklist_slc_item'; cfg.checklist_selected_item_css_class,
'cols_checklist_slc_item'
);
/** /**
* Text preceding the columns list, defaults to 'Hide' or 'Show' * Text preceding the columns list, defaults to 'Hide' or 'Show'
* depending on tick mode (tick_to_hide option) * depending on tick mode (tick_to_hide option)
* @type {String} * @type {String}
*/ */
this.text = f.text || (this.tickToHide ? 'Hide: ' : 'Show: '); this.text = defaultsStr(f.text, this.tickToHide ? 'Hide: ' : 'Show: ');
/** /**
* List of columns indexes to be hidden at initialization * List of columns indexes to be hidden at initialization
* @type {Array} * @type {Array}
*/ */
this.atStart = f.at_start || []; this.atStart = defaultsArr(f.at_start, []);
/** /**
* Enable hover behaviour on columns manager button/link * Enable hover behaviour on columns manager button/link
@ -198,7 +206,13 @@ export default class ColsVisibility extends Feature {
* Text for select all option, defaults to 'Select all:' * Text for select all option, defaults to 'Select all:'
* @type {String} * @type {String}
*/ */
this.tickAllText = f.tick_all_text || 'Select all:'; this.tickAllText = defaultsStr(f.tick_all_text, 'Select all:');
/**
* Default position in toolbar ('left'|'center'|'right')
* @type {String}
*/
this.toolbarPosition = defaultsStr(f.toolbar_position, RIGHT);
/** /**
* List of indexes of hidden columns * List of indexes of hidden columns
@ -216,73 +230,66 @@ export default class ColsVisibility extends Feature {
* Callback fired when the extension is initialized * Callback fired when the extension is initialized
* @type {Function} * @type {Function}
*/ */
this.onLoaded = isFn(f.on_loaded) ? f.on_loaded : EMPTY_FN; this.onLoaded = defaultsFn(f.on_loaded, EMPTY_FN);
/** /**
* Callback fired before the columns manager is opened * Callback fired before the columns manager is opened
* @type {Function} * @type {Function}
*/ */
this.onBeforeOpen = isFn(f.on_before_open) ? this.onBeforeOpen = defaultsFn(f.on_before_open, EMPTY_FN);
f.on_before_open : EMPTY_FN;
/** /**
* Callback fired after the columns manager is opened * Callback fired after the columns manager is opened
* @type {Function} * @type {Function}
*/ */
this.onAfterOpen = isFn(f.on_after_open) ? f.on_after_open : EMPTY_FN; this.onAfterOpen = defaultsFn(f.on_after_open, EMPTY_FN);
/** /**
* Callback fired before the columns manager is closed * Callback fired before the columns manager is closed
* @type {Function} * @type {Function}
*/ */
this.onBeforeClose = isFn(f.on_before_close) ? this.onBeforeClose = defaultsFn(f.on_before_close, EMPTY_FN);
f.on_before_close : EMPTY_FN;
/** /**
* Callback fired after the columns manager is closed * Callback fired after the columns manager is closed
* @type {Function} * @type {Function}
*/ */
this.onAfterClose = isFn(f.on_after_close) ? this.onAfterClose = defaultsFn(f.on_after_close, EMPTY_FN);
f.on_after_close : EMPTY_FN;
/** /**
* Callback fired before a column is hidden * Callback fired before a column is hidden
* @type {Function} * @type {Function}
*/ */
this.onBeforeColHidden = isFn(f.on_before_col_hidden) ? this.onBeforeColHidden = defaultsFn(f.on_before_col_hidden, EMPTY_FN);
f.on_before_col_hidden : EMPTY_FN;
/** /**
* Callback fired after a column is hidden * Callback fired after a column is hidden
* @type {Function} * @type {Function}
*/ */
this.onAfterColHidden = isFn(f.on_after_col_hidden) ? this.onAfterColHidden = defaultsFn(f.on_after_col_hidden, EMPTY_FN);
f.on_after_col_hidden : EMPTY_FN;
/** /**
* Callback fired before a column is displayed * Callback fired before a column is displayed
* @type {Function} * @type {Function}
*/ */
this.onBeforeColDisplayed = isFn(f.on_before_col_displayed) ? this.onBeforeColDisplayed = defaultsFn(f.on_before_col_displayed,
f.on_before_col_displayed : EMPTY_FN; EMPTY_FN);
/** /**
* Callback fired after a column is displayed * Callback fired after a column is displayed
* @type {Function} * @type {Function}
*/ */
this.onAfterColDisplayed = isFn(f.on_after_col_displayed) ? this.onAfterColDisplayed = defaultsFn(f.on_after_col_displayed,
f.on_after_col_displayed : EMPTY_FN; EMPTY_FN);
//Grid layout support //Grid layout support
if (tf.gridLayout) { if (tf.gridLayout) {
this.headersTbl = tf.feature('gridLayout').headTbl; //headers table this.headersTbl = tf.feature('gridLayout').headTbl; //headers table
this.headersIndex = 0; //headers index this.headersIndex = 0; //headers index
this.onAfterColDisplayed = function () { };
this.onAfterColHidden = function () { };
} }
//Loads extension stylesheet //Loads extension stylesheet
tf.import(f.name + 'Style', tf.stylePath + this.stylesheet, null, tf.import(f.name + 'Style', tf.getStylePath() + this.stylesheet, null,
'link'); 'link');
this.enable(); this.enable();
@ -324,7 +331,7 @@ export default class ColsVisibility extends Feature {
} }
this.contEl.style.display = contDisplay === 'inline' ? this.contEl.style.display = contDisplay === 'inline' ?
'none' : 'inline'; NONE : 'inline';
if (contDisplay !== 'inline') { if (contDisplay !== 'inline') {
this.onAfterOpen(this); this.onAfterOpen(this);
@ -369,6 +376,9 @@ export default class ColsVisibility extends Feature {
return; return;
} }
this.emitter.emit('initializing-extension', this,
!isNull(this.btnTgtId));
this.emitter.on(['hide-column'], this.emitter.on(['hide-column'],
(tf, colIndex) => this.hideCol(colIndex)); (tf, colIndex) => this.hideCol(colIndex));
@ -381,6 +391,7 @@ export default class ColsVisibility extends Feature {
this.boundMouseup = this.onMouseup.bind(this); this.boundMouseup = this.onMouseup.bind(this);
this.emitter.emit('columns-visibility-initialized', this.tf, this); this.emitter.emit('columns-visibility-initialized', this.tf, this);
this.emitter.emit('extension-initialized', this);
// Hide columns at start at very end of initialization, do not move // Hide columns at start at very end of initialization, do not move
// as order is important // as order is important
@ -398,11 +409,10 @@ export default class ColsVisibility extends Feature {
let span = createElm('span'); let span = createElm('span');
span.className = this.spanCssClass; span.className = this.spanCssClass;
//Container element (rdiv or custom element) // Container element (rdiv or custom element)
if (!this.btnTgtId) { let targetEl = !this.btnTgtId ?
tf.setToolbar(); tf.feature('toolbar').container(this.toolbarPosition) :
} elm(this.btnTgtId);
let targetEl = !this.btnTgtId ? tf.rDiv : elm(this.btnTgtId);
if (!this.btnTgtId) { if (!this.btnTgtId) {
let firstChild = targetEl.firstChild; let firstChild = targetEl.firstChild;
@ -423,7 +433,7 @@ export default class ColsVisibility extends Feature {
} else { } else {
addEvt(btn, 'mouseover', (evt) => this.toggle(evt)); addEvt(btn, 'mouseover', (evt) => this.toggle(evt));
} }
} else { //Custom html } else { // Custom html
span.innerHTML = this.btnHtml; span.innerHTML = this.btnHtml;
let colVisEl = span.firstChild; let colVisEl = span.firstChild;
if (!this.enableHover) { if (!this.enableHover) {
@ -459,7 +469,7 @@ export default class ColsVisibility extends Feature {
let ul = createElm('ul'); let ul = createElm('ul');
ul.className = this.listCssClass; ul.className = this.listCssClass;
let tbl = this.headersTbl ? this.headersTbl : tf.tbl; let tbl = this.headersTbl || tf.dom();
let headerIndex = this.headersTbl ? let headerIndex = this.headersTbl ?
this.headersIndex : tf.getHeadersRowIndex(); this.headersIndex : tf.getHeadersRowIndex();
let headerRow = tbl.rows[headerIndex]; let headerRow = tbl.rows[headerIndex];
@ -485,8 +495,7 @@ export default class ColsVisibility extends Feature {
for (let i = 0; i < headerRow.cells.length; i++) { for (let i = 0; i < headerRow.cells.length; i++) {
let cell = headerRow.cells[i]; let cell = headerRow.cells[i];
let cellText = this.headersText && this.headersText[i] ? let cellText = this.headersText[i] || this._getHeaderText(cell);
this.headersText[i] : this._getHeaderText(cell);
let liElm = createCheckItem('col_' + i + '_' + tf.id, cellText, let liElm = createCheckItem('col_' + i + '_' + tf.id, cellText,
cellText); cellText);
addClass(liElm, this.listItemCssClass); addClass(liElm, this.listItemCssClass);
@ -535,18 +544,17 @@ export default class ColsVisibility extends Feature {
*/ */
setHidden(colIndex, hide) { setHidden(colIndex, hide) {
let tf = this.tf; let tf = this.tf;
let tbl = tf.tbl; let tbl = tf.dom();
if (hide) { if (hide) {
this.onBeforeColHidden(this, colIndex); this.onBeforeColHidden(this, colIndex);
} } else {
if (!hide) {
this.onBeforeColDisplayed(this, colIndex); this.onBeforeColDisplayed(this, colIndex);
} }
this._hideCells(tbl, colIndex, hide); this._hideElements(tbl, colIndex, hide);
if (this.headersTbl) { if (this.headersTbl) {
this._hideCells(this.headersTbl, colIndex, hide); this._hideElements(this.headersTbl, colIndex, hide);
} }
let hiddenCols = this.hiddenCols; let hiddenCols = this.hiddenCols;
@ -561,46 +569,11 @@ export default class ColsVisibility extends Feature {
} }
} }
let gridLayout;
let headTbl;
let gridColElms;
if (hide) { if (hide) {
//This event is fired just after a column is displayed for
//grid_layout support
//TODO: grid layout module should be responsible for those
//calculations
if (tf.gridLayout) {
gridLayout = tf.feature('gridLayout');
headTbl = gridLayout.headTbl;
gridColElms = gridLayout.colElms;
let hiddenWidth = parseInt(
gridColElms[colIndex].style.width, 10);
let headTblW = parseInt(headTbl.style.width, 10);
headTbl.style.width = headTblW - hiddenWidth + 'px';
tbl.style.width = headTbl.style.width;
}
this.onAfterColHidden(this, colIndex); this.onAfterColHidden(this, colIndex);
this.emitter.emit('column-hidden', tf, this, colIndex, this.emitter.emit('column-hidden', tf, this, colIndex,
this.hiddenCols); this.hiddenCols);
} } else {
if (!hide) {
//This event is fired just after a column is displayed for
//grid_layout support
//TODO: grid layout module should be responsible for those
//calculations
if (tf.gridLayout) {
gridLayout = tf.feature('gridLayout');
headTbl = gridLayout.headTbl;
gridColElms = gridLayout.colElms;
let width = parseInt(gridColElms[colIndex].style.width, 10);
headTbl.style.width =
(parseInt(headTbl.style.width, 10) + width) + 'px';
tf.tbl.style.width = headTbl.style.width;
}
this.onAfterColDisplayed(this, colIndex); this.onAfterColDisplayed(this, colIndex);
this.emitter.emit('column-shown', tf, this, colIndex, this.emitter.emit('column-shown', tf, this, colIndex,
this.hiddenCols); this.hiddenCols);
@ -612,7 +585,7 @@ export default class ColsVisibility extends Feature {
* @param {Number} colIndex Column index * @param {Number} colIndex Column index
*/ */
showCol(colIndex) { showCol(colIndex) {
if (colIndex === undefined || !this.isColHidden(colIndex)) { if (isUndef(colIndex) || !this.isColHidden(colIndex)) {
return; return;
} }
if (this.manager && this.contEl) { if (this.manager && this.contEl) {
@ -630,7 +603,7 @@ export default class ColsVisibility extends Feature {
* @param {Number} colIndex Column index * @param {Number} colIndex Column index
*/ */
hideCol(colIndex) { hideCol(colIndex) {
if (colIndex === undefined || this.isColHidden(colIndex)) { if (isUndef(colIndex) || this.isColHidden(colIndex)) {
return; return;
} }
if (this.manager && this.contEl) { if (this.manager && this.contEl) {
@ -659,7 +632,7 @@ export default class ColsVisibility extends Feature {
* @param {Number} colIndex Column index * @param {Number} colIndex Column index
*/ */
toggleCol(colIndex) { toggleCol(colIndex) {
if (colIndex === undefined || this.isColHidden(colIndex)) { if (isUndef(colIndex) || this.isColHidden(colIndex)) {
this.showCol(colIndex); this.showCol(colIndex);
} else { } else {
this.hideCol(colIndex); this.hideCol(colIndex);
@ -721,16 +694,29 @@ export default class ColsVisibility extends Feature {
return ''; return '';
} }
_hideCells(tbl, colIndex, hide) { _hideElements(tbl, colIdx, hide) {
this._hideCells(tbl, colIdx, hide);
this._hideCol(tbl, colIdx, hide);
}
_hideCells(tbl, colIdx, hide) {
for (let i = 0; i < tbl.rows.length; i++) { for (let i = 0; i < tbl.rows.length; i++) {
let row = tbl.rows[i]; let row = tbl.rows[i];
let cell = row.cells[colIndex]; let cell = row.cells[colIdx];
if (cell) { if (cell) {
cell.style.display = hide ? 'none' : ''; cell.style.display = hide ? NONE : '';
} }
} }
} }
_hideCol(tbl, colIdx, hide) {
let colElms = tag(tbl, 'col');
if (colElms.length === 0) {
return;
}
colElms[colIdx].style.display = hide ? NONE : '';
}
_hideAtStart() { _hideAtStart() {
this.atStart.forEach((colIdx) => { this.atStart.forEach((colIdx) => {
this.hideCol(colIdx); this.hideCol(colIdx);

View file

@ -1,7 +1,11 @@
import {Feature} from '../../feature'; import {Feature} from '../../feature';
import {createElm, removeElm, elm} from '../../dom'; import {createElm, removeElm, elm} from '../../dom';
import {isFn, isUndef, EMPTY_FN} from '../../types'; import {EMPTY_FN, isNull} from '../../types';
import {addEvt} from '../../event'; import {addEvt} from '../../event';
import {
defaultsBool, defaultsStr, defaultsFn, defaultsNb,
} from '../../settings';
import {RIGHT} from '../../modules/toolbar';
/** /**
* Filters Visibility extension * Filters Visibility extension
@ -14,7 +18,7 @@ export default class FiltersVisibility extends Feature {
* @param {Object} Configuration object * @param {Object} Configuration object
*/ */
constructor(tf, f) { constructor(tf, f) {
super(tf, f.name); super(tf, FiltersVisibility);
/** /**
* Module name * Module name
@ -26,25 +30,26 @@ export default class FiltersVisibility extends Feature {
* Module description * Module description
* @type {String} * @type {String}
*/ */
this.desc = f.description || 'Filters row visibility manager'; this.desc = defaultsStr(f.description,
'Filters row visibility manager');
/** /**
* Extension's stylesheet filename * Extension's stylesheet filename
* @type {String} * @type {String}
*/ */
this.stylesheet = f.stylesheet || 'filtersVisibility.css'; this.stylesheet = defaultsStr(f.stylesheet , 'filtersVisibility.css');
/** /**
* Expand icon filename * Expand icon filename
* @type {String} * @type {String}
*/ */
this.icnExpand = f.expand_icon_name || 'icn_exp.png'; this.icnExpand = defaultsStr(f.expand_icon_name, 'icn_exp.png');
/** /**
* Collapse icon filename * Collapse icon filename
* @type {String} * @type {String}
*/ */
this.icnCollapse = f.collapse_icon_name || 'icn_clp.png'; this.icnCollapse = defaultsStr(f.collapse_icon_name, 'icn_clp.png');
/** /**
* Main container element * Main container element
@ -88,13 +93,13 @@ export default class FiltersVisibility extends Feature {
* Enable expand/collapse icon, defaults to true * Enable expand/collapse icon, defaults to true
* @type {Boolean} * @type {Boolean}
*/ */
this.enableIcon = f.enable_icon === false ? false : true; this.enableIcon = defaultsBool(f.enable_icon, true);
/** /**
* Custom text for button * Custom text for button
* @type {String} * @type {String}
*/ */
this.btnText = f.btn_text || ''; this.btnText = defaultsStr(f.btn_text, '');
/** /**
* Collapse button HTML * Collapse button HTML
@ -116,62 +121,65 @@ export default class FiltersVisibility extends Feature {
* Button's custom HTML * Button's custom HTML
* @type {String} * @type {String}
*/ */
this.btnHtml = f.btn_html || null; this.btnHtml = defaultsStr(f.btn_html, null);
/** /**
* Css class for expand/collapse filters button * Css class for expand/collapse filters button
* @type {String} * @type {String}
*/ */
this.btnCssClass = f.btn_css_class || 'btnExpClpFlt'; this.btnCssClass = defaultsStr(f.btn_css_class, 'btnExpClpFlt');
/** /**
* Css class for main container * Css class for main container
* @type {String} * @type {String}
*/ */
this.contCssClass = f.cont_css_class || 'expClpFlt'; this.contCssClass = defaultsStr(f.cont_css_class, 'expClpFlt');
/** /**
* Filters row index * Filters row index
* @type {Number} * @type {Number}
*/ */
this.filtersRowIndex = !isUndef(f.filters_row_index) ? this.filtersRowIndex = defaultsNb(f.filters_row_index,
f.filters_row_index : tf.getFiltersRowIndex(); tf.getFiltersRowIndex());
/** /**
* Make filters visible at initialization, defaults to true * Make filters visible at initialization, defaults to true
* @type {Boolean} * @type {Boolean}
*/ */
this.visibleAtStart = !isUndef(f.visible_at_start) ? this.visibleAtStart = defaultsNb(f.visible_at_start, true);
Boolean(f.visible_at_start) : true;
/**
* Default position in toolbar ('left'|'center'|'right')
* @type {String}
*/
this.toolbarPosition = defaultsStr(f.toolbar_position, RIGHT);
/** /**
* Callback fired before filters row is shown * Callback fired before filters row is shown
* @type {Function} * @type {Function}
*/ */
this.onBeforeShow = isFn(f.on_before_show) ? this.onBeforeShow = defaultsFn(f.on_before_show, EMPTY_FN);
f.on_before_show : EMPTY_FN;
/** /**
* Callback fired after filters row is shown * Callback fired after filters row is shown
* @type {Function} * @type {Function}
*/ */
this.onAfterShow = isFn(f.on_after_show) ? f.on_after_show : EMPTY_FN; this.onAfterShow = defaultsFn(f.on_after_show, EMPTY_FN);
/** /**
* Callback fired before filters row is hidden * Callback fired before filters row is hidden
* @type {Function} * @type {Function}
*/ */
this.onBeforeHide = isFn(f.on_before_hide) ? this.onBeforeHide = defaultsFn(f.on_before_hide, EMPTY_FN);
f.on_before_hide : EMPTY_FN;
/** /**
* Callback fired after filters row is hidden * Callback fired after filters row is hidden
* @type {Function} * @type {Function}
*/ */
this.onAfterHide = isFn(f.on_after_hide) ? f.on_after_hide : EMPTY_FN; this.onAfterHide = defaultsFn(f.on_after_hide, EMPTY_FN);
//Import extension's stylesheet //Import extension's stylesheet
tf.import(f.name + 'Style', tf.stylePath + this.stylesheet, null, tf.import(f.name + 'Style', tf.getStylePath() + this.stylesheet, null,
'link'); 'link');
this.enable(); this.enable();
@ -185,15 +193,17 @@ export default class FiltersVisibility extends Feature {
return; return;
} }
this.emitter.emit('initializing-extension', this,
!isNull(this.targetId));
this.buildUI(); this.buildUI();
/** /** @inherited */
* @inherited
*/
this.initialized = true; this.initialized = true;
this.emitter.on(['show-filters'], (tf, visible) => this.show(visible)); this.emitter.on(['show-filters'], (tf, visible) => this.show(visible));
this.emitter.emit('filters-visibility-initialized', this.tf, this); this.emitter.emit('filters-visibility-initialized', this.tf, this);
this.emitter.emit('extension-initialized', this);
} }
/** /**
@ -204,11 +214,10 @@ export default class FiltersVisibility extends Feature {
let span = createElm('span'); let span = createElm('span');
span.className = this.contCssClass; span.className = this.contCssClass;
//Container element (rdiv or custom element) // Container element (rdiv or custom element)
if (!this.targetId) { let targetEl = !this.targetId ?
tf.setToolbar(); tf.feature('toolbar').container(this.toolbarPosition) :
} elm(this.targetId);
let targetEl = !this.targetId ? tf.rDiv : elm(this.targetId);
if (!this.targetId) { if (!this.targetId) {
let firstChild = targetEl.firstChild; let firstChild = targetEl.firstChild;
@ -224,7 +233,7 @@ export default class FiltersVisibility extends Feature {
btn.title = this.btnText || this.defaultText; btn.title = this.btnText || this.defaultText;
btn.innerHTML = this.collapseBtnHtml; btn.innerHTML = this.collapseBtnHtml;
span.appendChild(btn); span.appendChild(btn);
} else { //Custom html } else { // Custom html
span.innerHTML = this.btnHtml; span.innerHTML = this.btnHtml;
btn = span.firstChild; btn = span.firstChild;
} }
@ -244,7 +253,7 @@ export default class FiltersVisibility extends Feature {
*/ */
toggle() { toggle() {
let tf = this.tf; let tf = this.tf;
let tbl = tf.gridLayout ? tf.feature('gridLayout').headTbl : tf.tbl; let tbl = tf.gridLayout ? tf.feature('gridLayout').headTbl : tf.dom();
let fltRow = tbl.rows[this.filtersRowIndex]; let fltRow = tbl.rows[this.filtersRowIndex];
let isDisplayed = fltRow.style.display === ''; let isDisplayed = fltRow.style.display === '';
@ -258,7 +267,7 @@ export default class FiltersVisibility extends Feature {
*/ */
show(visible = true) { show(visible = true) {
let tf = this.tf; let tf = this.tf;
let tbl = tf.gridLayout ? tf.feature('gridLayout').headTbl : tf.tbl; let tbl = tf.gridLayout ? tf.feature('gridLayout').headTbl : tf.dom();
let fltRow = tbl.rows[this.filtersRowIndex]; let fltRow = tbl.rows[this.filtersRowIndex];
if (visible) { if (visible) {

View file

@ -1,12 +1,13 @@
import {Feature} from '../../feature'; import {Feature} from '../../feature';
import {isArray, isFn, isUndef, isObj, EMPTY_FN} from '../../types'; import {isUndef, isObj, EMPTY_FN} from '../../types';
import {createElm, elm, getText, tag} from '../../dom'; import {createElm, elm, tag} from '../../dom';
import {addEvt} from '../../event'; import {addEvt, bound} from '../../event';
import {parse as parseNb} from '../../number'; import {parse as parseNb} from '../../number';
import { import {
NONE, CELL_TAG, HEADER_TAG, STRING, NUMBER, DATE, FORMATTED_NUMBER, NONE, CELL_TAG, HEADER_TAG, STRING, NUMBER, DATE, FORMATTED_NUMBER,
IP_ADDRESS IP_ADDRESS
} from '../../const'; } from '../../const';
import {defaultsStr, defaultsFn, defaultsArr} from '../../settings';
/** /**
* SortableTable Adapter module * SortableTable Adapter module
@ -19,7 +20,7 @@ export default class AdapterSortableTable extends Feature {
* @param {Object} opts Configuration object * @param {Object} opts Configuration object
*/ */
constructor(tf, opts) { constructor(tf, opts) {
super(tf, opts.name); super(tf, AdapterSortableTable);
/** /**
* Module name * Module name
@ -31,7 +32,7 @@ export default class AdapterSortableTable extends Feature {
* Module description * Module description
* @type {String} * @type {String}
*/ */
this.desc = opts.description || 'Sortable table'; this.desc = defaultsStr(opts.description, 'Sortable table');
/** /**
* Indicate whether table previously sorted * Indicate whether table previously sorted
@ -44,15 +45,14 @@ export default class AdapterSortableTable extends Feature {
* List of sort type per column basis * List of sort type per column basis
* @type {Array} * @type {Array}
*/ */
this.sortTypes = isArray(opts.types) ? opts.types : tf.colTypes; this.sortTypes = defaultsArr(opts.types, tf.colTypes);
/** /**
* Column to be sorted at initialization, ie: * Column to be sorted at initialization, ie:
* sort_col_at_start: [1, true] * sort_col_at_start: [1, true]
* @type {Array} * @type {Array}
*/ */
this.sortColAtStart = isArray(opts.sort_col_at_start) ? this.sortColAtStart = defaultsArr(opts.sort_col_at_start, null);
opts.sort_col_at_start : null;
/** /**
* Enable asynchronous sort, if triggers are external * Enable asynchronous sort, if triggers are external
@ -64,7 +64,7 @@ export default class AdapterSortableTable extends Feature {
* List of element IDs triggering sort on a per column basis * List of element IDs triggering sort on a per column basis
* @type {Array} * @type {Array}
*/ */
this.triggerIds = isArray(opts.trigger_ids) ? opts.trigger_ids : []; this.triggerIds = defaultsArr(opts.trigger_ids, []);
// edit .sort-arrow.descending / .sort-arrow.ascending in // edit .sort-arrow.descending / .sort-arrow.ascending in
// tablefilter.css to reflect any path change // tablefilter.css to reflect any path change
@ -72,58 +72,57 @@ export default class AdapterSortableTable extends Feature {
* Path to images * Path to images
* @type {String} * @type {String}
*/ */
this.imgPath = opts.images_path || tf.themesPath; this.imgPath = defaultsStr(opts.images_path, tf.themesPath);
/** /**
* Blank image file name * Blank image file name
* @type {String} * @type {String}
*/ */
this.imgBlank = opts.image_blank || 'blank.png'; this.imgBlank = defaultsStr(opts.image_blank, 'blank.png');
/** /**
* Css class for sort indicator image * Css class for sort indicator image
* @type {String} * @type {String}
*/ */
this.imgClassName = opts.image_class_name || 'sort-arrow'; this.imgClassName = defaultsStr(opts.image_class_name, 'sort-arrow');
/** /**
* Css class for ascending sort indicator image * Css class for ascending sort indicator image
* @type {String} * @type {String}
*/ */
this.imgAscClassName = opts.image_asc_class_name || 'ascending'; this.imgAscClassName = defaultsStr(opts.image_asc_class_name,
'ascending');
/** /**
* Css class for descending sort indicator image * Css class for descending sort indicator image
* @type {String} * @type {String}
*/ */
this.imgDescClassName = opts.image_desc_class_name || 'descending'; this.imgDescClassName = defaultsStr(opts.image_desc_class_name,
'descending');
/** /**
* Cell attribute key storing custom value used for sorting * Cell attribute key storing custom value used for sorting
* @type {String} * @type {String}
*/ */
this.customKey = opts.custom_key || 'data-tf-sortKey'; this.customKey = defaultsStr(opts.custom_key, 'data-tf-sortKey');
/** /**
* Callback fired when sort extension is instanciated * Callback fired when sort extension is instanciated
* @type {Function} * @type {Function}
*/ */
this.onSortLoaded = isFn(opts.on_sort_loaded) ? this.onSortLoaded = defaultsFn(opts.on_sort_loaded, EMPTY_FN);
opts.on_sort_loaded : EMPTY_FN;
/** /**
* Callback fired before a table column is sorted * Callback fired before a table column is sorted
* @type {Function} * @type {Function}
*/ */
this.onBeforeSort = isFn(opts.on_before_sort) ? this.onBeforeSort = defaultsFn(opts.on_before_sort, EMPTY_FN);
opts.on_before_sort : EMPTY_FN;
/** /**
* Callback fired after a table column is sorted * Callback fired after a table column is sorted
* @type {Function} * @type {Function}
*/ */
this.onAfterSort = isFn(opts.on_after_sort) ? this.onAfterSort = defaultsFn(opts.on_after_sort, EMPTY_FN);
opts.on_after_sort : EMPTY_FN;
/** /**
* SortableTable instance * SortableTable instance
@ -190,8 +189,7 @@ export default class AdapterSortableTable extends Feature {
this.stt.sort(sortColAtStart[0], sortColAtStart[1]); this.stt.sort(sortColAtStart[0], sortColAtStart[1]);
} }
this.emitter.on(['sort'], this.emitter.on(['sort'], bound(this.sortByColumnIndexHandler, this));
(tf, colIdx, desc) => this.sortByColumnIndex(colIdx, desc));
/** @inherited */ /** @inherited */
this.initialized = true; this.initialized = true;
@ -208,6 +206,11 @@ export default class AdapterSortableTable extends Feature {
this.stt.sort(colIdx, desc); this.stt.sort(colIdx, desc);
} }
/** @private */
sortByColumnIndexHandler(tf, colIdx, desc) {
this.sortByColumnIndex(colIdx, desc);
}
/** /**
* Set SortableTable overrides for TableFilter integration * Set SortableTable overrides for TableFilter integration
*/ */
@ -358,17 +361,17 @@ export default class AdapterSortableTable extends Feature {
/** /**
* Overrides getInnerText in order to avoid Firefox unexpected sorting * Overrides getInnerText in order to avoid Firefox unexpected sorting
* behaviour with untrimmed text elements * behaviour with untrimmed text elements
* @param {Object} oNode DOM element * @param {Object} cell DOM element
* @return {String} DOM element inner text * @return {String} DOM element inner text
*/ */
SortableTable.getInnerText = function (oNode) { SortableTable.getInnerText = function (cell) {
if (!oNode) { if (!cell) {
return; return;
} }
if (oNode.getAttribute(adpt.customKey)) { if (cell.getAttribute(adpt.customKey)) {
return oNode.getAttribute(adpt.customKey); return cell.getAttribute(adpt.customKey);
} else { } else {
return getText(oNode); return tf.getCellValue(cell);
} }
}; };
} }
@ -378,8 +381,8 @@ export default class AdapterSortableTable extends Feature {
*/ */
addSortType(...args) { addSortType(...args) {
// Extract the arguments // Extract the arguments
let [id, caster, sorter] = args; let [id, caster, sorter, getRowValue] = args;
SortableTable.prototype.addSortType(id, caster, sorter); SortableTable.prototype.addSortType(id, caster, sorter, getRowValue);
} }
/** /**
@ -391,7 +394,7 @@ export default class AdapterSortableTable extends Feature {
sortTypes = this.sortTypes, sortTypes = this.sortTypes,
_sortTypes = []; _sortTypes = [];
for (let i = 0; i < tf.nbCells; i++) { tf.eachCol((i) => {
let colType; let colType;
if (sortTypes[i]) { if (sortTypes[i]) {
colType = sortTypes[i]; colType = sortTypes[i];
@ -421,7 +424,7 @@ export default class AdapterSortableTable extends Feature {
colType = STRING; colType = STRING;
} }
_sortTypes.push(colType); _sortTypes.push(colType);
} });
//Public TF method to add sort type //Public TF method to add sort type
@ -430,7 +433,7 @@ export default class AdapterSortableTable extends Feature {
this.addSortType(STRING); this.addSortType(STRING);
this.addSortType(IP_ADDRESS, ipAddress, sortIP); this.addSortType(IP_ADDRESS, ipAddress, sortIP);
this.stt = new SortableTable(tf.tbl, _sortTypes); this.stt = new SortableTable(tf.dom(), _sortTypes);
/*** external table headers adapter ***/ /*** external table headers adapter ***/
if (this.asyncSort && this.triggerIds.length > 0) { if (this.asyncSort && this.triggerIds.length > 0) {
@ -487,8 +490,7 @@ export default class AdapterSortableTable extends Feature {
return; return;
} }
let tf = this.tf; let tf = this.tf;
this.emitter.off(['sort'], this.emitter.off(['sort'], bound(this.sortByColumnIndexHandler, this));
(tf, colIdx, desc) => this.sortByColumnIndex(colIdx, desc));
this.sorted = false; this.sorted = false;
this.stt.destroy(); this.stt.destroy();
@ -506,9 +508,12 @@ export default class AdapterSortableTable extends Feature {
} }
AdapterSortableTable.meta = {altName: 'sort'};
//Converters //Converters
function ipAddress(value) { function ipAddress(value) {
let vals = value.split('.'); let vals = value.split('.');
// eslint-disable-next-line no-unused-vars
for (let x in vals) { for (let x in vals) {
let val = vals[x]; let val = vals[x];
while (3 > val.length) { while (3 > val.length) {

View file

@ -1,5 +1,6 @@
import {toCamelCase} from './string';
const NOTIMPLEMENTED = 'Not implemented.'; const NOT_IMPLEMENTED = 'Not implemented.';
/** /**
* Base class defining the interface of a TableFilter feature * Base class defining the interface of a TableFilter feature
@ -8,9 +9,11 @@ export class Feature {
/** /**
* Creates an instance of Feature * Creates an instance of Feature
* @param {Object} tf TableFilter instance * @param {Object} tf TableFilter instance
* @param {String} feature Feature name known by TableFilter * @param {Class} feature Feature class for TableFilter registration
*/ */
constructor(tf, feature) { constructor(tf, cls) {
cls.meta = cls.meta || {};
/** /**
* TableFilter instance * TableFilter instance
* @type {TableFilter} * @type {TableFilter}
@ -18,16 +21,18 @@ export class Feature {
this.tf = tf; this.tf = tf;
/** /**
* Feature name * Feature name is the camelised class name as per TableFilter's
* convention
* @type {String} * @type {String}
*/ */
this.feature = feature; this.feature = cls.meta.altName || cls.meta.name
|| toCamelCase(cls.name);
/** /**
* TableFilter feature setting * TableFilter feature setting
* @type {Boolean} * @type {Boolean}
*/ */
this.enabled = tf[feature]; this.enabled = tf[this.feature];
/** /**
* TableFilter configuration * TableFilter configuration
@ -55,7 +60,7 @@ export class Feature {
* Initialize the feature * Initialize the feature
*/ */
init() { init() {
throw new Error(NOTIMPLEMENTED); throw new Error(NOT_IMPLEMENTED);
} }
/** /**
@ -70,7 +75,7 @@ export class Feature {
* Destroy the feature * Destroy the feature
*/ */
destroy() { destroy() {
throw new Error(NOTIMPLEMENTED); throw new Error(NOT_IMPLEMENTED);
} }
/** /**
@ -92,6 +97,6 @@ export class Feature {
* @returns {Boolean} * @returns {Boolean}
*/ */
isEnabled() { isEnabled() {
return this.enabled; return this.enabled === true;
} }
} }

View file

@ -1,5 +1,7 @@
import {Feature} from '../feature'; import {Feature} from '../feature';
import {addClass, removeClass} from '../dom'; import {addClass, removeClass} from '../dom';
import {defaultsStr} from '../settings';
import {bound} from '../event';
/** /**
* Rows with alternating background color for improved readability * Rows with alternating background color for improved readability
@ -12,20 +14,21 @@ export class AlternateRows extends Feature {
* @param {Object} tf TableFilter instance * @param {Object} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'alternateRows'); super(tf, AlternateRows);
let config = this.config; let config = this.config;
/** /**
* Css class for even rows (default: 'even') * Css class for even rows (default: 'even')
* @type {String} * @type {String}
*/ */
this.evenCss = config.even_row_css_class || 'even'; this.evenCss = defaultsStr(config.even_row_css_class, 'even');
/** /**
* Css class for odd rows (default: 'odd') * Css class for odd rows (default: 'odd')
* @type {String} * @type {String}
*/ */
this.oddCss = config.odd_row_css_class || 'odd'; this.oddCss = defaultsStr(config.odd_row_css_class, 'odd');
} }
/** /**
@ -40,10 +43,9 @@ export class AlternateRows extends Feature {
// Subscribe to events // Subscribe to events
this.emitter.on(['row-processed', 'row-paged'], this.emitter.on(['row-processed', 'row-paged'],
(tf, rowIndex, arrIndex, isValid) => bound(this.processRowHandler, this));
this.processRow(rowIndex, arrIndex, isValid)); this.emitter.on(['column-sorted', 'rows-changed'],
this.emitter.on(['column-sorted'], () => this.processAll()); bound(this.processAll, this));
this.emitter.on(['rows-changed'], () => this.processAll());
/** @inherited */ /** @inherited */
this.initialized = true; this.initialized = true;
@ -94,7 +96,7 @@ export class AlternateRows extends Feature {
if (!this.isEnabled() || isNaN(rowIdx)) { if (!this.isEnabled() || isNaN(rowIdx)) {
return; return;
} }
let rows = this.tf.tbl.rows; let rows = this.tf.dom().rows;
let i = isNaN(idx) ? rowIdx : idx; let i = isNaN(idx) ? rowIdx : idx;
this.removeRowBg(rowIdx); this.removeRowBg(rowIdx);
@ -110,11 +112,16 @@ export class AlternateRows extends Feature {
if (isNaN(idx)) { if (isNaN(idx)) {
return; return;
} }
let rows = this.tf.tbl.rows; let rows = this.tf.dom().rows;
removeClass(rows[idx], this.oddCss); removeClass(rows[idx], this.oddCss);
removeClass(rows[idx], this.evenCss); removeClass(rows[idx], this.evenCss);
} }
/** @private */
processRowHandler(tf, rowIndex, arrIndex, isValid) {
this.processRow(rowIndex, arrIndex, isValid);
}
/** /**
* Removes all alternating backgrounds * Removes all alternating backgrounds
*/ */
@ -122,17 +129,15 @@ export class AlternateRows extends Feature {
if (!this.initialized) { if (!this.initialized) {
return; return;
} }
let nbRows = this.tf.getRowsNb(true);
for (let i = 0; i < nbRows; i++) { let eachRow = this.tf.eachRow(0);
this.removeRowBg(i); eachRow((row, i) => this.removeRowBg(i));
}
// Unsubscribe to events // Unsubscribe to events
this.emitter.off(['row-processed', 'row-paged'], this.emitter.off(['row-processed', 'row-paged'],
(tf, rowIndex, arrIndex, isValid) => bound(this.processRowHandler, this));
this.processRow(rowIndex, arrIndex, isValid)); this.emitter.off(['column-sorted', 'rows-changed'],
this.emitter.off(['column-sorted'], () => this.processAll()); bound(this.processAll, this));
this.emitter.off(['rows-changed'], () => this.processAll());
this.initialized = false; this.initialized = false;
} }

160
src/modules/baseDropdown.js Normal file
View file

@ -0,0 +1,160 @@
import {Feature} from '../feature';
import {
ignoreCase, numSortAsc, numSortDesc,
dateSortAsc, dateSortDesc, sortNumberStr, sortDateStr
} from '../sort';
import {isArray, isObj, isEmpty} from '../types';
import {NUMBER, FORMATTED_NUMBER, DATE} from '../const';
/**
* Base class for Dropdown and CheckList UI components
* @export
* @class BaseDropdown
* @extends {Feature}
*/
export class BaseDropdown extends Feature {
/**
* Creates an instance of BaseDropdown
* @param {TableFilter} tf
*/
constructor(tf, cls) {
super(tf, cls);
let f = this.config;
/**
* Filter options custom sorter on a column basis
* @type {Object}
*/
this.customSorter = isObj(f.filter_options_sorter) &&
isArray(f.filter_options_sorter.col) &&
isArray(f.filter_options_sorter.comparer) ?
f.filter_options_sorter :
null;
// TODO: move here all properties shared by Dropdown and CheckList
/**
* Has custom options
* @type {Boolean}
* @private
*/
this.isCustom = false;
/**
* List of options values
* @type {Array}
* @private
*/
this.opts = [];
/**
* List of options texts for custom values
* @type {Array}
* @private
*/
this.optsTxt = [];
/**
* List of options to be excluded from the checklist filter
* @type {Array}
* @private
*/
this.excludedOpts = [];
}
/**
* Sort passed options based on the type of the specified column
* @param {Number} colIndex Column index
* @param {Array} [options=[]] Collection of values
* @return {Array} Sorted values
* @private
*/
sortOptions(colIndex, options = []) {
let {tf} = this;
if (tf.isCustomOptions(colIndex) || !tf.sortSlc ||
(isArray(tf.sortSlc) && tf.sortSlc.indexOf(colIndex) === -1)) {
return options;
}
let { caseSensitive, sortFilterOptionsDesc } = tf;
let isSortDesc = sortFilterOptionsDesc.indexOf(colIndex) !== -1;
let compareFn;
if (this.customSorter &&
this.customSorter.col.indexOf(colIndex) !== -1) {
var idx = this.customSorter.col.indexOf(colIndex);
compareFn = this.customSorter.comparer[idx];
}
else if (tf.hasType(colIndex, [NUMBER, FORMATTED_NUMBER])) {
let decimal = tf.getDecimal(colIndex);
let comparer = isSortDesc ? numSortDesc : numSortAsc;
compareFn = sortNumberStr(comparer, decimal);
}
else if (tf.hasType(colIndex, [DATE])) {
let locale = tf.feature('dateType').getLocale(colIndex);
let comparer = isSortDesc ? dateSortDesc : dateSortAsc;
compareFn = sortDateStr(comparer, locale);
} else { // string
compareFn = caseSensitive ? undefined : ignoreCase;
if (isSortDesc) {
return options.sort(compareFn).reverse();
}
}
return options.sort(compareFn);
}
/**
* Regenerate filters of specified columns and maintain selection if any
* @param {Array} colIndexes Collection of column indexes
* @private
*/
refreshFilters(colIndexes) {
colIndexes.forEach((colIdx) => {
let values = this.getValues(colIdx);
this.build(colIdx, this.tf.linkedFilters);
this.selectOptions(colIdx, values);
});
}
/**
* Check passed row contains a valid linked value
* @param {Number} rowIdx Row index
* @param {Number} activeFilterIdx Current active filter index
* @returns {Boolean}
*/
isValidLinkedValue(rowIdx, activeFilterIdx) {
let tf = this.tf;
if (tf.disableExcludedOptions) {
return true;
}
if (tf.paging) {
if (!isEmpty(activeFilterIdx) && tf.isRowValid(rowIdx)) {
return true;
}
} else {
if (tf.isRowDisplayed(rowIdx)) {
return true;
}
}
return false;
}
/**
* Refresh linked filters to offer only selected options
*/
linkFilters() {
let tf = this.tf;
if (!tf.linkedFilters || !tf.activeFilterId) {
return;
}
this.refreshAll();
}
}

View file

@ -1,29 +1,28 @@
import {Feature} from '../feature'; import {BaseDropdown} from './baseDropdown';
import { import {
addClass, createCheckItem, createText, createElm, elm, getText, addClass, createCheckItem, createText, createElm, elm, removeClass, tag
removeClass, tag
} from '../dom'; } from '../dom';
import {has} from '../array'; import {has} from '../array';
import {matchCase, trim, rgxEsc} from '../string'; import {matchCase, trim, rgxEsc} from '../string';
import {ignoreCase, numSortAsc, numSortDesc} from '../sort';
import {addEvt, removeEvt, targetEvt} from '../event'; import {addEvt, removeEvt, targetEvt} from '../event';
import {isEmpty} from '../types'; import {isEmpty} from '../types';
import {CHECKLIST, NONE} from '../const'; import {CHECKLIST, NONE} from '../const';
import {defaultsStr, defaultsBool} from '../settings';
const SORT_ERROR = 'Filter options for column {0} cannot be sorted in ' +
'{1} manner.';
/** /**
* Checklist filter UI component * Checklist filter UI component
* @export
* @class CheckList
* @extends {BaseDropdown}
*/ */
export class CheckList extends Feature { export class CheckList extends BaseDropdown {
/** /**
* Creates an instance of CheckList * Creates an instance of CheckList
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'checkList'); super(tf, CheckList);
let f = this.config; let f = this.config;
@ -37,48 +36,57 @@ export class CheckList extends Feature {
* Css class for the container of the checklist filter (div) * Css class for the container of the checklist filter (div)
* @type {String} * @type {String}
*/ */
this.containerCssClass = f.div_checklist_css_class || 'div_checklist'; this.containerCssClass = defaultsStr(f.div_checklist_css_class,
'div_checklist');
/** /**
* Css class for the checklist filter element (ul) * Css class for the checklist filter element (ul)
* @type {String} * @type {String}
*/ */
this.filterCssClass = f.checklist_css_class || 'flt_checklist'; this.filterCssClass = defaultsStr(f.checklist_css_class,
'flt_checklist');
/** /**
* Css class for the item of a checklist (li) * Css class for the item of a checklist (li)
* @type {String} * @type {String}
*/ */
this.itemCssClass = f.checklist_item_css_class || 'flt_checklist_item'; this.itemCssClass = defaultsStr(f.checklist_item_css_class,
'flt_checklist_item');
/** /**
* Css class for a selected item of a checklist (li) * Css class for a selected item of a checklist (li)
* @type {String} * @type {String}
*/ */
this.selectedItemCssClass = this.selectedItemCssClass = defaultsStr(
f.checklist_selected_item_css_class || 'flt_checklist_slc_item'; f.checklist_selected_item_css_class,
'flt_checklist_slc_item'
);
/** /**
* Text placed in the filter's container when load filter on demand * Text placed in the filter's container when load filter on demand
* feature is enabled * feature is enabled
* @type {String} * @type {String}
*/ */
this.activateText = this.activateText = defaultsStr(
f.activate_checklist_text || 'Click to load filter data'; f.activate_checklist_text,
'Click to load filter data'
);
/** /**
* Css class for a disabled item of a checklist (li) * Css class for a disabled item of a checklist (li)
* @type {String} * @type {String}
*/ */
this.disabledItemCssClass = f.checklist_item_disabled_css_class || this.disabledItemCssClass = defaultsStr(
'flt_checklist_item_disabled'; f.checklist_item_disabled_css_class,
'flt_checklist_item_disabled'
);
/** /**
* Enable the reset filter option as first item * Enable the reset filter option as first item
* @type {Boolean} * @type {Boolean}
*/ */
this.enableResetOption = f.enable_checklist_reset_filter === false ? this.enableResetOption = defaultsBool(f.enable_checklist_reset_filter,
false : true; true);
/** /**
* Prefix for container element ID * Prefix for container element ID
@ -86,34 +94,6 @@ export class CheckList extends Feature {
* @private * @private
*/ */
this.prfx = 'chkdiv_'; this.prfx = 'chkdiv_';
/**
* Has custom options
* @type {Boolean}
* @private
*/
this.isCustom = false;
/**
* List of options values
* @type {Array}
* @private
*/
this.opts = [];
/**
* List of options texts for custom values
* @type {Array}
* @private
*/
this.optsTxt = [];
/**
* List of options to be excluded from the checklist filter
* @type {Array}
* @private
*/
this.excludedOpts = [];
} }
/** /**
@ -126,7 +106,7 @@ export class CheckList extends Feature {
let tf = this.tf; let tf = this.tf;
this.emitter.emit('filter-focus', tf, elm); this.emitter.emit('filter-focus', tf, elm);
this.setCheckListValues(elm); this.setItemOption(elm);
tf.filter(); tf.filter();
} }
@ -149,13 +129,8 @@ export class CheckList extends Feature {
* Refresh all checklist filters * Refresh all checklist filters
*/ */
refreshAll() { refreshAll() {
let tf = this.tf; let colIdxs = this.tf.getFiltersByType(CHECKLIST, true);
let fltsIdxs = tf.getFiltersByType(CHECKLIST, true); this.refreshFilters(colIdxs);
fltsIdxs.forEach((colIdx) => {
let values = this.getValues(colIdx);
this.build(colIdx, tf.linkedFilters);
this.selectOptions(colIdx, values);
});
} }
/** /**
@ -167,7 +142,7 @@ export class CheckList extends Feature {
init(colIndex, isExternal, container) { init(colIndex, isExternal, container) {
let tf = this.tf; let tf = this.tf;
let externalFltTgtId = isExternal ? let externalFltTgtId = isExternal ?
tf.externalFltTgtIds[colIndex] : null; tf.externalFltIds[colIndex] : null;
let divCont = createElm('div', let divCont = createElm('div',
['id', `${this.prfx}${colIndex}_${tf.id}`], ['id', `${this.prfx}${colIndex}_${tf.id}`],
@ -203,6 +178,8 @@ export class CheckList extends Feature {
this.emitter.on(['rows-changed'], () => this.refreshAll()); this.emitter.on(['rows-changed'], () => this.refreshAll());
this.emitter.on(['after-filtering'], () => this.linkFilters());
/** @inherited */ /** @inherited */
this.initialized = true; this.initialized = true;
} }
@ -214,11 +191,13 @@ export class CheckList extends Feature {
*/ */
build(colIndex, isLinked = false) { build(colIndex, isLinked = false) {
let tf = this.tf; let tf = this.tf;
colIndex = parseInt(colIndex, 10); colIndex = Number(colIndex);
this.emitter.emit('before-populating-filter', tf, colIndex); this.emitter.emit('before-populating-filter', tf, colIndex);
/** @inherited */
this.opts = []; this.opts = [];
/** @inherited */
this.optsTxt = []; this.optsTxt = [];
let flt = this.containers[colIndex]; let flt = this.containers[colIndex];
@ -227,71 +206,10 @@ export class CheckList extends Feature {
['colIndex', colIndex]); ['colIndex', colIndex]);
ul.className = this.filterCssClass; ul.className = this.filterCssClass;
let rows = tf.tbl.rows;
let nbRows = tf.getRowsNb(true);
let caseSensitive = tf.caseSensitive; let caseSensitive = tf.caseSensitive;
/** @inherited */
this.isCustom = tf.isCustomOptions(colIndex); this.isCustom = tf.isCustomOptions(colIndex);
let activeIdx;
let activeFilterId = tf.getActiveFilterId();
if (isLinked && activeFilterId) {
activeIdx = tf.getColumnIndexFromFilterId(activeFilterId);
}
let filteredDataCol = [];
if (isLinked && tf.disableExcludedOptions) {
this.excludedOpts = [];
}
flt.innerHTML = '';
for (let k = tf.refRow; k < nbRows; k++) {
// always visible rows don't need to appear on selects as always
// valid
if (tf.hasVisibleRows && tf.visibleRows.indexOf(k) !== -1) {
continue;
}
let cells = rows[k].cells;
let ncells = cells.length;
// checks if row has exact cell #
if (ncells !== tf.nbCells || this.isCustom) {
continue;
}
// this loop retrieves cell data
for (let j = 0; j < ncells; j++) {
if (colIndex !== j) {
continue;
}
if (isLinked && !tf.disableExcludedOptions &&
(!tf.paging && !tf.isRowDisplayed(k)) ||
(tf.paging && activeIdx && !tf.isRowValid(k))) {
continue;
}
let cellValue = tf.getCellValue(cells[j]);
//Vary Peter's patch
let cellString = matchCase(cellValue, caseSensitive);
// checks if celldata is already in array
if (!has(this.opts, cellString, caseSensitive)) {
this.opts.push(cellValue);
}
let filteredCol = filteredDataCol[j];
if (isLinked && tf.disableExcludedOptions) {
if (!filteredCol) {
filteredCol = tf.getFilteredDataCol(j);
}
if (!has(filteredCol, cellString, caseSensitive) &&
!has(this.excludedOpts, cellString,
caseSensitive)) {
this.excludedOpts.push(cellValue);
}
}
}
}
//Retrieves custom values //Retrieves custom values
if (this.isCustom) { if (this.isCustom) {
let customValues = tf.getCustomOptions(colIndex); let customValues = tf.getCustomOptions(colIndex);
@ -299,48 +217,64 @@ export class CheckList extends Feature {
this.optsTxt = customValues[1]; this.optsTxt = customValues[1];
} }
if (tf.sortSlc && !this.isCustom) { let activeIdx;
if (!caseSensitive) { let activeFilterId = tf.getActiveFilterId();
this.opts.sort(ignoreCase);
if (isLinked && activeFilterId) {
activeIdx = tf.getColumnIndexFromFilterId(activeFilterId);
}
let filteredDataCol = [];
if (isLinked && tf.disableExcludedOptions) {
/** @inherited */
this.excludedOpts = [];
}
flt.innerHTML = '';
let eachRow = tf.eachRow();
eachRow(
(row) => {
let cellValue = tf.getCellValue(row.cells[colIndex]);
//Vary Peter's patch
let cellString = matchCase(cellValue, caseSensitive);
// checks if celldata is already in array
if (!has(this.opts, cellString, caseSensitive)) {
this.opts.push(cellValue);
}
let filteredCol = filteredDataCol[colIndex];
if (isLinked && tf.disableExcludedOptions) {
if (!filteredCol) {
filteredCol = tf.getVisibleColumnValues(colIndex);
}
if (!has(filteredCol, cellString, caseSensitive) &&
!has(this.excludedOpts, cellString, caseSensitive)) {
this.excludedOpts.push(cellValue);
}
}
},
// continue conditions function
(row, k) => {
// excluded rows don't need to appear on selects as always valid
if (tf.excludeRows.indexOf(k) !== -1) {
return true;
}
// checks if row has expected number of cells
if (row.cells.length !== tf.nbCells || this.isCustom) {
return true;
}
if (isLinked && !this.isValidLinkedValue(k, activeIdx)) {
return true;
}
}
);
//sort options
this.opts = this.sortOptions(colIndex, this.opts);
if (this.excludedOpts) { if (this.excludedOpts) {
this.excludedOpts.sort(ignoreCase); this.excludedOpts = this.sortOptions(colIndex, this.excludedOpts);
}
} else {
this.opts.sort();
if (this.excludedOpts) {
this.excludedOpts.sort();
}
}
}
//asc sort
if (tf.sortNumAsc.indexOf(colIndex) !== -1) {
try {
this.opts.sort(numSortAsc);
if (this.excludedOpts) {
this.excludedOpts.sort(numSortAsc);
}
if (this.isCustom) {
this.optsTxt.sort(numSortAsc);
}
} catch (e) {
throw new Error(SORT_ERROR.replace('{0}', colIndex)
.replace('{1}', 'ascending'));
}//in case there are alphanumeric values
}
//desc sort
if (tf.sortNumDesc.indexOf(colIndex) !== -1) {
try {
this.opts.sort(numSortDesc);
if (this.excludedOpts) {
this.excludedOpts.sort(numSortDesc);
}
if (this.isCustom) {
this.optsTxt.sort(numSortDesc);
}
} catch (e) {
throw new Error(SORT_ERROR.replace('{0}', colIndex)
.replace('{1}', 'descending'));
}//in case there are alphanumeric values
} }
this.addChecks(colIndex, ul); this.addChecks(colIndex, ul);
@ -368,7 +302,9 @@ export class CheckList extends Feature {
let val = this.opts[y]; //item value let val = this.opts[y]; //item value
let lbl = this.isCustom ? this.optsTxt[y] : val; //item text let lbl = this.isCustom ? this.optsTxt[y] : val; //item text
let fltId = tf.fltIds[colIndex]; let fltId = tf.fltIds[colIndex];
let li = createCheckItem(`${fltId}_${(y + chkCt)}`, val, lbl); let lblIdx = y + chkCt;
let li = createCheckItem(`${fltId}_${lblIdx}`, val, lbl,
['data-idx', lblIdx]);
li.className = this.itemCssClass; li.className = this.itemCssClass;
if (tf.linkedFilters && tf.disableExcludedOptions && if (tf.linkedFilters && tf.disableExcludedOptions &&
@ -400,7 +336,7 @@ export class CheckList extends Feature {
let chkCt = 1; let chkCt = 1;
let fltId = tf.fltIds[colIndex]; let fltId = tf.fltIds[colIndex];
let li0 = createCheckItem(`${fltId}_0`, '', let li0 = createCheckItem(`${fltId}_0`, '',
tf.getClearFilterText(colIndex)); tf.getClearFilterText(colIndex), ['data-idx', 0]);
li0.className = this.itemCssClass; li0.className = this.itemCssClass;
ul.appendChild(li0); ul.appendChild(li0);
@ -412,7 +348,7 @@ export class CheckList extends Feature {
if (tf.enableEmptyOption) { if (tf.enableEmptyOption) {
let li1 = createCheckItem(`${fltId}_1`, tf.emOperator, let li1 = createCheckItem(`${fltId}_1`, tf.emOperator,
tf.emptyText); tf.emptyText, ['data-idx', 1]);
li1.className = this.itemCssClass; li1.className = this.itemCssClass;
ul.appendChild(li1); ul.appendChild(li1);
addEvt(li1.check, 'click', evt => this.optionClick(evt)); addEvt(li1.check, 'click', evt => this.optionClick(evt));
@ -421,7 +357,7 @@ export class CheckList extends Feature {
if (tf.enableNonEmptyOption) { if (tf.enableNonEmptyOption) {
let li2 = createCheckItem(`${fltId}_2`, tf.nmOperator, let li2 = createCheckItem(`${fltId}_2`, tf.nmOperator,
tf.nonEmptyText); tf.nonEmptyText, ['data-idx', 2]);
li2.className = this.itemCssClass; li2.className = this.itemCssClass;
ul.appendChild(li2); ul.appendChild(li2);
addEvt(li2.check, 'click', evt => this.optionClick(evt)); addEvt(li2.check, 'click', evt => this.optionClick(evt));
@ -431,83 +367,75 @@ export class CheckList extends Feature {
} }
/** /**
* Store checked options in DOM element attribute * Set/unset value of passed item option in filter's DOM element attribute
* @param {Object} o checklist option DOM element * @param {Object} o checklist option DOM element
* @private * @private
*/ */
setCheckListValues(o) { setItemOption(o) {
if (!o) { if (!o) {
return; return;
} }
let tf = this.tf; let tf = this.tf;
let chkValue = o.value; //checked item value let chkValue = o.value; //checked item value
// TODO: provide helper to extract column index, ugly! let chkIndex = o.dataset.idx;
let chkIndex = parseInt(o.id.split('_')[2], 10);
let colIdx = tf.getColumnIndexFromFilterId(o.id); let colIdx = tf.getColumnIndexFromFilterId(o.id);
let itemTag = 'LI';
let n = tf.getFilterElement(parseInt(colIdx, 10)); let n = tf.getFilterElement(parseInt(colIdx, 10));
let li = n.childNodes[chkIndex]; let items = n.childNodes;
let colIndex = n.getAttribute('colIndex'); let li = items[chkIndex];
let fltValue = n.getAttribute('value'); //filter value (ul tag) //selected values (ul tag)
let fltIndexes = n.getAttribute('indexes'); //selected items (ul tag) let slcValues = n.getAttribute('value') || '';
//selected items indexes (ul tag)
let slcIndexes = n.getAttribute('indexes') || '';
if (o.checked) { if (o.checked) {
//show all item //show all item
if (chkValue === '') { if (chkValue === '') {
if ((fltIndexes && fltIndexes !== '')) {
//items indexes //items indexes
let indSplit = fltIndexes.split(tf.separator); let indexes = slcIndexes.split(tf.separator);
//checked items loop indexes.forEach(idx => {
for (let u = 0; u < indSplit.length; u++) { idx = Number(idx);
//checked item let li = items[idx];
let cChk = elm(tf.fltIds[colIndex] + '_' + let chx = tag(li, 'input')[0];
indSplit[u]); if (chx && idx > 0) {
if (cChk) { chx.checked = false;
cChk.checked = false; removeClass(li, this.selectedItemCssClass);
removeClass(n.childNodes[indSplit[u]],
this.selectedItemCssClass);
}
}
} }
});
n.setAttribute('value', ''); n.setAttribute('value', '');
n.setAttribute('indexes', ''); n.setAttribute('indexes', '');
} else { } else {
fltValue = (fltValue) ? fltValue : ''; let indexes = slcIndexes + chkIndex + tf.separator;
chkValue = trim(fltValue + ' ' + chkValue + ' ' + let values =
tf.orOperator); trim(slcValues + ' ' + chkValue + ' ' + tf.orOperator);
chkIndex = fltIndexes + chkIndex + tf.separator;
n.setAttribute('value', chkValue); n.setAttribute('value', values);
n.setAttribute('indexes', chkIndex); n.setAttribute('indexes', indexes);
//1st option unchecked
if (elm(tf.fltIds[colIndex] + '_0')) { //uncheck first option
elm(tf.fltIds[colIndex] + '_0').checked = false; let chx0 = tag(items[0], 'input')[0];
if (chx0) {
chx0.checked = false;
} }
} }
if (li.nodeName === itemTag) { removeClass(items[0], this.selectedItemCssClass);
removeClass(n.childNodes[0], this.selectedItemCssClass);
addClass(li, this.selectedItemCssClass); addClass(li, this.selectedItemCssClass);
}
} else { //removes values and indexes } else { //removes values and indexes
if (chkValue !== '') { let replaceValue =
let replaceValue = new RegExp( new RegExp(rgxEsc(chkValue + ' ' + tf.orOperator));
rgxEsc(chkValue + ' ' + tf.orOperator)); let values = slcValues.replace(replaceValue, '');
fltValue = fltValue.replace(replaceValue, ''); let replaceIndex = new RegExp(rgxEsc(chkIndex + tf.separator));
n.setAttribute('value', trim(fltValue)); let indexes = slcIndexes.replace(replaceIndex, '');
n.setAttribute('value', trim(values));
n.setAttribute('indexes', indexes);
let replaceIndex = new RegExp(
rgxEsc(chkIndex + tf.separator));
fltIndexes = fltIndexes.replace(replaceIndex, '');
n.setAttribute('indexes', fltIndexes);
}
if (li.nodeName === itemTag) {
removeClass(li, this.selectedItemCssClass); removeClass(li, this.selectedItemCssClass);
} }
} }
}
/** /**
* Select filter options programmatically * Select filter options programmatically
@ -517,39 +445,36 @@ export class CheckList extends Feature {
selectOptions(colIndex, values = []) { selectOptions(colIndex, values = []) {
let tf = this.tf; let tf = this.tf;
let flt = tf.getFilterElement(colIndex); let flt = tf.getFilterElement(colIndex);
if (tf.getFilterType(colIndex) !== CHECKLIST || !flt || if (!flt || values.length === 0) {
values.length === 0) {
return; return;
} }
let lisNb = tag(flt, 'li').length; let lis = tag(flt, 'li');
flt.setAttribute('value', ''); flt.setAttribute('value', '');
flt.setAttribute('indexes', ''); flt.setAttribute('indexes', '');
for (let k = 0; k < lisNb; k++) { [].forEach.call(lis, (li) => {
let li = tag(flt, 'li')[k];
let lbl = tag(li, 'label')[0];
let chk = tag(li, 'input')[0]; let chk = tag(li, 'input')[0];
let lblTxt = matchCase(getText(lbl), tf.caseSensitive); let chkVal = matchCase(chk.value, tf.caseSensitive);
if (lblTxt !== '' && has(values, lblTxt, tf.caseSensitive)) { if (chkVal !== '' && has(values, chkVal, tf.caseSensitive)) {
chk.checked = true; chk.checked = true;
} else { } else {
// Check non-empty-text or empty-text option // Check non-empty-text or empty-text option
if (values.indexOf(tf.nmOperator) !== -1 && if (values.indexOf(tf.nmOperator) !== -1 &&
lblTxt === matchCase(tf.nonEmptyText, tf.caseSensitive)) { chkVal === matchCase(tf.nonEmptyText, tf.caseSensitive)) {
chk.checked = true; chk.checked = true;
} }
else if (values.indexOf(tf.emOperator) !== -1 && else if (values.indexOf(tf.emOperator) !== -1 &&
lblTxt === matchCase(tf.emptyText, tf.caseSensitive)) { chkVal === matchCase(tf.emptyText, tf.caseSensitive)) {
chk.checked = true; chk.checked = true;
} else { } else {
chk.checked = false; chk.checked = false;
} }
} }
this.setCheckListValues(chk); this.setItemOption(chk);
} });
} }
/** /**
@ -560,9 +485,12 @@ export class CheckList extends Feature {
getValues(colIndex) { getValues(colIndex) {
let tf = this.tf; let tf = this.tf;
let flt = tf.getFilterElement(colIndex); let flt = tf.getFilterElement(colIndex);
if (!flt) {
return [];
}
let fltAttr = flt.getAttribute('value'); let fltAttr = flt.getAttribute('value');
let values = isEmpty(fltAttr) ? '' : fltAttr; let values = isEmpty(fltAttr) ? '' : fltAttr;
//removes last operator || //removes last operator ||
values = values.substr(0, values.length - 3); values = values.substr(0, values.length - 3);
//turn || separated values into array //turn || separated values into array
@ -584,6 +512,7 @@ export class CheckList extends Feature {
(tf, colIndex, values) => this.selectOptions(colIndex, values) (tf, colIndex, values) => this.selectOptions(colIndex, values)
); );
this.emitter.off(['rows-changed'], () => this.refreshAll()); this.emitter.off(['rows-changed'], () => this.refreshAll());
this.emitter.off(['after-filtering'], () => this.linkFilters());
this.initialized = false; this.initialized = false;
} }

View file

@ -1,6 +1,9 @@
import {Feature} from '../feature'; import {Feature} from '../feature';
import {createElm, createText, elm, removeElm} from '../dom'; import {createElm, createText, elm, removeElm} from '../dom';
import {addEvt} from '../event'; import {addEvt} from '../event';
import {defaultsStr} from '../settings';
import {isNull} from '../types';
import {RIGHT} from './toolbar';
/** /**
* Clear button UI component * Clear button UI component
@ -12,15 +15,48 @@ export class ClearButton extends Feature {
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'btnReset'); super(tf, ClearButton);
let f = this.config; let f = this.config.btn_reset || {};
/** /**
* Container element ID * Container element ID
* @type {String} * @type {String}
*/ */
this.targetId = f.btn_reset_target_id || null; this.targetId = defaultsStr(f.target_id, null);
/**
* Text for the clear button
* @type {String}
*/
this.text = defaultsStr(f.text, null);
/**
* Css class for reset button
* @type {String}
*/
this.cssClass = defaultsStr(f.css_class, 'reset');
/**
* Tooltip text for the clear button
* @type {String}
*/
this.tooltip = f.tooltip || 'Clear filters';
/**
* Custom Html string for the clear button
* @type {String}
*/
this.html = defaultsStr(f.html,
(!tf.enableIcons || this.text ? null :
'<input type="button" value="" class="' + this.cssClass +
'" ' + 'title="' + this.tooltip + '" />'));
/**
* Default position in toolbar ('left'|'center'|'right')
* @type {String}
*/
this.toolbarPosition = defaultsStr(f.toolbar_position, RIGHT);
/** /**
* Clear button container element * Clear button container element
@ -35,33 +71,6 @@ export class ClearButton extends Feature {
* @private * @private
*/ */
this.element = null; this.element = null;
/**
* Text for the clear button
* @type {String}
*/
this.text = f.btn_reset_text || 'Reset';
/**
* Css class for reset button
* @type {String}
*/
this.cssClass = f.btn_reset_css_class || 'reset';
/**
* Tooltip text for the clear button
* @type {String}
*/
this.tooltip = f.btn_reset_tooltip || 'Clear filters';
/**
* Custom Html string for the clear button
* @type {String}
*/
this.html = f.btn_reset_html ||
(!tf.enableIcons ? null :
'<input type="button" value="" class="' + this.cssClass +
'" ' + 'title="' + this.tooltip + '" />');
} }
/** /**
@ -85,13 +94,13 @@ export class ClearButton extends Feature {
return; return;
} }
this.emitter.emit('initializing-feature', this, !isNull(this.targetId));
let cont = createElm('span'); let cont = createElm('span');
// reset button is added to defined element let targetEl = !this.targetId ?
if (!this.targetId) { tf.feature('toolbar').container(this.toolbarPosition) :
tf.setToolbar(); elm(this.targetId);
}
let targetEl = !this.targetId ? tf.rDiv : elm(this.targetId);
targetEl.appendChild(cont); targetEl.appendChild(cont);
if (!this.html) { if (!this.html) {
@ -110,6 +119,8 @@ export class ClearButton extends Feature {
/** @inherited */ /** @inherited */
this.initialized = true; this.initialized = true;
this.emitter.emit('feature-initialized', this);
} }
/** /**
@ -126,3 +137,6 @@ export class ClearButton extends Feature {
this.initialized = false; this.initialized = false;
} }
} }
// TODO: remove as soon as feature name is fixed
ClearButton.meta = {altName: 'btnReset'};

View file

@ -17,7 +17,7 @@ export class DateType extends Feature {
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'dateType'); super(tf, DateType);
/** /**
* Global locale * Global locale
@ -94,6 +94,16 @@ export class DateType extends Feature {
return isObj(colType) ? colType : {}; return isObj(colType) ? colType : {};
} }
/**
* Return the locale code for supplied column index as per configuration
* or global setting
* @param {Number} colIndex Column index
* @returns {String} Locale code (ie: 'en-us')
*/
getLocale(colIndex) {
return this.getOptions(colIndex).locale || this.locale;
}
/** /**
* Add date time format(s) to a locale as specified by the passed * Add date time format(s) to a locale as specified by the passed
* collection of column types, ie: * collection of column types, ie:

View file

@ -1,25 +1,25 @@
import {Feature} from '../feature'; import {BaseDropdown} from './baseDropdown';
import {createElm, createOpt, elm} from '../dom'; import {createElm, createOpt, elm} from '../dom';
import {has} from '../array'; import {has} from '../array';
import {matchCase} from '../string'; import {matchCase} from '../string';
import {ignoreCase, numSortAsc, numSortDesc} from '../sort';
import {addEvt, targetEvt} from '../event'; import {addEvt, targetEvt} from '../event';
import {SELECT, MULTIPLE, NONE} from '../const'; import {SELECT, MULTIPLE, NONE} from '../const';
import {defaultsStr, defaultsBool} from '../settings';
const SORT_ERROR = 'Filter options for column {0} cannot be sorted in ' +
'{1} manner.';
/** /**
* Dropdown filter UI component * Dropdown filter UI component
* @export
* @class Dropdown
* @extends {BaseDropdown}
*/ */
export class Dropdown extends Feature { export class Dropdown extends BaseDropdown {
/** /**
* Creates an instance of Dropdown * Creates an instance of Dropdown
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'dropdown'); super(tf, Dropdown);
// Configuration object // Configuration object
let f = this.config; let f = this.config;
@ -28,41 +28,21 @@ export class Dropdown extends Feature {
* Enable the reset filter option as first item * Enable the reset filter option as first item
* @type {Boolean} * @type {Boolean}
*/ */
this.enableSlcResetFilter = f.enable_slc_reset_filter === false ? this.enableSlcResetFilter =
false : true; defaultsBool(f.enable_slc_reset_filter, true);
/** /**
* Non empty option text * Non empty option text
* @type {String} * @type {String}
*/ */
this.nonEmptyText = f.non_empty_text || '(Non empty)'; this.nonEmptyText = defaultsStr(f.non_empty_text, '(Non empty)');
/** /**
* Tooltip text appearing on multiple select * Tooltip text appearing on multiple select
* @type {String} * @type {String}
*/ */
this.multipleSlcTooltip = f.multiple_slc_tooltip || this.multipleSlcTooltip = defaultsStr(f.multiple_slc_tooltip,
'Use Ctrl/Cmd key for multiple selections'; 'Use Ctrl/Cmd key for multiple selections');
/**
* Indicates drop-down has custom options
* @private
*/
this.isCustom = null;
/**
* List of options values
* @type {Array}
* @private
*/
this.opts = null;
/**
* List of options texts for custom values
* @type {Array}
* @private
*/
this.optsTxt = null;
} }
@ -96,15 +76,10 @@ export class Dropdown extends Feature {
* Refresh all drop-down filters * Refresh all drop-down filters
*/ */
refreshAll() { refreshAll() {
let tf = this.tf; let selectFlts = this.tf.getFiltersByType(SELECT, true);
let selectFlts = tf.getFiltersByType(SELECT, true); let multipleFlts = this.tf.getFiltersByType(MULTIPLE, true);
let multipleFlts = tf.getFiltersByType(MULTIPLE, true); let colIdxs = selectFlts.concat(multipleFlts);
let flts = selectFlts.concat(multipleFlts); this.refreshFilters(colIdxs);
flts.forEach((colIdx) => {
let values = this.getValues(colIdx);
this.build(colIdx, tf.linkedFilters);
this.selectOptions(colIdx, values);
});
} }
/** /**
@ -117,7 +92,7 @@ export class Dropdown extends Feature {
let tf = this.tf; let tf = this.tf;
let col = tf.getFilterType(colIndex); let col = tf.getFilterType(colIndex);
let externalFltTgtId = isExternal ? let externalFltTgtId = isExternal ?
tf.externalFltTgtIds[colIndex] : null; tf.externalFltIds[colIndex] : null;
let slc = createElm(SELECT, let slc = createElm(SELECT,
['id', tf.buildFilterId(colIndex)], ['id', tf.buildFilterId(colIndex)],
@ -162,6 +137,8 @@ export class Dropdown extends Feature {
); );
this.emitter.on(['rows-changed'], () => this.refreshAll()); this.emitter.on(['rows-changed'], () => this.refreshAll());
this.emitter.on(['after-filtering'], () => this.linkFilters());
/** @inherited */ /** @inherited */
this.initialized = true; this.initialized = true;
} }
@ -173,21 +150,28 @@ export class Dropdown extends Feature {
*/ */
build(colIndex, isLinked = false) { build(colIndex, isLinked = false) {
let tf = this.tf; let tf = this.tf;
colIndex = parseInt(colIndex, 10); colIndex = Number(colIndex);
this.emitter.emit('before-populating-filter', tf, colIndex); this.emitter.emit('before-populating-filter', tf, colIndex);
/** @inherited */
this.opts = []; this.opts = [];
/** @inherited */
this.optsTxt = []; this.optsTxt = [];
let slcId = tf.fltIds[colIndex]; let slc = tf.getFilterElement(colIndex);
let slc = elm(slcId);
let rows = tf.tbl.rows;
let nbRows = tf.getRowsNb(true);
//custom select test //custom select test
/** @inherited */
this.isCustom = tf.isCustomOptions(colIndex); this.isCustom = tf.isCustomOptions(colIndex);
//Retrieves custom values
if (this.isCustom) {
let customValues = tf.getCustomOptions(colIndex);
this.opts = customValues[0];
this.optsTxt = customValues[1];
}
//custom selects text //custom selects text
let activeIdx; let activeIdx;
let activeFilterId = tf.getActiveFilterId(); let activeFilterId = tf.getActiveFilterId();
@ -202,35 +186,12 @@ export class Dropdown extends Feature {
filteredDataCol = []; filteredDataCol = [];
} }
for (let k = tf.refRow; k < nbRows; k++) { let eachRow = tf.eachRow();
// always visible rows don't need to appear on selects as always eachRow(
// valid (row) => {
if (tf.hasVisibleRows && tf.visibleRows.indexOf(k) !== -1) { let cellValue = tf.getCellValue(row.cells[colIndex]);
continue;
}
let cell = rows[k].cells,
nchilds = cell.length;
// checks if row has exact cell #
if (nchilds !== tf.nbCells || this.isCustom) {
continue;
}
// this loop retrieves cell data
for (let j = 0; j < nchilds; j++) {
if (colIndex !== j) {
continue;
}
if (isLinked && !tf.disableExcludedOptions &&
(!tf.paging && !tf.isRowDisplayed(k)) ||
(tf.paging && activeIdx && !tf.isRowValid(k))) {
continue;
}
let cellValue = tf.getCellValue(cell[j]),
//Vary Peter's patch //Vary Peter's patch
cellString = matchCase(cellValue, tf.caseSensitive); let cellString = matchCase(cellValue, tf.caseSensitive);
// checks if celldata is already in array // checks if celldata is already in array
if (!has(this.opts, cellString, tf.caseSensitive)) { if (!has(this.opts, cellString, tf.caseSensitive)) {
@ -238,66 +199,38 @@ export class Dropdown extends Feature {
} }
if (isLinked && tf.disableExcludedOptions) { if (isLinked && tf.disableExcludedOptions) {
let filteredCol = filteredDataCol[j]; let filteredCol = filteredDataCol[colIndex];
if (!filteredCol) { if (!filteredCol) {
filteredCol = tf.getFilteredDataCol(j); filteredCol = tf.getVisibleColumnValues(colIndex);
} }
if (!has(filteredCol, cellString, tf.caseSensitive) && if (!has(filteredCol, cellString, tf.caseSensitive) &&
!has(excludedOpts, cellString, tf.caseSensitive)) { !has(excludedOpts, cellString, tf.caseSensitive)) {
excludedOpts.push(cellValue); excludedOpts.push(cellValue);
} }
} }
}//for j },
}//for k // continue conditions function
(row, k) => {
//Retrieves custom values // excluded rows don't need to appear on selects as always valid
if (this.isCustom) { if (tf.excludeRows.indexOf(k) !== -1) {
let customValues = tf.getCustomOptions(colIndex); return true;
this.opts = customValues[0];
this.optsTxt = customValues[1];
} }
if (tf.sortSlc && !this.isCustom) { // checks if row has expected number of cells
if (!tf.caseSensitive) { if (row.cells.length !== tf.nbCells || this.isCustom) {
this.opts.sort(ignoreCase); return true;
if (excludedOpts) {
excludedOpts.sort(ignoreCase);
}
} else {
this.opts.sort();
if (excludedOpts) { excludedOpts.sort(); }
}
} }
//asc sort if (isLinked && !this.isValidLinkedValue(k, activeIdx)) {
if (tf.sortNumAsc.indexOf(colIndex) !== -1) { return true;
try { }
this.opts.sort(numSortAsc); }
);
//sort options
this.opts = this.sortOptions(colIndex, this.opts);
if (excludedOpts) { if (excludedOpts) {
excludedOpts.sort(numSortAsc); excludedOpts = this.sortOptions(colIndex, excludedOpts);
}
if (this.isCustom) {
this.optsTxt.sort(numSortAsc);
}
} catch (e) {
throw new Error(SORT_ERROR.replace('{0}', colIndex)
.replace('{1}', 'ascending'));
}//in case there are alphanumeric values
}
//desc sort
if (tf.sortNumDesc.indexOf(colIndex) !== -1) {
try {
this.opts.sort(numSortDesc);
if (excludedOpts) {
excludedOpts.sort(numSortDesc);
}
if (this.isCustom) {
this.optsTxt.sort(numSortDesc);
}
} catch (e) {
throw new Error(SORT_ERROR.replace('{0}', colIndex)
.replace('{1}', 'ascending'));
}//in case there are alphanumeric values
} }
//populates drop-down //populates drop-down
@ -437,6 +370,7 @@ export class Dropdown extends Feature {
(tf, colIndex, values) => this.selectOptions(colIndex, values) (tf, colIndex, values) => this.selectOptions(colIndex, values)
); );
this.emitter.off(['rows-changed'], () => this.refreshAll()); this.emitter.off(['rows-changed'], () => this.refreshAll());
this.emitter.off(['after-filtering'], () => this.linkFilters());
this.initialized = false; this.initialized = false;
} }
} }

View file

@ -3,6 +3,9 @@ import {createElm, removeElm, elm, tag} from '../dom';
import {addEvt, targetEvt} from '../event'; import {addEvt, targetEvt} from '../event';
import {contains} from '../string'; import {contains} from '../string';
import {NONE} from '../const'; import {NONE} from '../const';
import {
defaultsBool, defaultsStr, defaultsNb, defaultsArr
} from '../settings';
/** /**
* Grid layout, table with fixed headers * Grid layout, table with fixed headers
@ -14,77 +17,76 @@ export class GridLayout extends Feature {
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'gridLayout'); super(tf, GridLayout);
let f = this.config; let f = this.config.grid_layout || {};
/** /**
* Grid-layout container width as CSS string * Grid-layout container width as CSS string
* @type {String} * @type {String}
*/ */
this.width = f.grid_width || null; this.width = defaultsStr(f.width, null);
/** /**
* Grid-layout container height as CSS string * Grid-layout container height as CSS string
* @type {String} * @type {String}
*/ */
this.height = f.grid_height || null; this.height = defaultsStr(f.height, null);
/** /**
* Css class for main container element * Css class for main container element
* @type {String} * @type {String}
*/ */
this.mainContCssClass = f.grid_cont_css_class || 'grd_Cont'; this.mainContCssClass = defaultsStr(f.cont_css_class, 'grd_Cont');
/** /**
* Css class for body table container element * Css class for body table container element
* @type {String} * @type {String}
*/ */
this.contCssClass = f.grid_tbl_cont_css_class || 'grd_tblCont'; this.contCssClass = defaultsStr(f.tbl_cont_css_class, 'grd_tblCont');
/** /**
* Css class for headers table container element * Css class for headers table container element
* @type {String} * @type {String}
*/ */
this.headContCssClass = f.grid_tblHead_cont_css_class || this.headContCssClass = defaultsStr(f.tbl_head_css_class,
'grd_headTblCont'; 'grd_headTblCont');
/** /**
* Css class for toolbar container element (rows counter, paging etc.) * Css class for toolbar container element (rows counter, paging etc.)
* @type {String} * @type {String}
*/ */
this.infDivCssClass = f.grid_inf_grid_css_class || 'grd_inf'; this.infDivCssClass = defaultsStr(f.inf_grid_css_class, 'grd_inf');
/** /**
* Index of the headers row, default: 0 * Index of the headers row, default: 0
* @type {Number} * @type {Number}
*/ */
this.headRowIndex = f.grid_headers_row_index || 0; this.headRowIndex = defaultsNb(f.headers_row_index, 0);
/** /**
* Collection of the header row indexes to be moved into headers table * Collection of the header row indexes to be moved into headers table
* @type {Array} * @type {Array}
*/ */
this.headRows = f.grid_headers_rows || [0]; this.headRows = defaultsArr(f.headers_rows, [0]);
/** /**
* Enable or disable column filters generation, default: true * Enable or disable column filters generation, default: true
* @type {Boolean} * @type {Boolean}
*/ */
this.enableFilters = f.grid_enable_default_filters === false ? this.filters = defaultsBool(f.filters, true);
false : true;
/** /**
* Enable or disable column headers, default: false * Enable or disable column headers, default: false
* @type {Boolean} * @type {Boolean}
*/ */
this.noHeaders = Boolean(f.grid_no_headers); this.noHeaders = Boolean(f.no_headers);
/** /**
* Grid-layout default column widht as CSS string * Grid-layout default column widht as CSS string
* @type {String} * @type {String}
*/ */
this.defaultColWidth = f.grid_default_col_width || '100px'; this.defaultColWidth = defaultsStr(f.default_col_width, '100px');
/** /**
* List of column elements * List of column elements
@ -112,14 +114,14 @@ export class GridLayout extends Feature {
* @type {String} * @type {String}
* @private * @private
*/ */
this.sourceTblHtml = tf.tbl.outerHTML; this.sourceTblHtml = tf.dom().outerHTML;
/** /**
* Indicates if working table has column elements * Indicates if working table has column elements
* @type {Boolean} * @type {Boolean}
* @private * @private
*/ */
this.tblHasColTag = tag(tf.tbl, 'col').length > 0 ? true : false; this.tblHasColTag = tag(tf.dom(), 'col').length > 0 ? true : false;
/** /**
* Main container element * Main container element
@ -146,7 +148,7 @@ export class GridLayout extends Feature {
this.headTbl = null; this.headTbl = null;
// filters flag at TF level // filters flag at TF level
tf.fltGrid = this.enableFilters; tf.fltGrid = this.filters;
} }
/** /**
@ -155,7 +157,7 @@ export class GridLayout extends Feature {
*/ */
init() { init() {
let tf = this.tf; let tf = this.tf;
let tbl = tf.tbl; let tbl = tf.dom();
if (this.initialized) { if (this.initialized) {
return; return;
@ -167,9 +169,6 @@ export class GridLayout extends Feature {
// Assign default column widths // Assign default column widths
this.setDefaultColWidths(); this.setDefaultColWidths();
// Initial table width
let tblW = this.initialTableWidth();
//Main container: it will contain all the elements //Main container: it will contain all the elements
this.tblMainCont = this.createContainer( this.tblMainCont = this.createContainer(
'div', this.mainContCssClass); 'div', this.mainContCssClass);
@ -190,6 +189,7 @@ export class GridLayout extends Feature {
//In case table width is expressed in % //In case table width is expressed in %
if (tbl.style.width === '') { if (tbl.style.width === '') {
let tblW = this.initialTableWidth();
tbl.style.width = (contains('%', tblW) ? tbl.style.width = (contains('%', tblW) ?
tbl.clientWidth : tblW) + 'px'; tbl.clientWidth : tblW) + 'px';
} }
@ -200,7 +200,6 @@ export class GridLayout extends Feature {
//Headers table container: div wrapping headers table //Headers table container: div wrapping headers table
this.headTblCont = this.createContainer( this.headTblCont = this.createContainer(
'div', this.headContCssClass); 'div', this.headContCssClass);
this.setConfigWidth(this.headTblCont);
//Headers table //Headers table
this.headTbl = createElm('table'); this.headTbl = createElm('table');
@ -233,22 +232,16 @@ export class GridLayout extends Feature {
tbl.removeChild(thead[0]); tbl.removeChild(thead[0]);
} }
//Headers table style // ensure table layout is always set even if already set in css
// definitions, potentially with custom css class this could be lost
this.headTbl.style.tableLayout = 'fixed'; this.headTbl.style.tableLayout = 'fixed';
tbl.style.tableLayout = 'fixed'; tbl.style.tableLayout = 'fixed';
this.headTbl.cellPadding = tbl.cellPadding;
this.headTbl.cellSpacing = tbl.cellSpacing;
// this.headTbl.style.width = tbl.style.width;
//content table without headers needs col widths to be reset //content table without headers needs col widths to be reset
tf.setColWidths(this.headTbl); tf.setColWidths(this.headTbl);
//Headers container width //Headers container width
// this.headTblCont.style.width = this.tblCont.clientWidth+'px'; this.headTbl.style.width = tbl.style.width;
tbl.style.width = '';
//
this.headTbl.style.width = tbl.clientWidth + 'px';
// //
//scroll synchronisation //scroll synchronisation
@ -288,10 +281,6 @@ export class GridLayout extends Feature {
filtersRow.style.display = NONE; filtersRow.style.display = NONE;
} }
if (tbl.clientWidth !== this.headTbl.clientWidth) {
tbl.style.width = this.headTbl.clientWidth + 'px';
}
/** @inherited */ /** @inherited */
this.initialized = true; this.initialized = true;
} }
@ -305,7 +294,6 @@ export class GridLayout extends Feature {
tf.refRow = 0; tf.refRow = 0;
tf.headersRow = 0; tf.headersRow = 0;
tf.filtersRowIndex = 1; tf.filtersRowIndex = 1;
tf.isExternalFlt = true;
} }
/** /**
@ -314,12 +302,13 @@ export class GridLayout extends Feature {
*/ */
setDefaultColWidths() { setDefaultColWidths() {
let tf = this.tf; let tf = this.tf;
if (tf.hasColWidths) { if (tf.colWidths.length > 0) {
return; return;
} }
for (let k = 0, len = tf.getCellsNb(); k < len; k++) {
tf.eachCol((k) => {
let colW; let colW;
let cell = tf.tbl.rows[tf.getHeadersRowIndex()].cells[k]; let cell = tf.dom().rows[tf.getHeadersRowIndex()].cells[k];
if (cell.width !== '') { if (cell.width !== '') {
colW = cell.width; colW = cell.width;
} else if (cell.style.width !== '') { } else if (cell.style.width !== '') {
@ -328,8 +317,8 @@ export class GridLayout extends Feature {
colW = this.defaultColWidth; colW = this.defaultColWidth;
} }
tf.colWidths[k] = colW; tf.colWidths[k] = colW;
} });
tf.hasColWidths = true;
tf.setColWidths(); tf.setColWidths();
} }
@ -339,7 +328,7 @@ export class GridLayout extends Feature {
* @private * @private
*/ */
initialTableWidth() { initialTableWidth() {
let tbl = this.tf.tbl; let tbl = this.tf.dom();
let width; //initial table width let width; //initial table width
if (tbl.width !== '') { if (tbl.width !== '') {
@ -374,14 +363,14 @@ export class GridLayout extends Feature {
createFiltersRow() { createFiltersRow() {
let tf = this.tf; let tf = this.tf;
let filtersRow = createElm('tr'); let filtersRow = createElm('tr');
if (this.enableFilters && tf.fltGrid) { if (this.filters && tf.fltGrid) {
tf.externalFltTgtIds = []; tf.externalFltIds = [];
for (let j = 0; j < tf.getCellsNb(); j++) { tf.eachCol((j) => {
let fltTdId = `${tf.prfxFlt + j + this.prfxGridFltTd + tf.id}`; let fltTdId = `${tf.prfxFlt + j + this.prfxGridFltTd + tf.id}`;
let cl = createElm(tf.fltCellTag, ['id', fltTdId]); let cl = createElm(tf.fltCellTag, ['id', fltTdId]);
filtersRow.appendChild(cl); filtersRow.appendChild(cl);
tf.externalFltTgtIds[j] = fltTdId; tf.externalFltIds[j] = fltTdId;
} });
} }
return filtersRow; return filtersRow;
} }
@ -392,15 +381,15 @@ export class GridLayout extends Feature {
*/ */
setColumnElements() { setColumnElements() {
let tf = this.tf; let tf = this.tf;
let cols = tag(tf.tbl, 'col'); let cols = tag(tf.dom(), 'col');
this.tblHasColTag = cols.length > 0; this.tblHasColTag = cols.length > 0;
for (let k = (tf.nbCells - 1); k >= 0; k--) { for (let k = (tf.getCellsNb() - 1); k >= 0; k--) {
let col; let col;
if (!this.tblHasColTag) { if (!this.tblHasColTag) {
col = createElm('col'); col = createElm('col');
tf.tbl.insertBefore(col, tf.tbl.firstChild); tf.dom().insertBefore(col, tf.dom().firstChild);
} else { } else {
col = cols[k]; col = cols[k];
} }
@ -423,7 +412,7 @@ export class GridLayout extends Feature {
} else { } else {
// Headers row are moved from content table to headers table // Headers row are moved from content table to headers table
for (let i = 0; i < this.headRows.length; i++) { for (let i = 0; i < this.headRows.length; i++) {
let row = this.tf.tbl.rows[this.headRows[i]]; let row = this.tf.dom().rows[this.headRows[i]];
tableHead.appendChild(row); tableHead.appendChild(row);
} }
} }
@ -454,7 +443,7 @@ export class GridLayout extends Feature {
getSortTriggerIds(row) { getSortTriggerIds(row) {
let tf = this.tf; let tf = this.tf;
let sortTriggers = []; let sortTriggers = [];
for (let n = 0; n < tf.getCellsNb(); n++) { tf.eachCol((n) => {
let c = row.cells[n]; let c = row.cells[n];
let thId = c.getAttribute('id'); let thId = c.getAttribute('id');
if (!thId || thId === '') { if (!thId || thId === '') {
@ -462,7 +451,7 @@ export class GridLayout extends Feature {
c.setAttribute('id', thId); c.setAttribute('id', thId);
} }
sortTriggers.push(thId); sortTriggers.push(thId);
} });
return sortTriggers; return sortTriggers;
} }
@ -471,7 +460,7 @@ export class GridLayout extends Feature {
*/ */
destroy() { destroy() {
let tf = this.tf; let tf = this.tf;
let tbl = tf.tbl; let tbl = tf.dom();
if (!this.initialized) { if (!this.initialized) {
return; return;

View file

@ -86,7 +86,7 @@ export class Hash {
} }
/** /**
* Converts a URL hash into a state JSON object * Converts a URL hash into a JSON object
* *
* @param {String} hash URL hash fragment * @param {String} hash URL hash fragment
* @returns {Object} JSON object * @returns {Object} JSON object

View file

@ -3,10 +3,13 @@ import {createElm, createText, elm, removeElm} from '../dom';
import {addEvt, targetEvt, removeEvt} from '../event'; import {addEvt, targetEvt, removeEvt} from '../event';
import {NONE} from '../const'; import {NONE} from '../const';
import {root} from '../root'; import {root} from '../root';
import {isEmpty, isNull} from '../types';
import {defaultsStr, defaultsNb} from '../settings';
import {RIGHT} from './toolbar';
const WIKI_URL = 'https://github.com/koalyptus/TableFilter/wiki/' + const WIKI_URL = 'https://github.com/koalyptus/TableFilter/wiki/' +
'4.-Filter-operators'; '4.-Filter-operators';
const WEBSITE_URL = 'http://koalyptus.github.io/TableFilter/'; const WEBSITE_URL = 'https://www.tablefilter.com/';
/** /**
* Help UI component * Help UI component
@ -18,29 +21,27 @@ export class Help extends Feature {
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'help'); super(tf, Help);
let f = this.config; let f = this.config.help_instructions || {};
/** /**
* ID of main custom container element * ID of main custom container element
* @type {String} * @type {String}
*/ */
this.tgtId = f.help_instructions_target_id || null; this.tgtId = defaultsStr(f.target_id, null);
/** /**
* ID of custom container element for instructions * ID of custom container element for instructions
* @type {String} * @type {String}
*/ */
this.contTgtId = f.help_instructions_container_target_id || this.contTgtId = defaultsStr(f.container_target_id, null);
null;
/** /**
* Instructions text (accepts HTML) * Instructions text (accepts HTML)
* @type {String} * @type {String}
*/ */
this.instrText = f.help_instructions_text ? this.instrText = !isEmpty(f.text) ? f.text :
f.help_instructions_text :
'Use the filters above each column to filter and limit table ' + 'Use the filters above each column to filter and limit table ' +
'data. Advanced searches can be performed by using the following ' + 'data. Advanced searches can be performed by using the following ' +
'operators: <br /><b>&lt;</b>, <b>&lt;=</b>, <b>&gt;</b>, ' + 'operators: <br /><b>&lt;</b>, <b>&lt;=</b>, <b>&gt;</b>, ' +
@ -53,32 +54,31 @@ export class Help extends Feature {
* Instructions HTML * Instructions HTML
* @type {String} * @type {String}
*/ */
this.instrHtml = f.help_instructions_html || null; this.instrHtml = defaultsStr(f.html, null);
/** /**
* Help button text ('?') * Help button text ('?')
* @type {String} * @type {String}
*/ */
this.btnText = f.help_instructions_btn_text || '?'; this.btnText = defaultsStr(f.btn_text, '?');
/** /**
* Custom help button HTML * Custom help button HTML
* @type {String} * @type {String}
*/ */
this.btnHtml = f.help_instructions_btn_html || null; this.btnHtml = defaultsStr(f.btn_html, null);
/** /**
* Css class for help button * Css class for help button
* @type {String} * @type {String}
*/ */
this.btnCssClass = f.help_instructions_btn_css_class || 'helpBtn'; this.btnCssClass = defaultsStr(f.btn_css_class, 'helpBtn');
/** /**
* Css class for help container element * Css class for help container element
* @type {String} * @type {String}
*/ */
this.contCssClass = f.help_instructions_container_css_class || this.contCssClass = defaultsStr(f.container_css_class, 'helpCont');
'helpCont';
/** /**
* Button DOM element * Button DOM element
@ -92,6 +92,15 @@ export class Help extends Feature {
*/ */
this.cont = null; this.cont = null;
/**
* Adjust container left position when table's horizontal scroll is
* on, typically when `responsive` option is enabled.
* @type {Number}
* @defaultValue 25
*/
this.contAdjustLeftPosition =
defaultsNb(f.container_adjust_left_position, 25);
/** /**
* Bound mouseup wrapper * Bound mouseup wrapper
* @private * @private
@ -109,6 +118,12 @@ export class Help extends Feature {
'<div align="center" style="margin-top:8px;">' + '<div align="center" style="margin-top:8px;">' +
'<a href="javascript:void(0);" class="close">Close</a></div></div>'; '<a href="javascript:void(0);" class="close">Close</a></div></div>';
/**
* Default position in toolbar ('left'|'center'|'right')
* @type {String}
*/
this.toolbarPosition = defaultsStr(f.toolbar_position, RIGHT);
this.emitter.on(['init-help'], () => this.init()); this.emitter.on(['init-help'], () => this.init());
} }
@ -138,6 +153,8 @@ export class Help extends Feature {
return; return;
} }
this.emitter.emit('initializing-feature', this, !isNull(this.tgtId));
let tf = this.tf; let tf = this.tf;
let btn = createElm('span'); let btn = createElm('span');
@ -146,10 +163,9 @@ export class Help extends Feature {
this.boundMouseup = this.onMouseup.bind(this); this.boundMouseup = this.onMouseup.bind(this);
//help button is added to defined element //help button is added to defined element
if (!this.tgtId) { let targetEl = !this.tgtId ?
tf.setToolbar(); tf.feature('toolbar').container(this.toolbarPosition) :
} elm(this.tgtId);
let targetEl = !this.tgtId ? tf.rDiv : elm(this.tgtId);
targetEl.appendChild(btn); targetEl.appendChild(btn);
let divContainer = !this.contTgtId ? btn : elm(this.contTgtId); let divContainer = !this.contTgtId ? btn : elm(this.contTgtId);
@ -187,15 +203,17 @@ export class Help extends Feature {
this.btn = btn; this.btn = btn;
/** @inherited */ /** @inherited */
this.initialized = true; this.initialized = true;
this.emitter.emit('feature-initialized', this);
} }
/** /**
* Toggle help pop-up * Toggle help pop-up
*/ */
toggle() { toggle() {
// check only if explicitily set to false as in this case undefined // check only if explicitily disabled as in this case undefined
// signifies the help feature is enabled by default // signifies the help feature is enabled by default
if (this.enabled === false) { if (!this.isEnabled()) {
return; return;
} }
@ -205,9 +223,21 @@ export class Help extends Feature {
let divDisplay = this.cont.style.display; let divDisplay = this.cont.style.display;
if (divDisplay === '' || divDisplay === NONE) { if (divDisplay === '' || divDisplay === NONE) {
this.cont.style.display = 'inline'; this.cont.style.display = 'inline';
// if table element has an horizontal scrollbar adjust container
// left position accordingly
if (this.tf.dom().scrollLeft > 0) {
this.cont.style.left = `${
this.btn.offsetLeft
- this.tf.dom().scrollLeft
+ this.contAdjustLeftPosition
}px`;
}
addEvt(root, 'mouseup', this.boundMouseup); addEvt(root, 'mouseup', this.boundMouseup);
} else { } else {
this.cont.style.display = NONE; this.cont.style.display = NONE;
this.cont.style.left = '';
} }
} }
@ -225,8 +255,10 @@ export class Help extends Feature {
this.cont = null; this.cont = null;
this.boundMouseup = null; this.boundMouseup = null;
this.initialized = false; this.initialized = false;
} }
} }
// TODO: remove as soon as feature name is fixed
Help.meta = {alwaysInstantiate: true};

View file

@ -1,6 +1,7 @@
import {createText, createElm, getText} from '../dom'; import {createText, createElm, getText} from '../dom';
import {isArray} from '../types'; import {isNull} from '../types';
import {rgxEsc} from '../string'; import {rgxEsc} from '../string';
import {defaultsStr} from '../settings';
/** /**
* Highlight matched keywords upon filtering * Highlight matched keywords upon filtering
@ -21,7 +22,7 @@ export class HighlightKeyword {
* Css class for highlighted term * Css class for highlighted term
* @type {String} * @type {String}
*/ */
this.highlightCssClass = f.highlight_css_class || 'keyword'; this.highlightCssClass = defaultsStr(f.highlight_css_class, 'keyword');
/** /**
* TableFilter instance * TableFilter instance
@ -99,12 +100,13 @@ export class HighlightKeyword {
* @param {String} cssClass Css class to remove * @param {String} cssClass Css class to remove
*/ */
unhighlight(term, cssClass) { unhighlight(term, cssClass) {
let highlightedNodes = this.tf.tbl.querySelectorAll(`.${cssClass}`); let highlightedNodes = this.tf.dom().querySelectorAll(`.${cssClass}`);
for (let i = 0; i < highlightedNodes.length; i++) { for (let i = 0; i < highlightedNodes.length; i++) {
let n = highlightedNodes[i]; let n = highlightedNodes[i];
let nodeVal = getText(n); let nodeVal = getText(n);
if (nodeVal.toLowerCase().indexOf(term.toLowerCase()) !== -1) { if (isNull(term) ||
nodeVal.toLowerCase().indexOf(term.toLowerCase()) !== -1) {
let parentNode = n.parentNode; let parentNode = n.parentNode;
parentNode.replaceChild(createText(nodeVal), n); parentNode.replaceChild(createText(nodeVal), n);
parentNode.normalize(); parentNode.normalize();
@ -119,15 +121,8 @@ export class HighlightKeyword {
if (!this.tf.highlightKeywords) { if (!this.tf.highlightKeywords) {
return; return;
} }
// iterate filters values to unhighlight all values
this.tf.getFiltersValue().forEach((val) => { this.unhighlight(null, this.highlightCssClass);
if (isArray(val)) {
val.forEach((item) =>
this.unhighlight(item, this.highlightCssClass));
} else {
this.unhighlight(val, this.highlightCssClass);
}
});
} }
/** Remove feature */ /** Remove feature */
@ -177,3 +172,9 @@ export class HighlightKeyword {
this.highlight(cell, term, this.highlightCssClass); this.highlight(cell, term, this.highlightCssClass);
} }
} }
// TODO: remove as soon as feature name is fixed
HighlightKeyword.meta = {
name: 'highlightKeyword',
altName: 'highlightKeywords'
};

View file

@ -1,10 +1,11 @@
import {Feature} from '../feature'; import {Feature} from '../feature';
import {createElm, createText, elm, removeElm} from '../dom'; import {createElm, createText, elm, removeElm} from '../dom';
import {isFn, EMPTY_FN} from '../types'; import {EMPTY_FN} from '../types';
import {root} from '../root'; import {root} from '../root';
import {NONE} from '../const'; import {NONE} from '../const';
import {defaultsStr, defaultsFn} from '../settings';
const EVENTS = [ const BEFORE_ACTION_EVENTS = [
'before-filtering', 'before-filtering',
'before-populating-filter', 'before-populating-filter',
'before-page-change', 'before-page-change',
@ -16,6 +17,18 @@ const EVENTS = [
'before-loading-themes' 'before-loading-themes'
]; ];
const AFTER_ACTION_EVENTS = [
'after-filtering',
'after-populating-filter',
'after-page-change',
'after-clearing-filters',
'after-page-length-change',
'after-reset-page',
'after-reset-page-length',
'after-loading-extensions',
'after-loading-themes'
];
/** /**
* Activity indicator * Activity indicator
* *
@ -31,15 +44,15 @@ export class Loader extends Feature {
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'loader'); super(tf, Loader);
let f = this.config; let f = this.config.loader || {};
/** /**
* ID of custom container element * ID of custom container element
* @type {String} * @type {String}
*/ */
this.targetId = f.loader_target_id || null; this.targetId = defaultsStr(f.target_id, null);
/** /**
* Loader container DOM element * Loader container DOM element
@ -51,19 +64,19 @@ export class Loader extends Feature {
* Text displayed when indicator is visible * Text displayed when indicator is visible
* @type {String} * @type {String}
*/ */
this.text = f.loader_text || 'Loading...'; this.text = defaultsStr(f.text, 'Loading...');
/** /**
* Custom HTML injected in Loader's container element * Custom HTML injected in Loader's container element
* @type {String} * @type {String}
*/ */
this.html = f.loader_html || null; this.html = defaultsStr(f.html, null);
/** /**
* Css class for Loader's container element * Css class for Loader's container element
* @type {String} * @type {String}
*/ */
this.cssClass = f.loader_css_class || 'loader'; this.cssClass = defaultsStr(f.css_class, 'loader');
/** /**
* Close delay in milliseconds * Close delay in milliseconds
@ -75,14 +88,13 @@ export class Loader extends Feature {
* Callback fired when loader is displayed * Callback fired when loader is displayed
* @type {Function} * @type {Function}
*/ */
this.onShow = isFn(f.on_show_loader) ? this.onShow = defaultsFn(f.on_show_loader, EMPTY_FN);
f.on_show_loader : EMPTY_FN;
/** /**
* Callback fired when loader is closed * Callback fired when loader is closed
* @type {Function} * @type {Function}
*/ */
this.onHide = isFn(f.on_hide_loader) ? f.on_hide_loader : EMPTY_FN; this.onHide = defaultsFn(f.on_hide_loader, EMPTY_FN);
} }
/** /**
@ -100,9 +112,9 @@ export class Loader extends Feature {
containerDiv.className = this.cssClass; containerDiv.className = this.cssClass;
let targetEl = !this.targetId ? let targetEl = !this.targetId ?
tf.tbl.parentNode : elm(this.targetId); tf.dom().parentNode : elm(this.targetId);
if (!this.targetId) { if (!this.targetId) {
targetEl.insertBefore(containerDiv, tf.tbl); targetEl.insertBefore(containerDiv, tf.dom());
} else { } else {
targetEl.appendChild(containerDiv); targetEl.appendChild(containerDiv);
} }
@ -116,12 +128,10 @@ export class Loader extends Feature {
this.show(NONE); this.show(NONE);
// Subscribe to events // Subscribe to events
emitter.on(EVENTS, () => this.show('')); emitter.on(BEFORE_ACTION_EVENTS, () => this.show(''));
emitter.on(EVENTS, () => this.show(NONE)); emitter.on(AFTER_ACTION_EVENTS, () => this.show(NONE));
/** /** @inherited */
* @inherited
*/
this.initialized = true; this.initialized = true;
} }
@ -134,7 +144,7 @@ export class Loader extends Feature {
return; return;
} }
let displayLoader = () => { function displayLoader() {
if (!this.cont) { if (!this.cont) {
return; return;
} }
@ -148,7 +158,7 @@ export class Loader extends Feature {
}; };
let t = p === NONE ? this.closeDelay : 1; let t = p === NONE ? this.closeDelay : 1;
root.setTimeout(displayLoader, t); root.setTimeout(displayLoader.bind(this), t);
} }
/** /**
@ -165,8 +175,8 @@ export class Loader extends Feature {
this.cont = null; this.cont = null;
// Unsubscribe to events // Unsubscribe to events
emitter.off(EVENTS, () => this.show('')); emitter.off(BEFORE_ACTION_EVENTS, () => this.show(''));
emitter.off(EVENTS, () => this.show(NONE)); emitter.off(AFTER_ACTION_EVENTS, () => this.show(NONE));
this.initialized = false; this.initialized = false;
} }

View file

@ -0,0 +1,146 @@
import {Feature} from '../feature';
import {addClass, removeClass, hasClass} from '../dom';
import {EMPTY_FN} from '../types';
import {defaultsStr, defaultsFn} from '../settings';
/**
* Visual indicator for filtered columns
* @export
* @class MarkActiveColumns
* @extends {Feature}
*/
export class MarkActiveColumns extends Feature {
/**
* Create an instance of MarkActiveColumns
* @param {TableFilter} tf TableFilter instance
*/
constructor(tf) {
super(tf, MarkActiveColumns);
let config = this.config.mark_active_columns || {};
/**
* Css class for filtered (active) columns
* @type {String}
*/
this.headerCssClass = defaultsStr(config.header_css_class,
'activeHeader');
/**
* Css class for filtered (active) column cells
* @type {String}
*/
this.cellCssClass = defaultsStr(config.cell_css_class,
'activeCell');
/**
* Enable/disable column highlighting
* @type {Boolean}
*/
this.highlightColumn = Boolean(config.highlight_column);
/**
* Callback fired before a column is marked as filtered
* @type {Function}
*/
this.onBeforeActiveColumn = defaultsFn(config.on_before_active_column,
EMPTY_FN);
/**
* Callback fired after a column is marked as filtered
* @type {Function}
*/
this.onAfterActiveColumn = defaultsFn(config.on_after_active_column,
EMPTY_FN);
}
/**
* Initialise MarkActiveColumns instance
*/
init() {
if (this.initialized) {
return;
}
this.emitter.on(['before-filtering'], () => this.clearActiveColumns());
this.emitter.on(
['cell-processed'],
(tf, colIndex) => this.markActiveColumn(colIndex)
);
/** @inherited */
this.initialized = true;
}
/**
* Clear filtered columns visual indicator (background color)
*/
clearActiveColumns() {
let tf = this.tf;
tf.eachCol((idx) => {
removeClass(tf.getHeaderElement(idx), this.headerCssClass);
if (this.highlightColumn) {
this.eachColumnCell(idx,
(cell) => removeClass(cell, this.cellCssClass));
}
});
}
/**
* Mark currently filtered column
* @param {Number} colIndex Column index
*/
markActiveColumn(colIndex) {
let tf = this.tf;
let header = tf.getHeaderElement(colIndex);
if (hasClass(header, this.headerCssClass)) {
return;
}
this.onBeforeActiveColumn(this, colIndex);
addClass(header, this.headerCssClass);
if (this.highlightColumn) {
this.eachColumnCell(colIndex,
(cell) => addClass(cell, this.cellCssClass));
}
this.onAfterActiveColumn(this, colIndex);
}
/**
* Column cells iterator
* TODO: make public and move into TableFilter if used elsewhere
* @param {Number} colIndex
* @param {Function} fn
* @param {DOMElement} tbl
* @private
*/
eachColumnCell(colIndex, fn = EMPTY_FN, tbl = this.tf.dom()) {
// TODO: remove [].forEach when polyfill for PhanthomJs is available
[].forEach.call(
tbl.querySelectorAll(`tbody td:nth-child(${colIndex + 1})`), fn);
}
/**
* Remove feature
*/
destroy() {
if (!this.initialized) {
return;
}
this.clearActiveColumns();
this.emitter.off(['before-filtering'], () => this.clearActiveColumns());
this.emitter.off(
['cell-processed'],
(tf, colIndex) => this.markActiveColumn(colIndex)
);
/** @inherited */
this.initialized = false;
}
}

View file

@ -1,7 +1,8 @@
import {Feature} from '../feature'; import {Feature} from '../feature';
import {createElm, elm, removeElm} from '../dom'; import {createElm, elm, removeElm} from '../dom';
import {isEmpty, isFn, EMPTY_FN} from '../types'; import {isEmpty, EMPTY_FN} from '../types';
import {NONE} from '../const'; import {NONE} from '../const';
import {defaultsStr, defaultsFn} from '../settings';
/** /**
* UI when filtering yields no matches * UI when filtering yields no matches
@ -16,28 +17,28 @@ export class NoResults extends Feature {
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'noResults'); super(tf, NoResults);
//configuration object //configuration object
let f = this.config.no_results_message; let f = this.config.no_results_message || {};
/** /**
* Text (accepts HTML) * Text (accepts HTML)
* @type {String} * @type {String}
*/ */
this.content = f.content || 'No results'; this.content = defaultsStr(f.content, 'No results');
/** /**
* Custom container DOM element * Custom container DOM element
* @type {DOMElement} * @type {DOMElement}
*/ */
this.customContainer = f.custom_container || null; this.customContainer = defaultsStr(f.custom_container, null);
/** /**
* ID of custom container element * ID of custom container element
* @type {String} * @type {String}
*/ */
this.customContainerId = f.custom_container_id || null; this.customContainerId = defaultsStr(f.custom_container_id, null);
/** /**
* Indicates if UI is contained in a external element * Indicates if UI is contained in a external element
@ -51,7 +52,7 @@ export class NoResults extends Feature {
* Css class assigned to container element * Css class assigned to container element
* @type {String} * @type {String}
*/ */
this.cssClass = f.css_class || 'no-results'; this.cssClass = defaultsStr(f.css_class, 'no-results');
/** /**
* Stores container DOM element * Stores container DOM element
@ -63,29 +64,25 @@ export class NoResults extends Feature {
* Callback fired before the message is displayed * Callback fired before the message is displayed
* @type {Function} * @type {Function}
*/ */
this.onBeforeShow = isFn(f.on_before_show_msg) ? this.onBeforeShow = defaultsFn(f.on_before_show_msg, EMPTY_FN);
f.on_before_show_msg : EMPTY_FN;
/** /**
* Callback fired after the message is displayed * Callback fired after the message is displayed
* @type {Function} * @type {Function}
*/ */
this.onAfterShow = isFn(f.on_after_show_msg) ? this.onAfterShow = defaultsFn(f.on_after_show_msg, EMPTY_FN);
f.on_after_show_msg : EMPTY_FN;
/** /**
* Callback fired before the message is hidden * Callback fired before the message is hidden
* @type {Function} * @type {Function}
*/ */
this.onBeforeHide = isFn(f.on_before_hide_msg) ? this.onBeforeHide = defaultsFn(f.on_before_hide_msg, EMPTY_FN);
f.on_before_hide_msg : EMPTY_FN;
/** /**
* Callback fired after the message is hidden * Callback fired after the message is hidden
* @type {Function} * @type {Function}
*/ */
this.onAfterHide = isFn(f.on_after_hide_msg) ? this.onAfterHide = defaultsFn(f.on_after_hide_msg, EMPTY_FN);
f.on_after_hide_msg : EMPTY_FN;
} }
/** /**
@ -97,7 +94,7 @@ export class NoResults extends Feature {
} }
let tf = this.tf; let tf = this.tf;
let target = this.customContainer || elm(this.customContainerId) || let target = this.customContainer || elm(this.customContainerId) ||
tf.tbl; tf.dom();
//container //container
let cont = createElm('div'); let cont = createElm('div');
@ -113,14 +110,13 @@ export class NoResults extends Feature {
this.cont = cont; this.cont = cont;
// subscribe to after-filtering event // subscribe to after-filtering event
this.emitter.on(['after-filtering'], () => this.toggle()); this.emitter.on(
['initialized', 'after-filtering'],
() => this.toggle()
);
/** /** @inherited */
* @inherited
*/
this.initialized = true; this.initialized = true;
this.hide();
} }
/** /**
@ -174,16 +170,15 @@ export class NoResults extends Feature {
let tf = this.tf; let tf = this.tf;
if (tf.gridLayout) { if (tf.gridLayout) {
let gridLayout = tf.feature('gridLayout'); let gridLayout = tf.feature('gridLayout');
this.cont.style.width = gridLayout.tblCont.clientWidth + 'px'; this.cont.style.width = gridLayout.headTbl.clientWidth + 'px';
} else { } else {
this.cont.style.width = (tf.tbl.tHead ? tf.tbl.tHead.clientWidth : this.cont.style.width = (tf.dom().tHead ?
tf.tbl.tBodies[0].clientWidth) + 'px'; tf.dom().tHead.clientWidth :
tf.dom().tBodies[0].clientWidth) + 'px';
} }
} }
/** /** Remove feature */
* Remove feature
*/
destroy() { destroy() {
if (!this.initialized) { if (!this.initialized) {
return; return;

View file

@ -1,8 +1,12 @@
import {Feature} from '../feature'; import {Feature} from '../feature';
import {createElm, createOpt, createText, elm, removeElm} from '../dom'; import {createElm, createOpt, createText, elm, removeElm} from '../dom';
import {isArray, isFn, isNull, EMPTY_FN} from '../types'; import {isArray, isNull, EMPTY_FN} from '../types';
import {addEvt, keyCode, removeEvt} from '../event'; import {addEvt, removeEvt, isKeyPressed, bound} from '../event';
import {INPUT, SELECT, NONE, ENTER_KEY} from '../const'; import {INPUT, SELECT, NONE, ENTER_KEY} from '../const';
import {
defaultsStr, defaultsNb, defaultsBool, defaultsArr, defaultsFn
} from '../settings';
import {CENTER, RIGHT} from './toolbar';
/** /**
* Paging UI component * Paging UI component
@ -17,65 +21,65 @@ export class Paging extends Feature {
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'paging'); super(tf, Paging);
// Configuration object // Configuration object
var f = this.config; let f = this.config.paging || {};
/** /**
* Css class for the paging buttons (previous, next, etc.) * Css class for the paging buttons (previous, next, etc.)
* @type {String} * @type {String}
*/ */
this.btnPageCssClass = f.paging_btn_css_class || 'pgInp'; this.btnCssClass = defaultsStr(f.btn_css_class, 'pgInp');
/** /**
* Main select DOM element * Main select DOM element
* @type {DOMElement} * @type {DOMElement}
*/ */
this.pagingSlc = null; this.pageSlc = null;
/** /**
* Results per page select DOM element * Results per page select DOM element
* @type {DOMElement} * @type {DOMElement}
*/ */
this.resultsPerPageSlc = null; this.pageLengthSlc = null;
/** /**
* ID of custom container element * ID of custom container element
* @type {String} * @type {String}
*/ */
this.pagingTgtId = f.paging_target_id || null; this.tgtId = defaultsStr(f.target_id, null);
/** /**
* Number of rows contained in a page * Number of rows contained in a page
* @type {Number} * @type {Number}
*/ */
this.pagingLength = !isNaN(f.paging_length) ? f.paging_length : 10; this.pageLength = defaultsNb(f.length, 10);
/** /**
* ID of custom container element for the results per page selector * ID of custom container element for the results per page selector
* @type {String} * @type {String}
*/ */
this.resultsPerPageTgtId = f.results_per_page_target_id || null; this.pageLengthTgtId = defaultsStr(f.results_per_page_target_id, null);
/** /**
* Css class for the paging select element * Css class for the paging select element
* @type {String} * @type {String}
*/ */
this.pgSlcCssClass = f.paging_slc_css_class || 'pgSlc'; this.pgSlcCssClass = defaultsStr(f.slc_css_class, 'pgSlc');
/** /**
* Css class for the paging input element * Css class for the paging input element
* @type {String} * @type {String}
*/ */
this.pgInpCssClass = f.paging_inp_css_class || 'pgNbInp'; this.pgInpCssClass = defaultsStr(f.inp_css_class, 'pgNbInp');
/** /**
* Label and values for the results per page select, example of usage: * Label and values for the results per page select, example of usage:
* ['Records: ', [10,25,50,100]] * ['Records: ', [10,25,50,100]]
* @type {Array} * @type {Array}
*/ */
this.resultsPerPage = f.results_per_page || null; this.resultsPerPage = defaultsArr(f.results_per_page, null);
/** /**
* Determines if results per page is configured * Determines if results per page is configured
@ -87,13 +91,14 @@ export class Paging extends Feature {
* Css class for the results per page select * Css class for the results per page select
* @type {String} * @type {String}
*/ */
this.resultsSlcCssClass = f.results_slc_css_class || 'rspg'; this.resultsSlcCssClass = defaultsStr(f.results_slc_css_class, 'rspg');
/** /**
* Css class for the label preceding results per page select * Css class for the label preceding results per page select
* @type {String} * @type {String}
*/ */
this.resultsSpanCssClass = f.results_span_css_class || 'rspgSpan'; this.resultsSpanCssClass = defaultsStr(f.results_span_css_class,
'rspgSpan');
/** /**
* Index of the first row of current page * Index of the first row of current page
@ -120,105 +125,109 @@ export class Paging extends Feature {
* Next page button text * Next page button text
* @type {String} * @type {String}
*/ */
this.btnNextPageText = f.btn_next_page_text || '>'; this.btnNextPageText = defaultsStr(f.btn_next_page_text, '>');
/** /**
* Previous page button text * Previous page button text
* @type {String} * @type {String}
*/ */
this.btnPrevPageText = f.btn_prev_page_text || '<'; this.btnPrevPageText = defaultsStr(f.btn_prev_page_text, '<');
/** /**
* Last page button text * Last page button text
* @type {String} * @type {String}
*/ */
this.btnLastPageText = f.btn_last_page_text || '>|'; this.btnLastPageText = defaultsStr(f.btn_last_page_text, '>|');
/** /**
* First page button text * First page button text
* @type {String} * @type {String}
*/ */
this.btnFirstPageText = f.btn_first_page_text || '|<'; this.btnFirstPageText = defaultsStr(f.btn_first_page_text, '|<');
/** /**
* Next page button HTML * Next page button HTML
* @type {String} * @type {String}
*/ */
this.btnNextPageHtml = f.btn_next_page_html || this.btnNextPageHtml = defaultsStr(f.btn_next_page_html,
(!tf.enableIcons ? null : (!tf.enableIcons ? null :
'<input type="button" value="" class="' + this.btnPageCssClass + '<input type="button" value="" class="' + this.btnCssClass +
' nextPage" title="Next page" />'); ' nextPage" title="Next page" />'));
/** /**
* Previous page button HTML * Previous page button HTML
* @type {String} * @type {String}
*/ */
this.btnPrevPageHtml = f.btn_prev_page_html || this.btnPrevPageHtml = defaultsStr(f.btn_prev_page_html,
(!tf.enableIcons ? null : (!tf.enableIcons ? null :
'<input type="button" value="" class="' + this.btnPageCssClass + '<input type="button" value="" class="' + this.btnCssClass +
' previousPage" title="Previous page" />'); ' previousPage" title="Previous page" />'));
/** /**
* First page button HTML * First page button HTML
* @type {String} * @type {String}
*/ */
this.btnFirstPageHtml = f.btn_first_page_html || this.btnFirstPageHtml = defaultsStr(f.btn_first_page_html,
(!tf.enableIcons ? null : (!tf.enableIcons ? null :
'<input type="button" value="" class="' + this.btnPageCssClass + '<input type="button" value="" class="' + this.btnCssClass +
' firstPage" title="First page" />'); ' firstPage" title="First page" />'));
/** /**
* Last page button HTML * Last page button HTML
* @type {String} * @type {String}
*/ */
this.btnLastPageHtml = f.btn_last_page_html || this.btnLastPageHtml = defaultsStr(f.btn_last_page_html,
(!tf.enableIcons ? null : (!tf.enableIcons ? null :
'<input type="button" value="" class="' + this.btnPageCssClass + '<input type="button" value="" class="' + this.btnCssClass +
' lastPage" title="Last page" />'); ' lastPage" title="Last page" />'));
/** /**
* Text preceeding page selector drop-down * Text preceeding page selector drop-down
* @type {String} * @type {String}
*/ */
this.pageText = f.page_text || ' Page '; this.pageText = defaultsStr(f.page_text, ' Page ');
/** /**
* Text after page selector drop-down * Text after page selector drop-down
* @type {String} * @type {String}
*/ */
this.ofText = f.of_text || ' of '; this.ofText = defaultsStr(f.of_text, ' of ');
/** /**
* Css class for the span containing total number of pages * Css class for the span containing total number of pages
* @type {String} * @type {String}
*/ */
this.nbPgSpanCssClass = f.nb_pages_css_class || 'nbpg'; this.nbPgSpanCssClass = defaultsStr(f.nb_pages_css_class, 'nbpg');
/** /**
* Determines if paging buttons are enabled (default: true) * Determines if paging buttons are enabled (default: true)
* @type {Boolean} * @type {Boolean}
*/ */
this.hasPagingBtns = f.paging_btns === false ? false : true; this.hasBtns = defaultsBool(f.btns, true);
/** /**
* Defines page selector type, two possible values: 'select', 'input' * Defines page selector type, two possible values: 'select', 'input'
* @type {String} * @type {String}
*/ */
this.pageSelectorType = f.page_selector_type || SELECT; this.pageSelectorType = defaultsStr(f.page_selector_type, SELECT);
/**
* Default position in toolbar ('left'|'center'|'right')
* @type {String}
*/
this.toolbarPosition = defaultsStr(f.toolbar_position, CENTER);
/** /**
* Callback fired before the page is changed * Callback fired before the page is changed
* @type {Function} * @type {Function}
*/ */
this.onBeforeChangePage = isFn(f.on_before_change_page) ? this.onBeforeChangePage = defaultsFn(f.on_before_change_page, EMPTY_FN);
f.on_before_change_page : EMPTY_FN;
/** /**
* Callback fired after the page is changed * Callback fired after the page is changed
* @type {Function} * @type {Function}
*/ */
this.onAfterChangePage = isFn(f.on_after_change_page) ? this.onAfterChangePage = defaultsFn(f.on_after_change_page, EMPTY_FN);
f.on_after_change_page : EMPTY_FN;
/** /**
* Label preciding results per page select * Label preciding results per page select
@ -269,12 +278,12 @@ export class Paging extends Feature {
*/ */
this.pgAfter = null; this.pgAfter = null;
var start_row = tf.refRow; let startRow = tf.refRow;
var nrows = tf.getRowsNb(true); let nrows = tf.getRowsNb(true);
//calculates page nb //calculates page nb
this.nbPages = Math.ceil((nrows - start_row) / this.pagingLength); this.nbPages = Math.ceil((nrows - startRow) / this.pageLength);
var o = this; let o = this;
/** /**
* Paging DOM events handlers * Paging DOM events handlers
* @type {String} * @type {String}
@ -283,21 +292,21 @@ export class Paging extends Feature {
this.evt = { this.evt = {
slcIndex() { slcIndex() {
return (o.pageSelectorType === SELECT) ? return (o.pageSelectorType === SELECT) ?
o.pagingSlc.options.selectedIndex : o.pageSlc.options.selectedIndex :
parseInt(o.pagingSlc.value, 10) - 1; parseInt(o.pageSlc.value, 10) - 1;
}, },
nbOpts() { nbOpts() {
return (o.pageSelectorType === SELECT) ? return (o.pageSelectorType === SELECT) ?
parseInt(o.pagingSlc.options.length, 10) - 1 : parseInt(o.pageSlc.options.length, 10) - 1 :
(o.nbPages - 1); (o.nbPages - 1);
}, },
next() { next() {
var nextIndex = o.evt.slcIndex() < o.evt.nbOpts() ? let nextIndex = o.evt.slcIndex() < o.evt.nbOpts() ?
o.evt.slcIndex() + 1 : 0; o.evt.slcIndex() + 1 : 0;
o.changePage(nextIndex); o.changePage(nextIndex);
}, },
prev() { prev() {
var prevIndex = o.evt.slcIndex() > 0 ? let prevIndex = o.evt.slcIndex() > 0 ?
o.evt.slcIndex() - 1 : o.evt.nbOpts(); o.evt.slcIndex() - 1 : o.evt.nbOpts();
o.changePage(prevIndex); o.changePage(prevIndex);
}, },
@ -308,8 +317,7 @@ export class Paging extends Feature {
o.changePage(0); o.changePage(0);
}, },
_detectKey(e) { _detectKey(e) {
var key = keyCode(e); if (isKeyPressed(e, [ENTER_KEY])) {
if (key === ENTER_KEY) {
if (tf.sorted) { if (tf.sorted) {
tf.filter(); tf.filter();
o.changePage(o.evt.slcIndex()); o.changePage(o.evt.slcIndex());
@ -331,27 +339,29 @@ export class Paging extends Feature {
* Initialize DOM elements * Initialize DOM elements
*/ */
init() { init() {
var slcPages; let slcPages;
var tf = this.tf; let tf = this.tf;
var evt = this.evt; let evt = this.evt;
if (this.initialized) { if (this.initialized) {
return; return;
} }
this.emitter.emit('initializing-feature', this, !isNull(this.tgtId));
// Check resultsPerPage is in expected format and initialise the // Check resultsPerPage is in expected format and initialise the
// results per page component // results per page component
if (this.hasResultsPerPage) { if (this.hasResultsPerPage) {
if (this.resultsPerPage.length < 2) { if (this.resultsPerPage.length < 2) {
this.hasResultsPerPage = false; this.hasResultsPerPage = false;
} else { } else {
this.pagingLength = this.resultsPerPage[1][0]; this.pageLength = this.resultsPerPage[1][0];
this.setResultsPerPage(); this.setResultsPerPage();
} }
} }
evt.slcPagesChange = (event) => { evt.slcPagesChange = (event) => {
var slc = event.target; let slc = event.target;
this.changePage(slc.selectedIndex); this.changePage(slc.selectedIndex);
}; };
@ -370,20 +380,20 @@ export class Paging extends Feature {
} }
// btns containers // btns containers
var btnNextSpan = createElm('span'); let btnNextSpan = createElm('span');
var btnPrevSpan = createElm('span'); let btnPrevSpan = createElm('span');
var btnLastSpan = createElm('span'); let btnLastSpan = createElm('span');
var btnFirstSpan = createElm('span'); let btnFirstSpan = createElm('span');
if (this.hasPagingBtns) { if (this.hasBtns) {
// Next button // Next button
if (!this.btnNextPageHtml) { if (!this.btnNextPageHtml) {
var btnNext = createElm(INPUT, let btnNext = createElm(INPUT,
['type', 'button'], ['type', 'button'],
['value', this.btnNextPageText], ['value', this.btnNextPageText],
['title', 'Next'] ['title', 'Next']
); );
btnNext.className = this.btnPageCssClass; btnNext.className = this.btnCssClass;
addEvt(btnNext, 'click', evt.next); addEvt(btnNext, 'click', evt.next);
btnNextSpan.appendChild(btnNext); btnNextSpan.appendChild(btnNext);
} else { } else {
@ -392,12 +402,12 @@ export class Paging extends Feature {
} }
// Previous button // Previous button
if (!this.btnPrevPageHtml) { if (!this.btnPrevPageHtml) {
var btnPrev = createElm(INPUT, let btnPrev = createElm(INPUT,
['type', 'button'], ['type', 'button'],
['value', this.btnPrevPageText], ['value', this.btnPrevPageText],
['title', 'Previous'] ['title', 'Previous']
); );
btnPrev.className = this.btnPageCssClass; btnPrev.className = this.btnCssClass;
addEvt(btnPrev, 'click', evt.prev); addEvt(btnPrev, 'click', evt.prev);
btnPrevSpan.appendChild(btnPrev); btnPrevSpan.appendChild(btnPrev);
} else { } else {
@ -406,12 +416,12 @@ export class Paging extends Feature {
} }
// Last button // Last button
if (!this.btnLastPageHtml) { if (!this.btnLastPageHtml) {
var btnLast = createElm(INPUT, let btnLast = createElm(INPUT,
['type', 'button'], ['type', 'button'],
['value', this.btnLastPageText], ['value', this.btnLastPageText],
['title', 'Last'] ['title', 'Last']
); );
btnLast.className = this.btnPageCssClass; btnLast.className = this.btnCssClass;
addEvt(btnLast, 'click', evt.last); addEvt(btnLast, 'click', evt.last);
btnLastSpan.appendChild(btnLast); btnLastSpan.appendChild(btnLast);
} else { } else {
@ -420,12 +430,12 @@ export class Paging extends Feature {
} }
// First button // First button
if (!this.btnFirstPageHtml) { if (!this.btnFirstPageHtml) {
var btnFirst = createElm(INPUT, let btnFirst = createElm(INPUT,
['type', 'button'], ['type', 'button'],
['value', this.btnFirstPageText], ['value', this.btnFirstPageText],
['title', 'First'] ['title', 'First']
); );
btnFirst.className = this.btnPageCssClass; btnFirst.className = this.btnCssClass;
addEvt(btnFirst, 'click', evt.first); addEvt(btnFirst, 'click', evt.first);
btnFirstSpan.appendChild(btnFirst); btnFirstSpan.appendChild(btnFirst);
} else { } else {
@ -435,23 +445,22 @@ export class Paging extends Feature {
} }
// paging elements (buttons+drop-down list) are added to defined element // paging elements (buttons+drop-down list) are added to defined element
if (!this.pagingTgtId) { let targetEl = !this.tgtId ?
tf.setToolbar(); tf.feature('toolbar').container(this.toolbarPosition) :
} elm(this.tgtId);
var targetEl = !this.pagingTgtId ? tf.mDiv : elm(this.pagingTgtId);
targetEl.appendChild(btnFirstSpan); targetEl.appendChild(btnFirstSpan);
targetEl.appendChild(btnPrevSpan); targetEl.appendChild(btnPrevSpan);
var pgBeforeSpan = createElm('span'); let pgBeforeSpan = createElm('span');
pgBeforeSpan.appendChild(createText(this.pageText)); pgBeforeSpan.appendChild(createText(this.pageText));
pgBeforeSpan.className = this.nbPgSpanCssClass; pgBeforeSpan.className = this.nbPgSpanCssClass;
targetEl.appendChild(pgBeforeSpan); targetEl.appendChild(pgBeforeSpan);
targetEl.appendChild(slcPages); targetEl.appendChild(slcPages);
var pgAfterSpan = createElm('span'); let pgAfterSpan = createElm('span');
pgAfterSpan.appendChild(createText(this.ofText)); pgAfterSpan.appendChild(createText(this.ofText));
pgAfterSpan.className = this.nbPgSpanCssClass; pgAfterSpan.className = this.nbPgSpanCssClass;
targetEl.appendChild(pgAfterSpan); targetEl.appendChild(pgAfterSpan);
var pgSpan = createElm('span'); let pgSpan = createElm('span');
pgSpan.className = this.nbPgSpanCssClass; pgSpan.className = this.nbPgSpanCssClass;
pgSpan.appendChild(createText(' ' + this.nbPages + ' ')); pgSpan.appendChild(createText(' ' + this.nbPages + ' '));
targetEl.appendChild(pgSpan); targetEl.appendChild(pgSpan);
@ -465,7 +474,7 @@ export class Paging extends Feature {
this.pgCont = pgSpan; this.pgCont = pgSpan;
this.pgBefore = pgBeforeSpan; this.pgBefore = pgBeforeSpan;
this.pgAfter = pgAfterSpan; this.pgAfter = pgAfterSpan;
this.pagingSlc = slcPages; this.pageSlc = slcPages;
this.setPagingInfo(); this.setPagingInfo();
@ -474,14 +483,15 @@ export class Paging extends Feature {
this.setPagingInfo(tf.validRowsIndex); this.setPagingInfo(tf.validRowsIndex);
} }
this.emitter.on(['after-filtering'], () => this.resetPagingInfo()); this.emitter.on(['after-filtering'], bound(this.resetPagingInfo, this));
this.emitter.on(['change-page'], this.emitter.on(['change-page'], bound(this.changePageHandler, this));
(tf, pageNumber) => this.setPage(pageNumber));
this.emitter.on(['change-page-results'], this.emitter.on(['change-page-results'],
(tf, pageLength) => this.changeResultsPerPage(pageLength)); bound(this.changePageResultsHandler, this));
/** @inherited */ /** @inherited */
this.initialized = true; this.initialized = true;
this.emitter.emit('feature-initialized', this);
} }
/** /**
@ -489,15 +499,11 @@ export class Paging extends Feature {
* @param {Boolean} filterTable Execute filtering once paging instanciated * @param {Boolean} filterTable Execute filtering once paging instanciated
*/ */
reset(filterTable = false) { reset(filterTable = false) {
var tf = this.tf;
if (this.isEnabled()) {
return;
}
this.enable(); this.enable();
this.init(); this.init();
if (filterTable) { if (filterTable) {
tf.filter(); this.tf.filter();
} }
} }
@ -516,36 +522,38 @@ export class Paging extends Feature {
* @param {Array} validRows Collection of valid rows * @param {Array} validRows Collection of valid rows
*/ */
setPagingInfo(validRows) { setPagingInfo(validRows) {
var tf = this.tf; let tf = this.tf;
var mdiv = !this.pagingTgtId ? tf.mDiv : elm(this.pagingTgtId); let cont = !this.tgtId ?
tf.feature('toolbar').container(this.toolbarPosition) :
elm(this.tgtId);
//store valid rows indexes //store valid rows indexes
tf.validRowsIndex = validRows || tf.getValidRows(true); tf.validRowsIndex = validRows || tf.getValidRows(true);
//calculate nb of pages //calculate nb of pages
this.nbPages = Math.ceil(tf.validRowsIndex.length / this.pagingLength); this.nbPages = Math.ceil(tf.validRowsIndex.length / this.pageLength);
//refresh page nb span //refresh page nb span
this.pgCont.innerHTML = this.nbPages; this.pgCont.innerHTML = this.nbPages;
//select clearing shortcut //select clearing shortcut
if (this.pageSelectorType === SELECT) { if (this.pageSelectorType === SELECT) {
this.pagingSlc.innerHTML = ''; this.pageSlc.innerHTML = '';
} }
if (this.nbPages > 0) { if (this.nbPages > 0) {
mdiv.style.visibility = 'visible'; cont.style.visibility = 'visible';
if (this.pageSelectorType === SELECT) { if (this.pageSelectorType === SELECT) {
for (var z = 0; z < this.nbPages; z++) { for (let z = 0; z < this.nbPages; z++) {
var opt = createOpt(z + 1, z * this.pagingLength, false); let opt = createOpt(z + 1, z * this.pageLength, false);
this.pagingSlc.options[z] = opt; this.pageSlc.options[z] = opt;
} }
} else { } else {
//input type //input type
this.pagingSlc.value = this.currentPageNb; this.pageSlc.value = this.currentPageNb;
} }
} else { } else {
/*** if no results paging select and buttons are hidden ***/ /*** if no results paging select and buttons are hidden ***/
mdiv.style.visibility = 'hidden'; cont.style.visibility = 'hidden';
} }
this.groupByPage(tf.validRowsIndex); this.groupByPage(tf.validRowsIndex);
} }
@ -555,10 +563,10 @@ export class Paging extends Feature {
* @param {Array} validRows Collection of valid rows * @param {Array} validRows Collection of valid rows
*/ */
groupByPage(validRows) { groupByPage(validRows) {
var tf = this.tf; let tf = this.tf;
var rows = tf.tbl.rows; let rows = tf.dom().rows;
var startPagingRow = parseInt(this.startPagingRow, 10); let startPagingRow = parseInt(this.startPagingRow, 10);
var endPagingRow = startPagingRow + parseInt(this.pagingLength, 10); let endPagingRow = startPagingRow + parseInt(this.pageLength, 10);
//store valid rows indexes //store valid rows indexes
if (validRows) { if (validRows) {
@ -566,11 +574,11 @@ export class Paging extends Feature {
} }
//this loop shows valid rows of current page //this loop shows valid rows of current page
for (var h = 0, len = tf.getValidRowsNb(true); h < len; h++) { for (let h = 0, len = tf.getValidRowsNb(true); h < len; h++) {
var validRowIdx = tf.validRowsIndex[h]; let validRowIdx = tf.validRowsIndex[h];
var r = rows[validRowIdx]; let r = rows[validRowIdx];
var isRowValid = r.getAttribute('validRow'); let isRowValid = r.getAttribute('validRow');
var rowDisplayed = false; let rowDisplayed = false;
if (h >= startPagingRow && h < endPagingRow) { if (h >= startPagingRow && h < endPagingRow) {
if (isNull(isRowValid) || Boolean(isRowValid === 'true')) { if (isNull(isRowValid) || Boolean(isRowValid === 'true')) {
@ -601,11 +609,11 @@ export class Paging extends Feature {
* 'previous', 'last', 'first' or page number as per param * 'previous', 'last', 'first' or page number as per param
*/ */
setPage(cmd) { setPage(cmd) {
var tf = this.tf; let tf = this.tf;
if (!tf.isInitialized() || !this.isEnabled()) { if (!tf.isInitialized() || !this.isEnabled()) {
return; return;
} }
var btnEvt = this.evt, let btnEvt = this.evt,
cmdtype = typeof cmd; cmdtype = typeof cmd;
if (cmdtype === 'string') { if (cmdtype === 'string') {
switch (cmd.toLowerCase()) { switch (cmd.toLowerCase()) {
@ -635,10 +643,10 @@ export class Paging extends Feature {
* Generates UI elements for the number of results per page drop-down * Generates UI elements for the number of results per page drop-down
*/ */
setResultsPerPage() { setResultsPerPage() {
var tf = this.tf; let tf = this.tf;
var evt = this.evt; let evt = this.evt;
if (this.resultsPerPageSlc || !this.resultsPerPage) { if (this.pageLengthSlc || !this.resultsPerPage) {
return; return;
} }
@ -647,22 +655,20 @@ export class Paging extends Feature {
ev.target.blur(); ev.target.blur();
}; };
var slcR = createElm(SELECT); let slcR = createElm(SELECT);
slcR.className = this.resultsSlcCssClass; slcR.className = this.resultsSlcCssClass;
var slcRText = this.resultsPerPage[0], let slcRText = this.resultsPerPage[0],
slcROpts = this.resultsPerPage[1]; slcROpts = this.resultsPerPage[1];
var slcRSpan = createElm('span'); let slcRSpan = createElm('span');
slcRSpan.className = this.resultsSpanCssClass; slcRSpan.className = this.resultsSpanCssClass;
// results per page select is added to external element // results per page select is added to external element
if (!this.resultsPerPageTgtId) { let targetEl = !this.pageLengthTgtId ?
tf.setToolbar(); tf.feature('toolbar').container(RIGHT) :
} elm(this.pageLengthTgtId);
var targetEl = !this.resultsPerPageTgtId ?
tf.rDiv : elm(this.resultsPerPageTgtId);
slcRSpan.appendChild(createText(slcRText)); slcRSpan.appendChild(createText(slcRText));
var help = tf.feature('help'); let help = tf.feature('help');
if (help && help.btn) { if (help && help.btn) {
help.btn.parentNode.insertBefore(slcRSpan, help.btn); help.btn.parentNode.insertBefore(slcRSpan, help.btn);
help.btn.parentNode.insertBefore(slcR, help.btn); help.btn.parentNode.insertBefore(slcR, help.btn);
@ -671,31 +677,31 @@ export class Paging extends Feature {
targetEl.appendChild(slcR); targetEl.appendChild(slcR);
} }
for (var r = 0; r < slcROpts.length; r++) { for (let r = 0; r < slcROpts.length; r++) {
var currOpt = new Option(slcROpts[r], slcROpts[r], false, false); let currOpt = new Option(slcROpts[r], slcROpts[r], false, false);
slcR.options[r] = currOpt; slcR.options[r] = currOpt;
} }
addEvt(slcR, 'change', evt.slcResultsChange); addEvt(slcR, 'change', evt.slcResultsChange);
this.slcResultsTxt = slcRSpan; this.slcResultsTxt = slcRSpan;
this.resultsPerPageSlc = slcR; this.pageLengthSlc = slcR;
} }
/** /**
* Remove number of results per page UI elements * Remove number of results per page UI elements
*/ */
removeResultsPerPage() { removeResultsPerPage() {
var tf = this.tf; let tf = this.tf;
if (!tf.isInitialized() || !this.resultsPerPageSlc || if (!tf.isInitialized() || !this.pageLengthSlc ||
!this.resultsPerPage) { !this.resultsPerPage) {
return; return;
} }
if (this.resultsPerPageSlc) { if (this.pageLengthSlc) {
removeElm(this.resultsPerPageSlc); removeElm(this.pageLengthSlc);
} }
if (this.slcResultsTxt) { if (this.slcResultsTxt) {
removeElm(this.slcResultsTxt); removeElm(this.slcResultsTxt);
} }
this.resultsPerPageSlc = null; this.pageLengthSlc = null;
this.slcResultsTxt = null; this.slcResultsTxt = null;
} }
@ -704,7 +710,7 @@ export class Paging extends Feature {
* @param {Number} index Index of the page (0-n) * @param {Number} index Index of the page (0-n)
*/ */
changePage(index) { changePage(index) {
var tf = this.tf; let tf = this.tf;
if (!this.isEnabled()) { if (!this.isEnabled()) {
return; return;
@ -714,20 +720,20 @@ export class Paging extends Feature {
if (index === null) { if (index === null) {
index = this.pageSelectorType === SELECT ? index = this.pageSelectorType === SELECT ?
this.pagingSlc.options.selectedIndex : this.pagingSlc.value - 1; this.pageSlc.options.selectedIndex : this.pageSlc.value - 1;
} }
if (index >= 0 && index <= (this.nbPages - 1)) { if (index >= 0 && index <= (this.nbPages - 1)) {
this.onBeforeChangePage(this, (index + 1)); this.onBeforeChangePage(this, (index + 1));
this.currentPageNb = parseInt(index, 10) + 1; this.currentPageNb = parseInt(index, 10) + 1;
if (this.pageSelectorType === SELECT) { if (this.pageSelectorType === SELECT) {
this.pagingSlc.options[index].selected = true; this.pageSlc.options[index].selected = true;
} else { } else {
this.pagingSlc.value = this.currentPageNb; this.pageSlc.value = this.currentPageNb;
} }
this.startPagingRow = (this.pageSelectorType === SELECT) ? this.startPagingRow = (this.pageSelectorType === SELECT) ?
this.pagingSlc.value : (index * this.pagingLength); this.pageSlc.value : (index * this.pageLength);
this.groupByPage(); this.groupByPage();
@ -746,7 +752,7 @@ export class Paging extends Feature {
return; return;
} }
this.resultsPerPageSlc.value = val; this.pageLengthSlc.value = val;
this.onChangeResultsPerPage(); this.onChangeResultsPerPage();
} }
@ -754,49 +760,51 @@ export class Paging extends Feature {
* Change rows according to page results drop-down * Change rows according to page results drop-down
*/ */
onChangeResultsPerPage() { onChangeResultsPerPage() {
var tf = this.tf; let tf = this.tf;
if (!this.isEnabled()) { if (!this.isEnabled() || tf.getValidRowsNb() === 0) {
return; return;
} }
this.emitter.emit('before-page-length-change', tf); let {
pageLengthSlc: slcR, pageSelectorType, pageSlc, emitter
} = this;
var slcR = this.resultsPerPageSlc; emitter.emit('before-page-length-change', tf);
var slcIndex = slcR.selectedIndex;
var slcPagesSelIndex = (this.pageSelectorType === SELECT) ?
this.pagingSlc.selectedIndex :
parseInt(this.pagingSlc.value - 1, 10);
this.pagingLength = parseInt(slcR.options[slcIndex].value, 10);
this.startPagingRow = this.pagingLength * slcPagesSelIndex;
if (!isNaN(this.pagingLength)) { let slcIndex = slcR.selectedIndex;
let slcPagesSelIndex = (pageSelectorType === SELECT) ?
pageSlc.selectedIndex : parseInt(pageSlc.value - 1, 10);
this.pageLength = parseInt(slcR.options[slcIndex].value, 10);
this.startPagingRow = this.pageLength * slcPagesSelIndex;
if (!isNaN(this.pageLength)) {
if (this.startPagingRow >= tf.nbFilterableRows) { if (this.startPagingRow >= tf.nbFilterableRows) {
this.startPagingRow = (tf.nbFilterableRows - this.pagingLength); this.startPagingRow = (tf.nbFilterableRows - this.pageLength);
} }
this.setPagingInfo(); this.setPagingInfo();
if (this.pageSelectorType === SELECT) { if (pageSelectorType === SELECT) {
var slcIdx = let slcIdx = (pageSlc.options.length - 1 <= slcPagesSelIndex) ?
(this.pagingSlc.options.length - 1 <= slcPagesSelIndex) ? (pageSlc.options.length - 1) :
(this.pagingSlc.options.length - 1) : slcPagesSelIndex; slcPagesSelIndex;
this.pagingSlc.options[slcIdx].selected = true; pageSlc.options[slcIdx].selected = true;
} }
} }
this.emitter.emit('after-page-length-change', tf, this.pagingLength); emitter.emit('after-page-length-change', tf, this.pageLength);
} }
/** /**
* Re-set page nb at page re-load * Re-set page nb at page re-load
*/ */
resetPage() { resetPage() {
var tf = this.tf; let tf = this.tf;
if (!this.isEnabled()) { if (!this.isEnabled()) {
return; return;
} }
this.emitter.emit('before-reset-page', tf); this.emitter.emit('before-reset-page', tf);
var pgNb = tf.feature('store').getPageNb(); let pgNb = tf.feature('store').getPageNb();
if (pgNb !== '') { if (pgNb !== '') {
this.changePage((pgNb - 1)); this.changePage((pgNb - 1));
} }
@ -807,20 +815,30 @@ export class Paging extends Feature {
* Re-set page length value at page re-load * Re-set page length value at page re-load
*/ */
resetPageLength() { resetPageLength() {
var tf = this.tf; let tf = this.tf;
if (!this.isEnabled()) { if (!this.isEnabled()) {
return; return;
} }
this.emitter.emit('before-reset-page-length', tf); this.emitter.emit('before-reset-page-length', tf);
var pglenIndex = tf.feature('store').getPageLength(); let pglenIndex = tf.feature('store').getPageLength();
if (pglenIndex !== '') { if (pglenIndex !== '') {
this.resultsPerPageSlc.options[pglenIndex].selected = true; this.pageLengthSlc.options[pglenIndex].selected = true;
this.changeResultsPerPage(); this.changeResultsPerPage();
} }
this.emitter.emit('after-reset-page-length', tf, pglenIndex); this.emitter.emit('after-reset-page-length', tf, pglenIndex);
} }
/** @private */
changePageHandler(tf, pageNumber) {
this.setPage(pageNumber);
}
/** @private */
changePageResultsHandler(tf, pageLength) {
this.changeResultsPerPage(pageLength);
}
/** /**
* Remove paging feature * Remove paging feature
*/ */
@ -829,16 +847,16 @@ export class Paging extends Feature {
return; return;
} }
var evt = this.evt; let evt = this.evt;
if (this.pagingSlc) { if (this.pageSlc) {
if (this.pageSelectorType === SELECT) { if (this.pageSelectorType === SELECT) {
removeEvt(this.pagingSlc, 'change', evt.slcPagesChange); removeEvt(this.pageSlc, 'change', evt.slcPagesChange);
} }
else if (this.pageSelectorType === INPUT) { else if (this.pageSelectorType === INPUT) {
removeEvt(this.pagingSlc, 'keypress', evt._detectKey); removeEvt(this.pageSlc, 'keypress', evt._detectKey);
} }
removeElm(this.pagingSlc); removeElm(this.pageSlc);
} }
if (this.btnNextCont) { if (this.btnNextCont) {
@ -884,15 +902,15 @@ export class Paging extends Feature {
this.removeResultsPerPage(); this.removeResultsPerPage();
} }
this.emitter.off(['after-filtering'], () => this.resetPagingInfo()); this.emitter.off(['after-filtering'],
this.emitter.off(['change-page'], bound(this.resetPagingInfo, this));
(tf, pageNumber) => this.setPage(pageNumber)); this.emitter.off(['change-page'], bound(this.changePageHandler, this));
this.emitter.off(['change-page-results'], this.emitter.off(['change-page-results'],
(tf, pageLength) => this.changeResultsPerPage(pageLength)); bound(this.changePageResultsHandler, this));
this.pagingSlc = null; this.pageSlc = null;
this.nbPages = 0; this.nbPages = 0;
this.disable();
this.initialized = false; this.initialized = false;
} }
} }

View file

@ -1,9 +1,10 @@
import {Feature} from '../feature'; import {Feature} from '../feature';
import {isFn, isUndef, EMPTY_FN} from '../types'; import {isUndef, EMPTY_FN} from '../types';
import {createElm, removeElm} from '../dom'; import {createElm, removeElm} from '../dom';
import {addEvt, cancelEvt, stopEvt, targetEvt, removeEvt} from '../event'; import {addEvt, cancelEvt, stopEvt, targetEvt, removeEvt} from '../event';
import {INPUT, NONE, CHECKLIST, MULTIPLE} from '../const'; import {INPUT, NONE, CHECKLIST, MULTIPLE} from '../const';
import {root} from '../root'; import {root} from '../root';
import {defaultsStr, defaultsBool, defaultsArr, defaultsFn} from '../settings';
/** /**
* Pop-up filter component * Pop-up filter component
@ -18,84 +19,81 @@ export class PopupFilter extends Feature {
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'popupFilters'); super(tf, PopupFilter);
// Configuration object // Configuration object
let f = this.config; let f = this.config.popup_filters || {};
// Enable external filters
tf.isExternalFlt = true;
tf.externalFltTgtIds = [];
/** /**
* Close active popup filter upon filtering, enabled by default * Close active popup filter upon filtering, enabled by default
* @type {Boolean} * @type {Boolean}
*/ */
this.closeOnFiltering = f.popup_filters_close_on_filtering === false ? this.closeOnFiltering = defaultsBool(f.close_on_filtering, true);
false : true;
/** /**
* Filter icon path * Filter icon path
* @type {String} * @type {String}
*/ */
this.iconPath = f.popup_filters_image || this.iconPath = defaultsStr(f.image, tf.themesPath + 'icn_filter.gif');
tf.themesPath + 'icn_filter.gif';
/** /**
* Active filter icon path * Active filter icon path
* @type {string} * @type {string}
*/ */
this.activeIconPath = f.popup_filters_image_active || this.activeIconPath = defaultsStr(f.image_active,
tf.themesPath + 'icn_filterActive.gif'; tf.themesPath + 'icn_filterActive.gif');
/** /**
* HTML for the filter icon * HTML for the filter icon
* @type {string} * @type {string}
*/ */
this.iconHtml = f.popup_filters_image_html || this.iconHtml = defaultsStr(f.image_html,
'<img src="' + this.iconPath + '" alt="Column filter" />'; '<img src="' + this.iconPath + '" alt="Column filter" />');
/**
* Css class assigned to the popup container element
* @type {String}
*/
this.placeholderCssClass = defaultsStr(f.placeholder_css_class,
'popUpPlaceholder');
/** /**
* Css class assigned to filter container element * Css class assigned to filter container element
* @type {String} * @type {String}
*/ */
this.containerCssClass = f.popup_div_css_class || 'popUpFilter'; this.containerCssClass = defaultsStr(f.div_css_class, 'popUpFilter');
/** /**
* Ensure filter's container element width matches column width, enabled * Ensure filter's container element width matches column width, enabled
* by default * by default
* @type {Boolean} * @type {Boolean}
*/ */
this.adjustToContainer = this.adjustToContainer = defaultsBool(f.adjust_to_container, true);
f.popup_filters_adjust_to_container === false ? false : true;
/** /**
* Callback fired before a popup filter is opened * Callback fired before a popup filter is opened
* @type {Function} * @type {Function}
*/ */
this.onBeforeOpen = isFn(f.on_before_popup_filter_open) ? this.onBeforeOpen = defaultsFn(f.on_before_popup_filter_open, EMPTY_FN);
f.on_before_popup_filter_open : EMPTY_FN;
/** /**
* Callback fired after a popup filter is opened * Callback fired after a popup filter is opened
* @type {Function} * @type {Function}
*/ */
this.onAfterOpen = isFn(f.on_after_popup_filter_open) ? this.onAfterOpen = defaultsFn(f.on_after_popup_filter_open, EMPTY_FN);
f.on_after_popup_filter_open : EMPTY_FN;
/** /**
* Callback fired before a popup filter is closed * Callback fired before a popup filter is closed
* @type {Function} * @type {Function}
*/ */
this.onBeforeClose = isFn(f.on_before_popup_filter_close) ? this.onBeforeClose = defaultsFn(f.on_before_popup_filter_close,
f.on_before_popup_filter_close : EMPTY_FN; EMPTY_FN);
/** /**
* Callback fired after a popup filter is closed * Callback fired after a popup filter is closed
* @type {Function} * @type {Function}
*/ */
this.onAfterClose = isFn(f.on_after_popup_filter_close) ? this.onAfterClose = defaultsFn(f.on_after_popup_filter_close, EMPTY_FN);
f.on_after_popup_filter_close : EMPTY_FN;
/** /**
* Collection of filters spans * Collection of filters spans
@ -123,7 +121,7 @@ export class PopupFilter extends Feature {
* @type {Array} * @type {Array}
* @private * @private
*/ */
this.fltElms = this.filtersCache || []; this.fltElms = defaultsArr(this.filtersCache, []);
/** /**
* Prefix for pop-up filter container ID * Prefix for pop-up filter container ID
@ -198,6 +196,12 @@ export class PopupFilter extends Feature {
let tf = this.tf; let tf = this.tf;
// Enable external filters
tf.externalFltIds = [''];
// Override filters row index supplied by configuration
tf.filtersRowIndex = 0;
// Override headers row index if no grouped headers // Override headers row index if no grouped headers
// TODO: Because of the filters row generation, headers row index needs // TODO: Because of the filters row generation, headers row index needs
// adjusting: prevent useless row generation // adjusting: prevent useless row generation
@ -246,10 +250,8 @@ export class PopupFilter extends Feature {
// adjusting: prevent useless row generation // adjusting: prevent useless row generation
tf.headersRow++; tf.headersRow++;
for (let i = 0; i < tf.nbCells; i++) { tf.eachCol(
if (tf.getFilterType(i) === NONE) { (i) => {
continue;
}
let icon = createElm('span', ['ci', i]); let icon = createElm('span', ['ci', i]);
icon.innerHTML = this.iconHtml; icon.innerHTML = this.iconHtml;
let header = tf.getHeaderElement(i); let header = tf.getHeaderElement(i);
@ -257,7 +259,10 @@ export class PopupFilter extends Feature {
addEvt(icon, 'click', (evt) => this.onClick(evt)); addEvt(icon, 'click', (evt) => this.onClick(evt));
this.fltSpans[i] = icon; this.fltSpans[i] = icon;
this.fltIcons[i] = icon.firstChild; this.fltIcons[i] = icon.firstChild;
} },
// continue condition function
(i) => tf.getFilterType(i) === NONE
);
} }
/** /**
@ -277,12 +282,14 @@ export class PopupFilter extends Feature {
build(colIndex, div) { build(colIndex, div) {
let tf = this.tf; let tf = this.tf;
let contId = `${this.prfxDiv}${tf.id}_${colIndex}`; let contId = `${this.prfxDiv}${tf.id}_${colIndex}`;
let cont = div || createElm('div', ['id', contId]); let placeholder = createElm('div', ['class', this.placeholderCssClass]);
cont.className = this.containerCssClass; let cont = div ||
tf.externalFltTgtIds.push(cont.id); createElm('div', ['id', contId], ['class', this.containerCssClass]);
tf.externalFltIds[colIndex] = cont.id;
placeholder.appendChild(cont);
let header = tf.getHeaderElement(colIndex); let header = tf.getHeaderElement(colIndex);
header.insertBefore(cont, header.firstChild); header.insertBefore(placeholder, header.firstChild);
addEvt(cont, 'click', (evt) => stopEvt(evt)); addEvt(cont, 'click', (evt) => stopEvt(evt));
this.fltElms[colIndex] = cont; this.fltElms[colIndex] = cont;
} }
@ -364,7 +371,7 @@ export class PopupFilter extends Feature {
if (i === exceptIdx) { if (i === exceptIdx) {
continue; continue;
} }
let fltType = tf.getFilterType(i); let fltType = this.tf.getFilterType(i);
let isMultipleFilter = let isMultipleFilter =
(fltType === CHECKLIST || fltType === MULTIPLE); (fltType === CHECKLIST || fltType === MULTIPLE);
@ -408,6 +415,7 @@ export class PopupFilter extends Feature {
this.filtersCache = []; this.filtersCache = [];
for (let i = 0; i < this.fltElms.length; i++) { for (let i = 0; i < this.fltElms.length; i++) {
let container = this.fltElms[i], let container = this.fltElms[i],
placeholder = container.parentNode,
icon = this.fltSpans[i], icon = this.fltSpans[i],
iconImg = this.fltIcons[i]; iconImg = this.fltIcons[i];
if (container) { if (container) {
@ -415,6 +423,10 @@ export class PopupFilter extends Feature {
this.filtersCache[i] = container; this.filtersCache[i] = container;
} }
container = null; container = null;
if (placeholder) {
removeElm(placeholder);
}
placeholder = null;
if (icon) { if (icon) {
removeElm(icon); removeElm(icon);
} }
@ -429,7 +441,7 @@ export class PopupFilter extends Feature {
this.fltIcons = []; this.fltIcons = [];
// TODO: expose an API to handle external filter IDs // TODO: expose an API to handle external filter IDs
tf.externalFltTgtIds = []; this.tf.externalFltIds = [];
// unsubscribe to events // unsubscribe to events
this.emitter.off(['before-filtering'], () => this.setIconsState()); this.emitter.off(['before-filtering'], () => this.setIconsState());
@ -444,3 +456,6 @@ export class PopupFilter extends Feature {
} }
} }
// TODO: remove as soon as feature name is fixed
PopupFilter.meta = {altName: 'popupFilters'};

View file

@ -1,6 +1,8 @@
import {Feature} from '../feature'; import {Feature} from '../feature';
import {createElm, createText, elm, removeElm} from '../dom'; import {createElm, createText, elm, removeElm} from '../dom';
import {isFn, EMPTY_FN} from '../types'; import {EMPTY_FN, isNull} from '../types';
import {defaultsStr, defaultsFn} from '../settings';
import {LEFT} from './toolbar';
/** /**
* Rows counter UI component * Rows counter UI component
@ -15,16 +17,16 @@ export class RowsCounter extends Feature {
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'rowsCounter'); super(tf, RowsCounter);
// TableFilter configuration // TableFilter configuration
let f = this.config; let f = this.config.rows_counter || {};
/** /**
* ID of custom container element * ID of custom container element
* @type {String} * @type {String}
*/ */
this.targetId = f.rows_counter_target_id || null; this.targetId = defaultsStr(f.target_id, null);
/** /**
* Container DOM element * Container DOM element
@ -44,14 +46,14 @@ export class RowsCounter extends Feature {
* Text preceding the total number of rows * Text preceding the total number of rows
* @type {String} * @type {String}
*/ */
this.text = f.rows_counter_text || 'Rows: '; this.text = defaultsStr(f.text, 'Rows: ');
/** /**
* Separator symbol appearing between the first and last visible rows of * Separator symbol appearing between the first and last visible rows of
* current page when paging is enabled. ie: Rows: 31-40 / 70 * current page when paging is enabled. ie: Rows: 31-40 / 70
* @type {String} * @type {String}
*/ */
this.fromToTextSeparator = f.from_to_text_separator || '-'; this.fromToTextSeparator = defaultsStr(f.separator, '-');
/** /**
* Separator symbol appearing between the first and last visible rows of * Separator symbol appearing between the first and last visible rows of
@ -59,27 +61,33 @@ export class RowsCounter extends Feature {
* enabled. ie: Rows: 31-40 / 70 * enabled. ie: Rows: 31-40 / 70
* @type {String} * @type {String}
*/ */
this.overText = f.over_text || ' / '; this.overText = defaultsStr(f.over_text, ' / ');
/** /**
* Css class for container element * Css class for container element
* @type {String} * @type {String}
*/ */
this.cssClass = f.tot_rows_css_class || 'tot'; this.cssClass = defaultsStr(f.css_class, 'tot');
/**
* Default position in toolbar ('left'|'center'|'right')
* @type {String}
*/
this.toolbarPosition = defaultsStr(f.toolbar_position, LEFT);
/** /**
* Callback fired before the counter is refreshed * Callback fired before the counter is refreshed
* @type {Function} * @type {Function}
*/ */
this.onBeforeRefreshCounter = isFn(f.on_before_refresh_counter) ? this.onBeforeRefreshCounter = defaultsFn(f.on_before_refresh_counter,
f.on_before_refresh_counter : EMPTY_FN; EMPTY_FN);
/** /**
* Callback fired after the counter is refreshed * Callback fired after the counter is refreshed
* @type {Function} * @type {Function}
*/ */
this.onAfterRefreshCounter = isFn(f.on_after_refresh_counter) ? this.onAfterRefreshCounter = defaultsFn(f.on_after_refresh_counter,
f.on_after_refresh_counter : EMPTY_FN; EMPTY_FN);
} }
/** /**
@ -90,6 +98,8 @@ export class RowsCounter extends Feature {
return; return;
} }
this.emitter.emit('initializing-feature', this, !isNull(this.targetId));
let tf = this.tf; let tf = this.tf;
//rows counter container //rows counter container
@ -101,18 +111,16 @@ export class RowsCounter extends Feature {
countText.appendChild(createText(this.text)); countText.appendChild(createText(this.text));
// counter is added to defined element // counter is added to defined element
if (!this.targetId) { let targetEl = !this.targetId ?
tf.setToolbar(); tf.feature('toolbar').container(this.toolbarPosition) :
} elm(this.targetId);
let targetEl = !this.targetId ? tf.lDiv : elm(this.targetId);
//default container: 'lDiv' //default container: 'lDiv'
if (!this.targetId) { if (!this.targetId) {
countDiv.appendChild(countText); countDiv.appendChild(countText);
countDiv.appendChild(countSpan); countDiv.appendChild(countSpan);
targetEl.appendChild(countDiv); targetEl.appendChild(countDiv);
} } else {
else {
//custom container, no need to append statusDiv //custom container, no need to append statusDiv
targetEl.appendChild(countText); targetEl.appendChild(countText);
targetEl.appendChild(countSpan); targetEl.appendChild(countSpan);
@ -128,12 +136,13 @@ export class RowsCounter extends Feature {
/** @inherited */ /** @inherited */
this.initialized = true; this.initialized = true;
this.refresh(); this.refresh();
this.emitter.emit('feature-initialized', this);
} }
/** /**
* Refreshes the rows counter * Refreshes the rows counter
* @param {Number} p Optional parameter the total number of rows to display * @param {Number} p Optional parameter the total number of rows to display
* @returns
*/ */
refresh(p) { refresh(p) {
if (!this.initialized || !this.isEnabled()) { if (!this.initialized || !this.isEnabled()) {
@ -154,16 +163,17 @@ export class RowsCounter extends Feature {
} else { } else {
let paging = tf.feature('paging'); let paging = tf.feature('paging');
if (paging) { if (paging) {
let nbValidRows = tf.getValidRowsNb();
//paging start row //paging start row
let pagingStartRow = parseInt(paging.startPagingRow, 10) + let pagingStartRow = parseInt(paging.startPagingRow, 10) +
((tf.getValidRowsNb() > 0) ? 1 : 0); ((nbValidRows > 0) ? 1 : 0);
let pagingEndRow = let pagingEndRow =
(pagingStartRow + paging.pagingLength) - 1 <= (pagingStartRow + paging.pageLength) - 1 <=
tf.getValidRowsNb() ? nbValidRows ?
pagingStartRow + paging.pagingLength - 1 : pagingStartRow + paging.pageLength - 1 :
tf.getValidRowsNb(); nbValidRows;
totTxt = pagingStartRow + this.fromToTextSeparator + totTxt = pagingStartRow + this.fromToTextSeparator +
pagingEndRow + this.overText + tf.getValidRowsNb(); pagingEndRow + this.overText + nbValidRows;
} }
} }

View file

@ -3,6 +3,7 @@ import {Hash} from './hash';
import {Storage} from './storage'; import {Storage} from './storage';
import {isEmpty} from '../string'; import {isEmpty} from '../string';
import {isArray, isNull, isString, isUndef} from '../types'; import {isArray, isNull, isString, isUndef} from '../types';
import {defaultsBool, defaultsNb} from '../settings';
/** /**
* Features state object persistable with localStorage, cookie or URL hash * Features state object persistable with localStorage, cookie or URL hash
@ -18,9 +19,9 @@ export class State extends Feature {
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'state'); super(tf, State);
let cfg = this.config.state; let cfg = this.config.state || {};
/** /**
* Determines whether state is persisted with URL hash * Determines whether state is persisted with URL hash
@ -47,7 +48,7 @@ export class State extends Feature {
* Persist filters values, enabled by default * Persist filters values, enabled by default
* @type {Boolean} * @type {Boolean}
*/ */
this.persistFilters = cfg.filters === false ? false : true; this.persistFilters = defaultsBool(cfg.filters, true);
/** /**
* Persist current page number when paging is enabled * Persist current page number when paging is enabled
@ -83,8 +84,8 @@ export class State extends Feature {
* Cookie duration in hours * Cookie duration in hours
* @type {Boolean} * @type {Boolean}
*/ */
this.cookieDuration = !isNaN(cfg.cookie_duration) ? this.cookieDuration = defaultsNb(parseInt(cfg.cookie_duration, 10),
parseInt(cfg.cookie_duration, 10) : 87600; 87600);
/** /**
* Enable Storage if localStorage or cookie is required * Enable Storage if localStorage or cookie is required
@ -212,9 +213,7 @@ export class State extends Feature {
this.storage.init(); this.storage.init();
} }
/** /** @inherited */
* @inherited
*/
this.initialized = true; this.initialized = true;
} }
@ -366,6 +365,7 @@ export class State extends Feature {
*/ */
override(state) { override(state) {
this.state = state; this.state = state;
this.emitter.emit('state-changed', this.tf, state);
} }
/** /**
@ -421,6 +421,10 @@ export class State extends Feature {
let state = this.state; let state = this.state;
let tf = this.tf; let tf = this.tf;
// clear all filters
// TODO: use tf.clearFilters() once it allows to not filter the table
tf.eachCol((colIdx) => tf.setFilterValue(colIdx, ''));
Object.keys(state).forEach((key) => { Object.keys(state).forEach((key) => {
if (key.indexOf(this.prfxCol) !== -1) { if (key.indexOf(this.prfxCol) !== -1) {
let colIdx = parseInt(key.replace(this.prfxCol, ''), 10); let colIdx = parseInt(key.replace(this.prfxCol, ''), 10);

View file

@ -1,7 +1,9 @@
import {Feature} from '../feature'; import {Feature} from '../feature';
import {root} from '../root'; import {root} from '../root';
import {createElm, createText, elm, removeElm} from '../dom'; import {createElm, createText, elm, removeElm} from '../dom';
import {isFn, EMPTY_FN} from '../types'; import {EMPTY_FN, isNull} from '../types';
import {defaultsStr, defaultsFn} from '../settings';
import {LEFT} from './toolbar';
const EVENTS = [ const EVENTS = [
'after-filtering', 'after-filtering',
@ -28,16 +30,16 @@ export class StatusBar extends Feature {
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'statusBar'); super(tf, StatusBar);
// Configuration object // Configuration object
let f = this.config; let f = this.config.status_bar || {};
/** /**
* ID of custom container element * ID of custom container element
* @type {String} * @type {String}
*/ */
this.targetId = f.status_bar_target_id || null; this.targetId = defaultsStr(f.target_id, null);
/** /**
* Container DOM element * Container DOM element
@ -64,13 +66,13 @@ export class StatusBar extends Feature {
* Text preceding status message * Text preceding status message
* @type {String} * @type {String}
*/ */
this.text = f.status_bar_text || ''; this.text = defaultsStr(f.text, '');
/** /**
* Css class for container element * Css class for container element
* @type {String} * @type {String}
*/ */
this.cssClass = f.status_bar_css_class || 'status'; this.cssClass = defaultsStr(f.css_class, 'status');
/** /**
* Message visibility duration in milliseconds * Message visibility duration in milliseconds
@ -83,85 +85,91 @@ export class StatusBar extends Feature {
* Callback fired before the message is displayed * Callback fired before the message is displayed
* @type {Function} * @type {Function}
*/ */
this.onBeforeShowMsg = isFn(f.on_before_show_msg) ? this.onBeforeShowMsg = defaultsFn(f.on_before_show_msg, EMPTY_FN);
f.on_before_show_msg : EMPTY_FN;
/** /**
* Callback fired after the message is displayed * Callback fired after the message is displayed
* @type {Function} * @type {Function}
*/ */
this.onAfterShowMsg = isFn(f.on_after_show_msg) ? this.onAfterShowMsg = defaultsFn(f.on_after_show_msg, EMPTY_FN);
f.on_after_show_msg : EMPTY_FN;
/** /**
* Message appearing upon filtering * Message appearing upon filtering
* @type {String} * @type {String}
*/ */
this.msgFilter = f.msg_filter || 'Filtering data...'; this.msgFilter = defaultsStr(f.msg_filter, 'Filtering data...');
/** /**
* Message appearing when a drop-down filter is populated * Message appearing when a drop-down filter is populated
* @type {String} * @type {String}
*/ */
this.msgPopulate = f.msg_populate || 'Populating filter...'; this.msgPopulate = defaultsStr(f.msg_populate, 'Populating filter...');
/** /**
* Message appearing when a checklist filter is populated * Message appearing when a checklist filter is populated
* @type {String} * @type {String}
*/ */
this.msgPopulateCheckList = f.msg_populate_checklist || this.msgPopulateCheckList = defaultsStr(f.msg_populate_checklist,
'Populating list...'; 'Populating list...');
/** /**
* Message appearing when a pagination page is changed * Message appearing when a pagination page is changed
* @type {String} * @type {String}
*/ */
this.msgChangePage = f.msg_change_page || 'Collecting paging data...'; this.msgChangePage = defaultsStr(f.msg_change_page,
'Collecting paging data...');
/** /**
* Message appearing when filters are cleared * Message appearing when filters are cleared
* @type {String} * @type {String}
*/ */
this.msgClear = f.msg_clear || 'Clearing filters...'; this.msgClear = defaultsStr(f.msg_clear, 'Clearing filters...');
/** /**
* Message appearing when the page length is changed * Message appearing when the page length is changed
* @type {String} * @type {String}
*/ */
this.msgChangeResults = f.msg_change_results || this.msgChangeResults = defaultsStr(f.msg_change_results,
'Changing results per page...'; 'Changing results per page...');
/** /**
* Message appearing when the page is re-set * Message appearing when the page is re-set
* @type {String} * @type {String}
*/ */
this.msgResetPage = f.msg_reset_page || 'Re-setting page...'; this.msgResetPage = defaultsStr(f.msg_reset_page, 'Re-setting page...');
/** /**
* Message appearing when the page length is re-set * Message appearing when the page length is re-set
* @type {String} * @type {String}
*/ */
this.msgResetPageLength = f.msg_reset_page_length || this.msgResetPageLength = defaultsStr(f.msg_reset_page_length,
'Re-setting page length...'; 'Re-setting page length...');
/** /**
* Message appearing upon column sorting * Message appearing upon column sorting
* @type {String} * @type {String}
*/ */
this.msgSort = f.msg_sort || 'Sorting data...'; this.msgSort = defaultsStr(f.msg_sort, 'Sorting data...');
/** /**
* Message appearing when extensions are loading * Message appearing when extensions are loading
* @type {String} * @type {String}
*/ */
this.msgLoadExtensions = f.msg_load_extensions || this.msgLoadExtensions = defaultsStr(f.msg_load_extensions,
'Loading extensions...'; 'Loading extensions...');
/** /**
* Message appearing when themes are loading * Message appearing when themes are loading
* @type {String} * @type {String}
*/ */
this.msgLoadThemes = f.msg_load_themes || 'Loading theme(s)...'; this.msgLoadThemes = defaultsStr(f.msg_load_themes,
'Loading theme(s)...');
/**
* Default position in toolbar ('left'|'center'|'right')
* @type {String}
*/
this.toolbarPosition = defaultsStr(f.toolbar_position, LEFT);
} }
/** /**
@ -175,23 +183,24 @@ export class StatusBar extends Feature {
let tf = this.tf; let tf = this.tf;
let emitter = this.emitter; let emitter = this.emitter;
//status bar container emitter.emit('initializing-feature', this, !isNull(this.targetId));
// status bar container
let statusDiv = createElm('div'); let statusDiv = createElm('div');
statusDiv.className = this.cssClass; statusDiv.className = this.cssClass;
//status bar label // status bar label
let statusSpan = createElm('span'); let statusSpan = createElm('span');
//preceding text // preceding text
let statusSpanText = createElm('span'); let statusSpanText = createElm('span');
statusSpanText.appendChild(createText(this.text)); statusSpanText.appendChild(createText(this.text));
// target element container // target element container
if (!this.targetId) { let targetEl = (!this.targetId) ?
tf.setToolbar(); tf.feature('toolbar').container(this.toolbarPosition) :
} elm(this.targetId);
let targetEl = (!this.targetId) ? tf.lDiv : elm(this.targetId);
//default container: 'lDiv' // default container
if (!this.targetId) { if (!this.targetId) {
statusDiv.appendChild(statusSpanText); statusDiv.appendChild(statusSpanText);
statusDiv.appendChild(statusSpan); statusDiv.appendChild(statusSpan);
@ -206,7 +215,7 @@ export class StatusBar extends Feature {
this.msgContainer = statusSpan; this.msgContainer = statusSpan;
this.labelContainer = statusSpanText; this.labelContainer = statusSpanText;
// Subscribe to events // subscribe to events
emitter.on(['before-filtering'], () => this.message(this.msgFilter)); emitter.on(['before-filtering'], () => this.message(this.msgFilter));
emitter.on(['before-populating-filter'], emitter.on(['before-populating-filter'],
() => this.message(this.msgPopulate)); () => this.message(this.msgPopulate));
@ -227,10 +236,10 @@ export class StatusBar extends Feature {
emitter.on(EVENTS, () => this.message('')); emitter.on(EVENTS, () => this.message(''));
/** /** @inherited */
* @inherited
*/
this.initialized = true; this.initialized = true;
emitter.emit('feature-initialized', this);
} }
/** /**

View file

@ -1,4 +1,3 @@
import Cookie from '../cookie'; import Cookie from '../cookie';
import {root} from '../root'; import {root} from '../root';

224
src/modules/toolbar.js Normal file
View file

@ -0,0 +1,224 @@
import {Feature} from '../feature';
import {createElm, removeElm, elm, tag} from '../dom';
import {defaultsStr} from '../settings';
import {isUndef} from '../types';
const EVENTS = [
'initializing-feature',
'initializing-extension'
];
/** Left position in toolbar */
export const LEFT = 'left';
/** Right position in toolbar */
export const RIGHT = 'right';
/** Center position in toolbar */
export const CENTER = 'center';
/**
* Toolbar UI component
* @export
* @class Toolbar
* @extends {Feature}
*/
export class Toolbar extends Feature {
/**
* Create an instance of Toolbar
* @param {TableFilter} tf TableFilter instance
* @memberof Toolbar
*/
constructor(tf) {
super(tf, Toolbar);
// Configuration object
let f = this.config.toolbar || {};
/**
* Css class for toolbar's container DOM element
* @type {String}
*/
this.contCssClass = defaultsStr(f.container_css_class, 'inf');
/**
* Css class for left-side inner container DOM element
* @type {String}
*/
this.lContCssClass = defaultsStr(f.left_cont_css_class, 'ldiv');
/**
* Css class for right-side inner container DOM element
* @type {String}
*/
this.rContCssClass = defaultsStr(f.right_cont_css_class, 'rdiv');
/**
* Css class for middle inner container DOM element
* @type {String}
*/
this.cContCssClass = defaultsStr(f.center_cont_css_class, 'mdiv');
/**
* Toolbar's custom container ID
* @type {String}
*/
this.tgtId = defaultsStr(f.target_id, null);
/**
* Toolbar's container DOM element
* @type {DOMElement}
* @private
*/
this.cont = null;
/**
* Left-side inner container DOM element (rows counter in toolbar)
* @type {DOMElement}
* @private
*/
this.lCont = null;
/**
* Right-side inner container DOM element (reset button,
* page length selector in toolbar)
* @type {DOMElement}
* @private
*/
this.rCont = null;
/**
* Middle inner container DOM element (paging elements in toolbar)
* @type {DOMElement}
* @private
*/
this.cCont = null;
/**
* Container elements inside toolbar
* @private
*/
this.innerCont = {
left: null,
center: null,
right: null
};
this.emitter.on(EVENTS,
(feature, isExternal) => this.init(isExternal));
/** @inherited */
this.enabled = true;
}
/**
* Initialize toolbar components
* @param {Boolean} isExternal initialize only if component belongs
* to toolbar
*/
init(isExternal) {
if (this.initialized || isExternal) {
return;
}
let tf = this.tf;
// default container
let container = createElm('div');
container.className = this.contCssClass;
// custom container
if (this.tgtId) {
elm(this.tgtId).appendChild(container);
}
// grid-layout
else if (tf.gridLayout) {
let gridLayout = tf.Mod.gridLayout;
gridLayout.tblMainCont.appendChild(container);
container.className = gridLayout.infDivCssClass;
}
// default location: just above the table
else {
let cont = createElm('caption');
cont.appendChild(container);
tf.dom().insertBefore(cont, tf.dom().firstChild);
}
this.cont = container;
// left container
this.lCont = this.createContainer(container, this.lContCssClass);
// right container
this.rCont = this.createContainer(container, this.rContCssClass);
// middle container
this.cCont = this.createContainer(container, this.cContCssClass);
this.innerCont = {
left: this.lCont,
center: this.cCont,
right: this.rCont
};
/** @inherited */
this.initialized = true;
// emit help initialisation only if undefined
if (isUndef(tf.help)) {
// explicitily enable help to initialise feature by
// default, only if setting is undefined
tf.Mod.help.enable();
this.emitter.emit('init-help', tf);
}
}
/**
* Return the container based on requested position inside the toolbar
* @param {String} [position=RIGHT] 3 possible positions: 'left', 'center',
* 'right'
* @param {DOMElement} el optional DOM element to be inserter in container
* @returns {DOMElement}
*/
container(position = RIGHT, el) {
let cont = this.innerCont[position];
if (el) {
cont.appendChild(el);
}
return cont;
}
/**
* Create DOM element inside passed container
* @param {DOMElement} container
* @param {String} css
* @private
*/
createContainer(container, css) {
let div = createElm('div', ['class', css]);
container.appendChild(div);
return div;
}
/**
* Destroy Toolbar instance
*/
destroy() {
if (!this.initialized) {
return;
}
let tf = this.tf;
removeElm(this.cont);
this.cont = null;
let tbl = tf.dom();
let captions = tag(tbl, 'caption');
[].forEach.call(captions, (el) => removeElm(el));
/** @inherited */
this.initialized = false;
}
}
// TODO: remove as soon as feature name is fixed
Toolbar.meta = {alwaysInstantiate: true};

View file

@ -19,11 +19,14 @@ export const parse = (value, decimal = '.') => {
let regex = new RegExp('[^0-9-' + decimal + ']', ['g']); let regex = new RegExp('[^0-9-' + decimal + ']', ['g']);
let unformatted = parseFloat( let unformatted = parseFloat(
('' + value) ('' + value)
.replace(/\((.*)\)/, '-$1') // replace bracketed values with negatives // replace bracketed values with negatives
.replace(regex, '') // strip out any cruft .replace(/\((.*)\)/, '-$1')
.replace(decimal, '.') // make sure decimal point is standard // strip out any cruft
.replace(regex, '')
// make sure decimal point is standard
.replace(decimal, '.')
); );
// This will fail silently // This will fail silently
return !isNaN(unformatted) ? unformatted : 0; return !isNaN(unformatted) ? unformatted : 0;
} };

53
src/settings.js Normal file
View file

@ -0,0 +1,53 @@
import {isBoolean, isString, isFn, isArray} from './types';
/** Configuration settings helpers */
/**
* If passed value is not of boolean type return the default value
* otherwise return the value itself
* @param {Boolean|Any} value
* @param {Boolean} default value
* @return {Boolean|Any}
*/
export const defaultsBool =
(val, defaultVal) => isBoolean(val) ? val : defaultVal;
/**
* If passed value is not of string type return the default value
* otherwise return the value itself
* @param {String|Any} value
* @param {String} default value
* @return {String|Any}
*/
export const defaultsStr =
(val, defaultVal) => isString(val) ? val : defaultVal;
/**
* If passed value is not of number type return the default value
* otherwise return the value itself
* @param {Number|Any} value
* @param {Number} default value
* @return {Number|Any}
*/
export const defaultsNb =
(val, defaultVal) => isNaN(val) ? defaultVal : val;
/**
* If passed value is not of array type return the default value
* otherwise return the value itself
* @param {Array|Any} value
* @param {Array} default value
* @return {Array|Any}
*/
export const defaultsArr =
(val, defaultVal) => isArray(val) ? val : defaultVal;
/**
* If passed value is not of function type return the default value
* otherwise return the value itself
* @param {Function|Any} value
* @param {Function} default value
* @return {Function|Any}
*/
export const defaultsFn =
(val, defaultVal) => isFn(val) ? val : defaultVal;

View file

@ -1,6 +1,7 @@
/** import {parse as parseNb} from './number';
* Sorting utilities import {Date as SugarDate} from 'sugar-date';
*/
/** Sorting utilities */
/** /**
* Case insensitive compare function for passed strings * Case insensitive compare function for passed strings
@ -13,21 +14,69 @@
export const ignoreCase = (a, b) => { export const ignoreCase = (a, b) => {
let x = a.toLowerCase(); let x = a.toLowerCase();
let y = b.toLowerCase(); let y = b.toLowerCase();
return ((x < y) ? -1 : ((x > y) ? 1 : 0)); return x < y ? -1 : (x > y ? 1 : 0);
} };
/** /**
* Sorts passed numbers in a ascending manner * Compare function for sorting passed numbers in ascending manner
* @param {Number} First number * @param {Number} First number
* @param {Number} Second number * @param {Number} Second number
* @param {Number} Negative, zero or positive number * @return {Number} Negative, zero or positive number
*/ */
export const numSortAsc = (a, b) => (a - b); export const numSortAsc = (a, b) => (a - b);
/** /**
* Sorts passed numbers in a descending manner * Compare function for sorting passed numbers in descending manner
* @param {Number} First number * @param {Number} First number
* @param {Number} Second number * @param {Number} Second number
* @param {Number} Negative, zero or positive number * @return {Number} Negative, zero or positive number
*/ */
export const numSortDesc = (a, b) => (b - a); export const numSortDesc = (a, b) => (b - a);
/**
* Compare function for sorting passed dates in ascending manner according to
* the corresponding UTC numeric value (returned by getTime)
* @param {Date} First date object
* @param {Date} Second date object
* @return {Number} Negative, zero or positive number
*/
export const dateSortAsc = (date1, date2) => date1.getTime() - date2.getTime();
/**
* Compare function for sorting passed dates in descending manner according to
* the corresponding UTC numeric value (returned by getTime)
* @param {Date} First date object
* @param {Date} Second date object
* @return {Number} Negative, zero or positive number
*/
export const dateSortDesc = (date1, date2) => date2.getTime() - date1.getTime();
/**
* Curried compare function for sorting passed formatted numbers in desired
* fashion according to supplied compare function and decimal separator
* @param {Function} Compare function
* @param {String} [decimal=','] Decimal separator
* @return {Function} Compare function receiving parsed numeric arguments
*/
export const sortNumberStr = (compareFn, decimal = ',') => {
return (numStr1, numStr2) => {
let num1 = parseNb(numStr1, decimal);
let num2 = parseNb(numStr2, decimal);
return compareFn(num1, num2);
};
};
/**
* Curried compare function for sorting passed formatted dates in desired
* fashion according to supplied compare function and locale
* @param {Function} Compare function
* @param {String} [locale='en-us'] Locale code
* @return {Function} Compare function receiving parsed date arguments
*/
export const sortDateStr = (compareFn, locale = 'en-us') => {
return (dateStr1, dateStr2) => {
let date1 = SugarDate.create(dateStr1, locale);
let date2 = SugarDate.create(dateStr2, locale);
return compareFn(date1, date2);
};
};

View file

@ -14,7 +14,7 @@ export const trim = (text) => {
return text.trim(); return text.trim();
} }
return text.replace(/^\s*|\s*$/g, ''); return text.replace(/^\s*|\s*$/g, '');
} };
/** /**
* Checks if passed string is empty * Checks if passed string is empty
@ -32,7 +32,7 @@ export const rgxEsc = (text) => {
let chars = /[-\/\\^$*+?.()|[\]{}]/g; let chars = /[-\/\\^$*+?.()|[\]{}]/g;
let escMatch = '\\$&'; let escMatch = '\\$&';
return String(text).replace(chars, escMatch); return String(text).replace(chars, escMatch);
} };
/** /**
* Returns passed string as lowercase if caseSensitive flag set false. By * Returns passed string as lowercase if caseSensitive flag set false. By
@ -45,7 +45,7 @@ export const matchCase = (text, caseSensitive = false) => {
return text.toLowerCase(); return text.toLowerCase();
} }
return text; return text;
} };
/** /**
* Checks if passed data contains the searched term * Checks if passed data contains the searched term
@ -73,4 +73,40 @@ export const contains = (term, data, exactMatch = false, caseSensitive = false,
regexp = new RegExp(rgxEsc(term), modifier); regexp = new RegExp(rgxEsc(term), modifier);
} }
return regexp.test(data); return regexp.test(data);
} };
/**
* Camelize a string, cutting the string by multiple separators like
* hyphens, underscores and spaces.
* @param {String} text text to camelize
* @return {String} camelized text
*/
export const toCamelCase = (text = '') => {
return text.replace(/^([A-Z])|[\s-_]+(\w)/g, (match, p1, p2) => {
if (p2) {
return p2.toUpperCase();
}
return p1.toLowerCase();
});
};
/**
* Generate a string in the format of a UUID (Universally Unique IDentifier).
* NOTE: This format of 8 chars, followed by 3 groups of 4 chars, followed by 12
* chars is known as a UUID and is defined in RFC4122 and is a standard for
* generating unique IDs. This function DOES NOT implement this standard.
* It simply outputs a string that looks similar. The standard is found here:
* https://www.ietf.org/rfc/rfc4122.txt
* source: https://gist.github.com/gordonbrander/2230317
* @return {String}
*/
export const uuid = () => {
const chr4 = () => Math.random().toString(16).slice(-4);
return chr4() + chr4()
+ '-' + chr4()
+ '-' + chr4()
+ '-' + chr4()
+ '-' + chr4()
+ chr4() + chr4();
};

File diff suppressed because it is too large Load diff

View file

@ -37,7 +37,7 @@ export const isArray =
/** /**
* Check passed argument is a string * Check passed argument is a string
* @param {String} obj objue * @param {String} obj obj
* @returns {Boolean} * @returns {Boolean}
*/ */
export const isString = export const isString =
@ -51,6 +51,14 @@ export const isString =
export const isNumber = export const isNumber =
(obj) => Object.prototype.toString.call(obj) === '[object Number]'; (obj) => Object.prototype.toString.call(obj) === '[object Number]';
/**
* Check passed argument is a boolean
* @param {Boolean} obj
* @returns {Boolean}
*/
export const isBoolean =
(obj) => Object.prototype.toString.call(obj) === '[object Boolean]';
/** /**
* Check passed argument is undefined * Check passed argument is undefined
* @param {Any} obj * @param {Any} obj

File diff suppressed because it is too large Load diff

View file

@ -5,3 +5,6 @@
.activeHeader .activeHeader
background-color #66AFE9 !important background-color #66AFE9 !important
color #fff !important color #fff !important
.activeCell
background-color rgba(0,0,0,0.075)

View file

@ -34,7 +34,7 @@ div.colVisCont
z-index 10000 z-index 10000
padding 10px 10px 10px 10px padding 10px 10px 10px 10px
text-align left text-align left
font-size 12px font-size inherit
p p
margin 6px auto 6px auto margin 6px auto 6px auto
@ -47,7 +47,7 @@ div.colVisCont
ul.cols_checklist ul.cols_checklist
padding 0 padding 0
margin 0 margin 0
list-style none list-style-type none
label label
display block display block

View file

@ -11,7 +11,7 @@ $item-font-color = #fff
.div_checklist .div_checklist
width 100% width 100%
height 90px height 90px
line-height 24px line-height 30px
border 1px solid $filter-border-color border 1px solid $filter-border-color
overflow auto overflow auto
text-align left text-align left
@ -27,19 +27,20 @@ $item-font-color = #fff
li.flt_checklist_item li.flt_checklist_item
padding 1px !important padding 1px !important
margin 0 !important margin 0 !important
font-size 10px !important font-size inherit
border-bottom 1px solid $filter-border-color !important border-bottom 1px solid $filter-border-color !important
&:hover &:hover
background-color $item-bg-color !important background-color $item-bg-color !important
color $item-font-color !important; color $item-font-color !important
label label
display block !important; display block !important
font-weight inherit !important
input input
vertical-align middle !important; vertical-align middle !important
margin 2px 5px 2px 1px !important; margin 2px 5px 3px 1px !important
// disabled checklist item // disabled checklist item
.flt_checklist_item_disabled .flt_checklist_item_disabled

View file

@ -43,6 +43,7 @@
// input and select filter type // input and select filter type
.flt .flt
font-family inherit font-family inherit
font-size inherit
display block display block
color $filter-font-color color $filter-font-color
background-color $filter-bg-color background-color $filter-bg-color
@ -64,6 +65,7 @@
// multiple select type filter // multiple select type filter
select.flt_multi select.flt_multi
font-family inherit font-family inherit
font-size inherit
color $filter-font-color color $filter-font-color
background-color $filter-bg-color background-color $filter-bg-color
border 1px solid $filter-border-color border 1px solid $filter-border-color
@ -92,7 +94,7 @@ select.flt_multi
box-sizing initial box-sizing initial
display initial display initial
// Pop-up filters elements // pop-up filters elements
div.popUpFilter div.popUpFilter
arrow(top, 10px white, 2px $th-bg-color) arrow(top, 10px white, 2px $th-bg-color)
box-shadow(3px 3px 2px #888) box-shadow(3px 3px 2px #888)
@ -103,3 +105,7 @@ div.popUpFilter
background-color $th-bg-color background-color $th-bg-color
border 1px solid $filter-row-bg-color border 1px solid $filter-row-bg-color
padding 0 padding 0
// pop-up container
.popUpPlaceholder
position relative

View file

@ -11,7 +11,6 @@ div.grd_Cont
width 800px width 800px
height auto height auto
overflow hidden overflow hidden
padding 3px 3px 3px 3px
background-color $grid-layout-bg-color background-color $grid-layout-bg-color
border 1px solid $grid-layout-border-color border 1px solid $grid-layout-border-color
@ -50,8 +49,9 @@ div.grd_tblCont
// headers' table container // headers' table container
div.grd_headTblCont div.grd_headTblCont
display block
margin-right 20px
height auto height auto
width 800px
overflow hidden overflow hidden
border-bottom 1px solid $grid-layout-border-color border-bottom 1px solid $grid-layout-border-color
background-color $grid-layout-bg-color background-color $grid-layout-bg-color
@ -63,10 +63,6 @@ div.grd_headTblCont table
table-layout fixed table-layout fixed
box-sizing initial box-sizing initial
div.grd_tblCont table
border-right 1px solid $grid-layout-border-color
box-sizing initial
// headers // headers
div.grd_tblCont table th div.grd_tblCont table th
div.grd_headTblCont table th div.grd_headTblCont table th

View file

@ -32,6 +32,7 @@ div.helpCont
color #333 color #333
background #fff background #fff
text-align left text-align left
z-index 1000
a a
color #cc0000 color #cc0000

View file

@ -0,0 +1,7 @@
/**
* Empty content mixin
*/
empty-content()
&:empty:after
content "\00A0"

View file

@ -14,3 +14,8 @@ input.reset
&:hover &:hover
background-color $toolbar-hover-color background-color $toolbar-hover-color
a.reset
font-weight normal !important
line-height $min-height
padding 5px 5px

View file

@ -26,11 +26,19 @@ table.TF
margin 0 margin 0
padding $padding padding $padding
border-bottom 1px solid $td-border-color border-bottom 1px solid $td-border-color
text-overflow ellipsis
// responsiveness // responsive
&.resp &.resp
display block display block
overflow-x auto overflow-x auto
overflow-y hidden
.sort-arrow .sort-arrow
position initial position initial
// stick headers
&.sticky
th
position sticky
top -1px

View file

@ -0,0 +1,18 @@
/** Main stylesheet */
@import 'active-header'
@import 'alternating-rows'
@import 'ezedittable'
@import 'filter-checklist'
@import 'filters'
@import 'grid-layout'
@import 'help'
@import 'keyword'
@import 'loader'
@import 'noresults'
@import 'paging'
@import 'reset-button'
@import 'rows-counter'
@import 'sort'
@import 'status-bar'
@import 'table'
@import 'toolbar'

View file

@ -3,12 +3,14 @@
*/ */
@import 'config' @import 'config'
@import 'mixins/empty-content'
// left, middle and right divs container (toolbar) // left, middle and right divs container (toolbar)
.inf .inf
clear both clear both
width auto width auto
height $min-height height $min-height
min-width 400px
background-color $toolbar-bg-color background-color $toolbar-bg-color
font-size $toolbar-font-size font-size $toolbar-font-size
margin 0 margin 0
@ -32,25 +34,25 @@
// left div // left div
.ldiv .ldiv
empty-content()
float left float left
width 30% width 30%
// height 100%
position inherit position inherit
text-align left text-align left
// middle div // middle div
.mdiv .mdiv
empty-content()
float left float left
width 38% width 38%
// height 100%
position inherit position inherit
text-align center text-align center
padding 0 padding 0
// right div // right div
.rdiv .rdiv
empty-content()
float right float right
width 30% width 30%
// height 100%
position inherit position inherit
text-align right text-align right

View file

@ -49,8 +49,9 @@
<script data-config> <script data-config>
var filtersConfig = { var filtersConfig = {
base_path: '../dist/tablefilter/', base_path: '../dist/tablefilter/',
grid_layout: true, grid_layout: {
grid_width: '900px', width: '900px'
},
alternate_rows: true, alternate_rows: true,
btn_reset: true, btn_reset: true,
rows_counter: true, rows_counter: true,

View file

@ -19,15 +19,18 @@
<script data-config> <script data-config>
var filtersConfig = { var filtersConfig = {
base_path: '../dist/tablefilter/', base_path: '../dist/tablefilter/',
auto_filter: true, auto_filter: {
auto_filter_delay: 750, //milliseconds delay: 750 // milliseconds
},
filters_row_index: 1, filters_row_index: 1,
state: true, state: true,
alternate_rows: true, alternate_rows: true,
rows_counter: true, rows_counter: {
rows_counter_text: 'Rows: ', text: 'Rows: '
},
btn_reset: true, btn_reset: true,
status_bar: true, status_bar: true,
sticky_headers: true,
msg_filter: 'Filtering...' msg_filter: 'Filtering...'
}; };

View file

@ -39,8 +39,9 @@ var tfConfig = {
}, },
alternate_rows: true, alternate_rows: true,
rows_counter: true, rows_counter: true,
btn_reset: true, btn_reset: {
btn_reset_text: 'Clear', text: 'Clear'
},
status_bar: true, status_bar: true,
col_1: 'select', col_1: 'select',
col_2: 'select', col_2: 'select',

View file

@ -32,40 +32,6 @@ var id = function (id){
var table = id('demo-tot'); var table = id('demo-tot');
var totRowIndex = table.getElementsByTagName('tr').length; var totRowIndex = table.getElementsByTagName('tr').length;
function addCommas(nStr){
nStr += '';
var x = nStr.split('.');
var x1 = x[0];
var x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + ',' + '$2');
}
return x1 + x2;
}
function addDots(nStr){
nStr += '';
var x = nStr.split('.');
var x1 = x[0];
var x2 = x.length > 1 ? ',' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + '.' + '$2');
}
return x1 + x2;
}
function formatTotals(){
var tot1 = id('sum1').innerHTML;
tot1 = addDots(tot1);
id('sum1').innerHTML = tot1;
var tot2 = id('sum2').innerHTML;
tot2 = addCommas(tot2);
id('sum2').innerHTML = tot2;
}
/* EXAMPLE 1 /* EXAMPLE 1
*********************** */ *********************** */
var tfConfig = { var tfConfig = {
@ -107,7 +73,10 @@ var tfConfig = {
exclude_row: [totRowIndex], exclude_row: [totRowIndex],
decimal_precision: [2, 2], decimal_precision: [2, 2],
tot_row_index: [totRowIndex], tot_row_index: [totRowIndex],
on_after_operation: formatTotals format_result: [
{ prefix: '€ ' },
{ prefix: '$ ' }
]
} }
] ]
}; };

View file

@ -23,9 +23,10 @@
btn_reset: true, btn_reset: true,
loader: true, loader: true,
status_bar: true, status_bar: true,
mark_active_columns: true, mark_active_columns: {
highlight_column: true
},
no_results_message: true, no_results_message: true,
responsive: true,
custom_options: { custom_options: {
cols:[3], cols:[3],
texts: [ texts: [
@ -46,8 +47,8 @@
}, },
col_widths: [ col_widths: [
'150px', '100px', '100px', '150px', '100px', '100px',
'70px', '70px', '70px', '90px', '90px', '90px',
'70px', '60px', '60px' '90px', '70px', '70px'
], ],
extensions:[{ name: 'sort' }] extensions:[{ name: 'sort' }]
}; };

View file

@ -82,8 +82,9 @@
var tfConfig = { var tfConfig = {
base_path: '../dist/tablefilter/', base_path: '../dist/tablefilter/',
alternate_rows: true, alternate_rows: true,
rows_counter: true, rows_counter: {
rows_counter_text: "Displayed rows: ", text: 'Displayed rows: '
},
loader: true, loader: true,
status: true, status: true,
status_bar: true, status_bar: true,
@ -105,8 +106,7 @@ var tfConfig = {
col_8: "none", col_8: "none",
/* external filters */ /* external filters */
external_flt_grid: true, external_flt_ids: [
external_flt_grid_ids: [
'slcCountry', 'slcCountry',
'slcCode', 'slcCode',
'slcYear', 'slcYear',

View file

@ -26,8 +26,9 @@ var tfConfig = {
'string', 'string', 'string', 'string', 'string', 'string',
'number', 'string', 'string', 'date' 'number', 'string', 'string', 'date'
], ],
rows_counter: true, rows_counter: {
rows_counter_text: 'Books: ', text: 'Books: '
},
alternate_rows: true, alternate_rows: true,
btn_reset: true, btn_reset: true,
@ -36,10 +37,10 @@ var tfConfig = {
col_4: 'select', col_4: 'select',
col_5: 'select', col_5: 'select',
/* custom_cell_data delegate used for filtering /* cell parser for filtering images in a column */
images in a column */ cell_parser: {
custom_cell_data_cols: [0, 4], cols: [0, 4],
custom_cell_data: function(o, cell, colIndex){ parse: function(o, cell, colIndex){
if(colIndex === 0){ if(colIndex === 0){
var img = cell.getElementsByTagName('img')[0]; var img = cell.getElementsByTagName('img')[0];
if(!img){ if(!img){
@ -54,6 +55,7 @@ var tfConfig = {
return 'no'; return 'no';
} }
} }
}
}, },
/* Custom options for 'Shipping' column */ /* Custom options for 'Shipping' column */

View file

@ -22,7 +22,7 @@ var tfConfig = {
col_2: 'checklist', col_2: 'checklist',
col_widths: [ col_widths: [
'75px', '200px', '200px', '75px', '200px', '200px',
'100px', '75px', '' '100px', '75px', '400px'
], ],
paging: true, paging: true,
alternate_rows: true, alternate_rows: true,

View file

@ -22,6 +22,9 @@
loader: true, loader: true,
status_bar: true, status_bar: true,
no_results_message: true, no_results_message: true,
mark_active_columns: {
highlight_column: true
},
col_1: 'select', col_1: 'select',
col_2: 'select', col_2: 'select',
col_widths: [ col_widths: [

View file

@ -58,8 +58,9 @@ var tfConfig = {
rows_counter: true, rows_counter: true,
btn_reset: true, btn_reset: true,
status_bar: true, status_bar: true,
paging: true, paging: {
paging_length: 15, length: 15
},
enable_empty_option: true, enable_empty_option: true,
enable_non_empty_option: true, enable_non_empty_option: true,
enable_default_theme: true, enable_default_theme: true,

View file

@ -20,14 +20,15 @@ var tfConfig = {
base_path: '../dist/tablefilter/', base_path: '../dist/tablefilter/',
col_widths: [ col_widths: [
'150px', '100px', '100px', '150px', '100px', '100px',
'70px', '70px', '70px', '100px', '100px', '100px',
'70px', '60px', '60px' '90px', '90px', '90px'
], ],
alternate_rows: true, alternate_rows: true,
rows_counter: true, rows_counter: true,
btn_reset: true, btn_reset: true,
status_bar: true, status_bar: true,
load_filters_on_demand: true, load_filters_on_demand: true,
sticky_headers: true,
col_0: 'multiple', col_0: 'multiple',
col_1: 'select', col_1: 'select',
col_2: 'checklist' col_2: 'checklist'

View file

@ -30,8 +30,9 @@
<script data-config> <script data-config>
var filtersConfig = { var filtersConfig = {
base_path: '../dist/tablefilter/', base_path: '../dist/tablefilter/',
paging: true, paging: {
results_per_page: ['Records: ', [10,25,50,100]], results_per_page: ['Records: ', [10, 25, 50, 100]]
},
state: { state: {
types: ['local_storage'], types: ['local_storage'],
filters: true, filters: true,
@ -39,15 +40,21 @@
page_length: true, page_length: true,
sort: true sort: true
}, },
responsive: true,
help_instructions: {
container_adjust_left_position: 30
},
alternate_rows: true, alternate_rows: true,
btn_reset: true, btn_reset: true,
rows_counter: true, rows_counter: true,
loader: true, loader: {
loader_html: '<div id="lblMsg"></div>', html: '<div id="lblMsg"></div>',
loader_css_class: 'myLoader', css_class: 'myLoader'
status_bar: true, },
status_bar_target_id: 'lblMsg', status_bar: {
status_bar_css_class: 'myStatus', target_id: 'lblMsg',
css_class: 'myStatus'
},
no_results_message: true, no_results_message: true,
col_0: 'select', col_0: 'select',
col_1: 'select', col_1: 'select',

View file

@ -1,69 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>{NAME} v{VERSION} - Development workflow with RequireJs</title>
<!-- @import partials/style.html -->
</head>
<body>
<h1>{NAME} v{VERSION}</h1>
<h2>Development workflow with RequireJs</h2>
<p>
To take advantage of the RequireJs development workflow use the
<code>grunt dev-modules</code> command.
</p>
<p>
If you use extensions, you will need to specify the extensions path as per
configuration example. Sorting feature also requires the third-party
<code>../libs/sortabletable</code> dependency to be imported.
</p>
<!-- @import partials/pre.html -->
<!-- @import partials/countries-by-continent.html -->
<script src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.17/require.min.js"></script>
<script data-config>
requirejs(
['../dist/tablefilter/tablefilter', '../libs/sortabletable'],
function(mod){
var TableFilter = mod.TableFilter;
var tfConfig = {
base_path: '../dist/tablefilter/',
col_1: 'multiple',
col_2: 'checklist',
alternate_rows: true,
rows_counter: true,
enable_default_theme: true,
col_widths: [
'70px', '170px', '170px',
'110px', '90px', '250px'
],
extensions:[
{
name: 'sort',
path: '../dist/tablefilter/extensions/sort/',
types: [
'number', 'string', 'string',
'US', 'none', 'string'
]
},
{
name: 'colsVisibility',
path: '../dist/tablefilter/extensions/colsVisibility/'
},
{
name: 'filtersVisibility',
path: '../dist/tablefilter/extensions/filtersVisibility/'
}
]
};
tf = new TableFilter('demo', tfConfig);
tf.init();
}
);
</script>
<!-- @import partials/pre-inline-script.html -->
</body>
</html>

View file

@ -43,7 +43,7 @@
}, },
col_widths: [ col_widths: [
'150px', '100px', '100px', '150px', '100px', '100px',
'70px', '70px', '70px', '100px', '100px', '100px',
'70px', '60px', '60px' '70px', '60px', '60px'
], ],
extensions:[{ name: 'sort' }] extensions:[{ name: 'sort' }]

View file

@ -35,19 +35,23 @@ var tfConfig = {
'string', 'string', 'number', 'string', 'string', 'number',
'string', 'string', 'date' 'string', 'string', 'date'
], ],
rows_counter: true, rows_counter: {
rows_counter_text: 'Books: ', text: 'Books: '
},
alternate_rows: true, alternate_rows: true,
btn_reset: true, btn_reset: true,
mark_active_columns: true, mark_active_columns: {
highlight_column: true
},
/* Filter types*/ /* Filter types*/
col_3: 'select', col_3: 'select',
col_4: 'select', col_4: 'select',
/* delegate for filtering 'In store' column */ /* cell parser for 'In store' column */
custom_cell_data_cols: [3], cell_parser: {
custom_cell_data: function(o, cell, colIndex){ cols: [3],
parse: function(o, cell, colIndex){
if(colIndex === 3){ if(colIndex === 3){
var chk = cell.getElementsByTagName('input')[0]; var chk = cell.getElementsByTagName('input')[0];
if(!chk){ if(!chk){
@ -59,6 +63,7 @@ var tfConfig = {
return 'no'; return 'no';
} }
} }
}
}, },
/* Custom options for 'Shipping' column */ /* Custom options for 'Shipping' column */

View file

@ -6,12 +6,72 @@
mark_active_columns: true mark_active_columns: true
}); });
tf.init(); tf.init();
var markActiveColumns = tf.feature('markActiveColumns');
module('Sanity checks'); module('Sanity checks');
test('Active columns', function() { test('Active columns', function() {
deepEqual(tf instanceof TableFilter, true, 'TableFilter instanciated'); deepEqual(tf instanceof TableFilter, true, 'TableFilter instanciated');
notEqual(markActiveColumns, null, 'markActiveColumns instanciated');
deepEqual(tf.markActiveColumns, true, 'markActiveColumns property');
equal(markActiveColumns.emitter.events['before-filtering'].length, 1,
'subscribed to `before-filtering` event');
equal(markActiveColumns.emitter.events['cell-processed'].length, 1,
'subscribed to `cell-processed` event');
}); });
module('Feature interface');
test('Properties', function() {
deepEqual(markActiveColumns.tf instanceof TableFilter, true,
'TableFilter instance');
deepEqual(markActiveColumns.feature, 'markActiveColumns',
'Feature name');
deepEqual(markActiveColumns.enabled, true, 'Feature enabled');
deepEqual(markActiveColumns.initialized, true, 'Feature initialized');
deepEqual(typeof markActiveColumns.emitter, 'object',
'Feature has emitter instance');
deepEqual(typeof markActiveColumns.config, 'object',
'TF configuration object');
deepEqual(typeof markActiveColumns.init, 'function',
'Feature init method');
deepEqual(typeof markActiveColumns.destroy, 'function',
'Feature destroy method');
deepEqual(typeof markActiveColumns.reset, 'function',
'Feature reset method');
deepEqual(typeof markActiveColumns.enable, 'function',
'Feature enable method');
deepEqual(typeof markActiveColumns.disable, 'function',
'Feature enable method');
deepEqual(typeof markActiveColumns.isEnabled, 'function',
'Feature enable method');
});
test('Can destroy', function() {
markActiveColumns.destroy();
deepEqual(markActiveColumns.initialized, false, 'not initialised');
});
test('Can reset', function() {
markActiveColumns.reset();
deepEqual(markActiveColumns.enabled, true, 'enabled');
});
test('Can disable', function() {
markActiveColumns.disable();
deepEqual(markActiveColumns.enabled, false, 'disabled');
});
test('Can enable', function() {
markActiveColumns.enable();
deepEqual(markActiveColumns.enabled, true, 'enabled');
});
test('Can init', function() {
markActiveColumns.destroy();
markActiveColumns.enable();
markActiveColumns.init();
deepEqual(markActiveColumns.enabled, true, 'enabled');
});
test('Can check is enabled', function() {
markActiveColumns.isEnabled();
deepEqual(markActiveColumns.enabled, true, 'enabled');
});
module('Behaviour');
test('Active columns', function() { test('Active columns', function() {
tf.setFilterValue(1, 'Bri'); tf.setFilterValue(1, 'Bri');
tf.setFilterValue(3, '>2'); tf.setFilterValue(3, '>2');
@ -28,6 +88,59 @@
'Active filter indicator'); 'Active filter indicator');
}); });
test('can highlight column cells', function() {
// setup
tf.clearFilters();
var markActiveColumns = tf.feature('markActiveColumns');
markActiveColumns.highlightColumn = true;
// act
tf.setFilterValue(3, '>2');
tf.filter();
// assert
deepEqual(tf.dom().rows[6].cells[3].className,
markActiveColumns.cellCssClass, 'cell has expected css class');
deepEqual(
tf.dom()
.querySelectorAll('.' + markActiveColumns.cellCssClass).length,
7,
'number of highlighted column cells'
);
});
test('can unhighlight column cells', function() {
// act
tf.clearFilters();
// assert
deepEqual(
tf.dom()
.querySelectorAll('.' + markActiveColumns.cellCssClass).length,
0,
'number of highlighted column cells'
);
markActiveColumns.highlightColumn = false;
});
test('cannot initialiase if already initialised', function() {
// setup
var hit = 0;
var emitterOn = markActiveColumns.emitter.on;
markActiveColumns.emitter.on = function() {
hit++;
};
// act
markActiveColumns.init();
// assert
deepEqual(hit, 0, 'init exited');
markActiveColumns.emitter.on = emitterOn;
});
test('Active columns with paging', function() { test('Active columns with paging', function() {
tf.destroy(); tf.destroy();
tf = null; tf = null;
@ -76,8 +189,130 @@
header3.className.indexOf('activeHeader') !== -1, header3.className.indexOf('activeHeader') !== -1,
true, true,
'Active filter indicator'); 'Active filter indicator');
});
test('Cannot destroy if not initialised', function() {
// setup
var clearActiveColumns = markActiveColumns.clearActiveColumns;
var hit = 0;
markActiveColumns.clearActiveColumns = function() { hit++; };
markActiveColumns.initialized = false;
// act
markActiveColumns.destroy();
// assert
deepEqual(hit, 0, 'clearActiveColumns not called');
markActiveColumns.clearActiveColumns = clearActiveColumns;
});
module('Callbacks');
test('Can trigger onBeforeActiveColumn callback', function() {
// setup
var colIndex;
markActiveColumns.onBeforeActiveColumn = function(feature, colIdx) {
colIndex = colIdx;
};
// act
markActiveColumns.markActiveColumn(2);
// assert
deepEqual(colIndex, 2,
'expected column index passed to onBeforeActiveColumn');
});
test('Can trigger onAfterActiveColumn callback', function() {
// setup
var colIndex;
markActiveColumns.onAfterActiveColumn = function(feature, colIdx) {
colIndex = colIdx;
};
// act
markActiveColumns.markActiveColumn(3);
// assert
deepEqual(colIndex, 3,
'expected column index passed to onAfterActiveColumn');
});
module('mark_active_columns as configuration object');
test('Sanity checks', function() {
tf.destroy(); tf.destroy();
var hit = 0;
tf = new TableFilter('demo', {
base_path: '../dist/tablefilter/',
mark_active_columns: {
header_css_class: 'myCssClass',
on_before_active_column: function(feature, colIndex) {
hit = colIndex;
},
on_after_active_column: function(feature, colIndex) {
hit = colIndex;
}
}
});
tf.init();
var markActiveColumns = tf.feature('markActiveColumns');
deepEqual(tf instanceof TableFilter, true, 'TableFilter instanciated');
notEqual(markActiveColumns, null, 'markActiveColumns instanciated');
deepEqual(tf.markActiveColumns, true, 'markActiveColumns property');
test('Custom header CSS class', function() {
// setup
tf.setFilterValue(1, 'Bri');
tf.setFilterValue(3, '>2');
var header1 = tf.getHeaderElement(1);
var header3 = tf.getHeaderElement(3);
// act
tf.filter();
// assert
deepEqual(
header1.className.indexOf('myCssClass') !== -1,
true,
'Active filter indicator');
deepEqual(
header3.className.indexOf('myCssClass') !== -1,
true,
'Active filter indicator');
});
test('on_before_active_column callback', function() {
// setup
tf.clearFilters();
tf.setFilterValue(1, 'Bri');
// act
tf.filter();
// assert
deepEqual(hit, 1,
'expected column index passed to on_before_active_column');
});
test('on_after_active_column callback', function() {
// setup
tf.clearFilters();
tf.setFilterValue(3, '>2');
// act
tf.filter();
// assert
deepEqual(hit, 3,
'expected column index passed to on_after_active_column');
});
module('Tear-down');
test('can destroy', function() {
tf.destroy();
deepEqual(tf.isInitialized(), false, 'Filters removed');
});
}); });
})(window, TableFilter); })(window, TableFilter);

View file

@ -4,7 +4,7 @@ var tf = new TableFilter('demo', {
alternate_rows: true alternate_rows: true
}); });
tf.init(); tf.init();
var tbl = tf.tbl; var tbl = tf.dom();
var altRows = tf.feature('alternateRows'); var altRows = tf.feature('alternateRows');
module('Sanity checks'); module('Sanity checks');
@ -91,8 +91,8 @@ test('Clear filters', function() {
tf.clearFilters(); tf.clearFilters();
tf.filter(); tf.filter();
deepEqual(tbl.querySelectorAll('tr.odd').length, 3, 'Odd bgs removed'); deepEqual(tbl.querySelectorAll('tr.odd').length, 4, 'Odd bgs removed');
deepEqual(tbl.querySelectorAll('tr.even').length, 4, 'Even bg removed'); deepEqual(tbl.querySelectorAll('tr.even').length, 3, 'Even bg removed');
}); });
test('Set background on a row', function() { test('Set background on a row', function() {
@ -110,7 +110,7 @@ test('Cannot init if initialised', function() {
// setup // setup
var processAll = altRows.processAll; var processAll = altRows.processAll;
var hit = 0; var hit = 0;
altRows.processAll = function() { hit++ }; altRows.processAll = function() { hit++; };
altRows.initialized = true; altRows.initialized = true;
// act // act
@ -126,7 +126,7 @@ test('Cannot processAll if not enabled', function() {
// setup // setup
var setRowBg = altRows.setRowBg; var setRowBg = altRows.setRowBg;
var hit = 0; var hit = 0;
altRows.setRowBg = function() { hit++ }; altRows.setRowBg = function() { hit++; };
altRows.enabled = false; altRows.enabled = false;
// act // act
@ -142,7 +142,7 @@ test('Cannot setRowBg if not enabled', function() {
// setup // setup
var removeRowBg = altRows.removeRowBg; var removeRowBg = altRows.removeRowBg;
var hit = 0; var hit = 0;
altRows.removeRowBg = function() { hit++ }; altRows.removeRowBg = function() { hit++; };
altRows.enabled = false; altRows.enabled = false;
// act // act
@ -171,7 +171,7 @@ test('Cannot destroy if not initialised', function() {
// setup // setup
var getRowsNb = altRows.tf.getRowsNb; var getRowsNb = altRows.tf.getRowsNb;
var hit = 0; var hit = 0;
altRows.tf.getRowsNb = function() { hit++ }; altRows.tf.getRowsNb = function() { hit++; };
altRows.initialized = false; altRows.initialized = false;
// act // act
@ -242,42 +242,6 @@ test('Can handle `row-paged` event', function() {
altRows.processRow = processRow; altRows.processRow = processRow;
}); });
test('Can handle `column-sorted` event', function() {
// setup
var processAll = altRows.processAll;
var hit = 0;
altRows.processAll = function() {
hit++;
};
// act
altRows.init();
tf.emitter.emit('column-sorted');
// assert
deepEqual(hit, 1, 'processAll called');
altRows.processAll = processAll;
});
test('Can handle `rows-changed` event', function() {
// setup
var processAll = altRows.processAll;
var hit = 0;
altRows.processAll = function() {
hit++;
};
// act
altRows.init();
tf.emitter.emit('rows-changed');
// assert
deepEqual(hit, 1, 'processAll called');
altRows.processAll = processAll;
});
module('Grid layout'); module('Grid layout');
test('Grid layout: initialising alternating rows', function() { test('Grid layout: initialising alternating rows', function() {
tf.destroy(); tf.destroy();
@ -288,7 +252,7 @@ test('Grid layout: initialising alternating rows', function() {
alternate_rows: true alternate_rows: true
}); });
tf.init(); tf.init();
tbl = tf.tbl; tbl = tf.dom();
altRows = tf.feature('alternateRows'); altRows = tf.feature('alternateRows');
deepEqual( deepEqual(
@ -309,8 +273,8 @@ test('Grid layout: clear filters', function() {
tf.clearFilters(); tf.clearFilters();
tf.filter(); tf.filter();
deepEqual(tbl.querySelectorAll('tr.odd').length, 3, 'Odd bgs removed'); deepEqual(tbl.querySelectorAll('tr.odd').length, 4, 'Odd bgs removed');
deepEqual(tbl.querySelectorAll('tr.even').length, 4, 'Even bg removed'); deepEqual(tbl.querySelectorAll('tr.even').length, 3, 'Even bg removed');
}); });
test('Grid layout: set background on a row', function() { test('Grid layout: set background on a row', function() {
@ -352,7 +316,7 @@ test('Sort: alternating rows with column sorted at start', function() {
deepEqual(altRows.oddCss, 'odd', 'Expected odd css class'); deepEqual(altRows.oddCss, 'odd', 'Expected odd css class');
function checkAlternateRows(tf) { function checkAlternateRows(tf) {
tbl = tf.tbl; tbl = tf.dom();
altRows = tf.feature('alternateRows'); altRows = tf.feature('alternateRows');
test('Alternate rows with sort column at start option', function() { test('Alternate rows with sort column at start option', function() {

View file

@ -1,115 +0,0 @@
(function(win, TableFilter){
var tf = new TableFilter('demo', {
base_path: '../dist/tablefilter/',
rows_always_visible: [4, 9]
});
tf.init();
module('Sanity checks');
test('Always visible rows', function() {
deepEqual(tf instanceof TableFilter, true, 'TableFilter type');
deepEqual(tf.hasVisibleRows, true, 'Contains always visible rows');
});
module('Behaviour');
test('for filtered table', function() {
tf.setFilterValue(0, 'Hello');
tf.filter();
var alwaysVisibleRow1 = tf.tbl.rows[4];
var alwaysVisibleRow2 = tf.tbl.rows[9];
deepEqual(
tf.getRowDisplay(alwaysVisibleRow1),
'',
'Row display for alwaysVisibleRow1'
);
deepEqual(
tf.getRowDisplay(alwaysVisibleRow2),
'',
'Row display for alwaysVisibleRow2'
);
});
test('after filters are cleared', function() {
tf.clearFilters();
var alwaysVisibleRow1 = tf.tbl.rows[4];
var alwaysVisibleRow2 = tf.tbl.rows[9];
deepEqual(
tf.getRowDisplay(alwaysVisibleRow1),
'',
'Row display for alwaysVisibleRow1'
);
deepEqual(
tf.getRowDisplay(alwaysVisibleRow2),
'',
'Row display for alwaysVisibleRow2'
);
testPaging();
});
function testPaging(){
tf.destroy();
tf = new TableFilter('demo', {
base_path: '../dist/tablefilter/',
rows_always_visible: [4, 9],
paging: true,
paging_length: 2
});
tf.init();
var paging = tf.feature('paging');
module('Behaviour with paging');
test('for filtered table', function() {
tf.setFilterValue(0, 'Hello');
tf.filter();
var alwaysVisibleRow1 = tf.tbl.rows[4];
var alwaysVisibleRow2 = tf.tbl.rows[9];
deepEqual(
tf.getRowDisplay(alwaysVisibleRow1),
'',
'Row display for alwaysVisibleRow1'
);
deepEqual(
tf.getRowDisplay(alwaysVisibleRow2),
'',
'Row display for alwaysVisibleRow2'
);
});
test('after filters are cleared', function() {
tf.clearFilters();
var alwaysVisibleRow1 = tf.tbl.rows[4];
var alwaysVisibleRow2 = tf.tbl.rows[9];
deepEqual(
tf.getRowDisplay(alwaysVisibleRow1),
'none',
'Row display for alwaysVisibleRow1'
);
deepEqual(
tf.getRowDisplay(alwaysVisibleRow2),
'none',
'Row display for alwaysVisibleRow2'
);
});
test('after changing pagination page', function() {
paging.setPage(2);
var alwaysVisibleRow1 = tf.tbl.rows[4];
var alwaysVisibleRow2 = tf.tbl.rows[9];
deepEqual(
tf.getRowDisplay(alwaysVisibleRow1),
'',
'Row display for alwaysVisibleRow1'
);
deepEqual(
tf.getRowDisplay(alwaysVisibleRow2),
'none',
'Row display for alwaysVisibleRow2'
);
tf.destroy();
});
}
})(window, TableFilter);

View file

@ -14,6 +14,14 @@ var tf1 = new TableFilter('demo1', {
on_loaded: colsVisibilityTests on_loaded: colsVisibilityTests
}] }]
}); });
tf1.registerExtension(
{
init: function() {},
destroy: function() {}
},
'myExtension'
);
tf1.init(); tf1.init();
module('Sanity checks'); module('Sanity checks');
@ -28,6 +36,7 @@ test('TableFilter object', function() {
deepEqual(tf.getFilterId(0), 'flt0_demo', 'Filter DOM element id'); deepEqual(tf.getFilterId(0), 'flt0_demo', 'Filter DOM element id');
deepEqual(tf.getStartRowIndex(), 2, 'Start of filterable rows'); deepEqual(tf.getStartRowIndex(), 2, 'Start of filterable rows');
deepEqual(tf.getLastRowIndex(), 8, 'Last row index'); deepEqual(tf.getLastRowIndex(), 8, 'Last row index');
deepEqual(tf.dom().nodeName, 'TABLE', 'Working DOM element type');
deepEqual( deepEqual(
tf.getHeadersText(), tf.getHeadersText(),
[ [
@ -42,7 +51,7 @@ test('TableFilter object', function() {
); );
deepEqual(tf.getValidRowsNb(), 0, 'Number of valid rows before filtering'); deepEqual(tf.getValidRowsNb(), 0, 'Number of valid rows before filtering');
deepEqual( deepEqual(
tf.getCellData(tf.tbl.rows[3].cells[2]), tf.getCellData(tf.dom().rows[3].cells[2]),
982, 982,
'getCellData returns typed value' 'getCellData returns typed value'
); );
@ -128,6 +137,21 @@ test('Activate filter for a specified column', function() {
deepEqual(tf.getActiveFilterId(), filterId, 'Filter active'); deepEqual(tf.getActiveFilterId(), filterId, 'Filter active');
}); });
test('Activate filter not called if colIndex not a number', function() {
//set
var originalSetActiveFilterId = tf.setActiveFilterId;
var hit = 0;
tf.setActiveFilterId = function() { hit++; };
//act
tf.activateFilter(undefined);
//assert
deepEqual(hit, 0, 'setActiveFilterId never called');
tf.setActiveFilterId = originalSetActiveFilterId;
});
test('Clear filters', function() { test('Clear filters', function() {
tf.clearFilters(); tf.clearFilters();
deepEqual(tf.getValidRowsNb(), 7, 'Filtered rows number'); deepEqual(tf.getValidRowsNb(), 7, 'Filtered rows number');
@ -140,6 +164,27 @@ test('Can get feature', function() {
deepEqual(feature.feature, 'help', 'Feature name'); deepEqual(feature.feature, 'help', 'Feature name');
}); });
test('can iterate columns', function() {
// setup
var counter = [];
// act
tf.eachCol(
function(idx) {
counter.push(idx);
},
function(idx) {
return idx === 2;
},
function(idx) {
return idx === 4;
}
);
// assert
deepEqual(counter, [0, 1, 3], 'column iterator conditions met');
});
test('Get table data', function() { test('Get table data', function() {
deepEqual(tf.getColValues(0), deepEqual(tf.getColValues(0),
[ [
@ -204,7 +249,7 @@ test('Get table data', function() {
tf.setFilterValue(0, 'Adelaide'); tf.setFilterValue(0, 'Adelaide');
tf.filter(); tf.filter();
deepEqual( deepEqual(
tf.getFilteredData(), tf.getFilteredValues(),
[ [
[6, ['Adelaide','Perth','2781','3.1','38']], [6, ['Adelaide','Perth','2781','3.1','38']],
[7, ['Adelaide','Alice Springs','1533','2','20.25']], [7, ['Adelaide','Alice Springs','1533','2','20.25']],
@ -213,7 +258,7 @@ test('Get table data', function() {
'Get filtered table data' 'Get filtered table data'
); );
deepEqual( deepEqual(
tf.getFilteredData(true), tf.getFilteredValues(true),
[ [
[1, ['From','Destination','Road Distance (km)', [1, ['From','Destination','Road Distance (km)',
'By Air (hrs)','By Rail (hrs)']], 'By Air (hrs)','By Rail (hrs)']],
@ -221,10 +266,10 @@ test('Get table data', function() {
[7, ['Adelaide','Alice Springs','1533','2','20.25']], [7, ['Adelaide','Alice Springs','1533','2','20.25']],
[8, ['Adelaide','Brisbane','2045','2.15','40']] [8, ['Adelaide','Brisbane','2045','2.15','40']]
], ],
'Get filtered table data including columns headers' 'Get filtered table values including columns headers'
); );
deepEqual( deepEqual(
tf.getFilteredData(false, false, true), tf.getFilteredData(),
[ [
[6, ['Adelaide','Perth',2781,3.1,38]], [6, ['Adelaide','Perth',2781,3.1,38]],
[7, ['Adelaide','Alice Springs',1533,2,20.25]], [7, ['Adelaide','Alice Springs',1533,2,20.25]],
@ -247,6 +292,46 @@ test('Get table data', function() {
[2781,1533,2045], [2781,1533,2045],
'Get specified column filtered typed values' 'Get specified column filtered typed values'
); );
deepEqual(
tf.getFilteredColumnData(2),
[2781,1533,2045],
'Get filtered column data'
);
deepEqual(
tf.getFilteredColumnData(2, true),
['Road Distance (km)',2781,1533,2045],
'Get filtered column data with headers'
);
deepEqual(
tf.getVisibleColumnData(2),
[2781,1533,2045],
'Get visible column data'
);
deepEqual(
tf.getVisibleColumnData(2, true),
['Road Distance (km)',2781,1533,2045],
'Get visible column data with headers'
);
deepEqual(
tf.getFilteredColumnValues(2),
['2781','1533','2045'],
'Get filtered column data'
);
deepEqual(
tf.getFilteredColumnValues(2, true),
['Road Distance (km)','2781','1533','2045'],
'Get filtered column data with headers'
);
deepEqual(
tf.getVisibleColumnValues(2),
['2781','1533','2045'],
'Get visible column data'
);
deepEqual(
tf.getVisibleColumnValues(2, true),
['Road Distance (km)','2781','1533','2045'],
'Get visible column data with headers'
);
tf.clearFilters(); tf.clearFilters();
tf.filter(); tf.filter();
}); });
@ -264,7 +349,8 @@ test('Test filter types', function() {
base_path: '../dist/tablefilter/', base_path: '../dist/tablefilter/',
col_0: 'select', col_0: 'select',
col_1: 'multiple', col_1: 'multiple',
col_2: 'checklist' col_2: 'checklist',
col_types: ['string', 'string', 'number', 'number', 'number']
}); });
tf.init(); tf.init();
@ -338,17 +424,28 @@ test('Can select checklist options with array', function() {
tf.setFilterValue(2, ''); tf.setFilterValue(2, '');
tf.setFilterValue(2, ['1412', '982']); tf.setFilterValue(2, ['1412', '982']);
deepEqual(tf.getFilterValue(2), ['1412', '982'], deepEqual(tf.getFilterValue(2), ['982', '1412'],
'Column 2 filter values'); 'Column 2 filter values');
}); });
test('get and set filter value can handle out of range column index',
function() {
// act
tf.setFilterValue(11, '');
// assert
deepEqual(tf.getFilterValue(11), '',
'return empty string for inexistent filter');
});
module('TableFilter with pop-up filters'); module('TableFilter with pop-up filters');
test('Sanity checks', function() { test('Sanity checks', function() {
tf.destroy(); tf.destroy();
tf = null; tf = null;
tf = new TableFilter('demo', { tf = new TableFilter('demo', {
base_path: '../dist/tablefilter/', base_path: '../dist/tablefilter/',
popup_filters: true popup_filters: true,
col_types: ['string', 'string', 'number', 'number', 'number']
}); });
tf.init(); tf.init();
@ -396,7 +493,8 @@ test('Sanity checks', function() {
grid_layout: true, grid_layout: true,
col_0: 'select', col_0: 'select',
col_1: 'multiple', col_1: 'multiple',
col_2: 'checklist' col_2: 'checklist',
col_types: ['string', 'string', 'number', 'number', 'number']
}); });
tf.init(); tf.init();
@ -456,6 +554,28 @@ test('Get table data', function() {
], ],
'Get specified column values including column header' 'Get specified column values including column header'
); );
deepEqual(tf.getColumnValues(0),
[
'Sydney','Sydney','Sydney',
'Sydney','Adelaide','Adelaide','Adelaide'
],
'Get specified column values'
);
deepEqual(tf.getColumnValues(0, true),
[
'From','Sydney','Sydney','Sydney',
'Sydney','Adelaide','Adelaide','Adelaide'
],
'Get specified column values including column header'
);
deepEqual(tf.getColumnData(2),
[1412, 982, 286, 872, 2781, 1533, 2045],
'Get specified column data'
);
deepEqual(tf.getColumnData(2, true),
['Road Distance (km)', 1412, 982, 286, 872, 2781, 1533, 2045],
'Get specified column data including column header'
);
deepEqual( deepEqual(
tf.getTableData(), tf.getTableData(),
[ [
@ -467,22 +587,49 @@ test('Get table data', function() {
[5, ['Adelaide','Alice Springs','1533','2','20.25']], [5, ['Adelaide','Alice Springs','1533','2','20.25']],
[6, ['Adelaide','Brisbane','2045','2.15','40']] [6, ['Adelaide','Brisbane','2045','2.15','40']]
], ],
'Get table values with getTableData()'
);
deepEqual(
tf.getData(),
[
[0, ['Sydney','Adelaide',1412,1.4,25.3]],
[1, ['Sydney','Brisbane',982,1.5,16]],
[2, ['Sydney','Canberra',286,0.6,4.3]],
[3, ['Sydney','Melbourne',872,1.1,10.5]],
[4, ['Adelaide','Perth',2781,3.1,38]],
[5, ['Adelaide','Alice Springs',1533,2,20.25]],
[6, ['Adelaide','Brisbane',2045,2.15,40]]
],
'Get table data' 'Get table data'
); );
deepEqual(
tf.getValues(),
[
[0, ['Sydney','Adelaide','1412','1.4','25.3']],
[1, ['Sydney','Brisbane','982','1.5','16']],
[2, ['Sydney','Canberra','286','.6','4.3']],
[3, ['Sydney','Melbourne','872','1.1','10.5']],
[4, ['Adelaide','Perth','2781','3.1','38']],
[5, ['Adelaide','Alice Springs','1533','2','20.25']],
[6, ['Adelaide','Brisbane','2045','2.15','40']]
],
'Get table values'
);
tf.clearFilters(); tf.clearFilters();
tf.setFilterValue(0, 'Adelaide'); tf.setFilterValue(0, 'Adelaide');
tf.filter(); tf.filter();
deepEqual( deepEqual(
tf.getFilteredData(), tf.getFilteredValues(),
[ [
[4, ['Adelaide','Perth','2781','3.1','38']], [4, ['Adelaide','Perth','2781','3.1','38']],
[5, ['Adelaide','Alice Springs','1533','2','20.25']], [5, ['Adelaide','Alice Springs','1533','2','20.25']],
[6, ['Adelaide','Brisbane','2045','2.15','40']] [6, ['Adelaide','Brisbane','2045','2.15','40']]
], ],
'Get filtered table data' 'Get filtered table values'
); );
deepEqual( deepEqual(
tf.getFilteredData(true), tf.getFilteredValues(true),
[ [
[0, ['From','Destination','Road Distance (km)', [0, ['From','Destination','Road Distance (km)',
'By Air (hrs)','By Rail (hrs)']], 'By Air (hrs)','By Rail (hrs)']],
@ -490,7 +637,7 @@ test('Get table data', function() {
[5, ['Adelaide','Alice Springs','1533','2','20.25']], [5, ['Adelaide','Alice Springs','1533','2','20.25']],
[6, ['Adelaide','Brisbane','2045','2.15','40']] [6, ['Adelaide','Brisbane','2045','2.15','40']]
], ],
'Get filtered table data including columns headers' 'Get filtered table values including columns headers'
); );
deepEqual( deepEqual(
tf.getFilteredDataCol(0), tf.getFilteredDataCol(0),
@ -502,6 +649,46 @@ test('Get table data', function() {
['From','Adelaide','Adelaide','Adelaide'], ['From','Adelaide','Adelaide','Adelaide'],
'Get specified column filtered values including header' 'Get specified column filtered values including header'
); );
deepEqual(
tf.getFilteredColumnData(2),
[2781,1533,2045],
'Get filtered column data'
);
deepEqual(
tf.getFilteredColumnData(2, true),
['Road Distance (km)',2781,1533,2045],
'Get filtered column data with headers'
);
deepEqual(
tf.getVisibleColumnData(2),
[2781,1533,2045],
'Get visible column data'
);
deepEqual(
tf.getVisibleColumnData(2, true),
['Road Distance (km)',2781,1533,2045],
'Get visible column data with headers'
);
deepEqual(
tf.getFilteredColumnValues(2),
['2781','1533','2045'],
'Get filtered column data'
);
deepEqual(
tf.getFilteredColumnValues(2, true),
['Road Distance (km)','2781','1533','2045'],
'Get filtered column data with headers'
);
deepEqual(
tf.getVisibleColumnValues(2),
['2781','1533','2045'],
'Get visible column data'
);
deepEqual(
tf.getVisibleColumnValues(2, true),
['Road Distance (km)','2781','1533','2045'],
'Get visible column data with headers'
);
tf.clearFilters(); tf.clearFilters();
tf.filter(); tf.filter();
}); });
@ -520,24 +707,24 @@ function colsVisibilityTests() { // issue 94
tf1.filter(); tf1.filter();
deepEqual( deepEqual(
tf1.getFilteredData(false, true), tf1.getFilteredValues(false, true),
[ [
[6, ['Adelaide','3.1','38']], [6, ['Adelaide','3.1','38']],
[7, ['Adelaide','2','20.25']], [7, ['Adelaide','2','20.25']],
[8, ['Adelaide','2.15','40']] [8, ['Adelaide','2.15','40']]
], ],
'Get filtered table data with excluded columns' 'Get filtered table values with excluded columns'
); );
deepEqual( deepEqual(
tf1.getFilteredData(true, true), tf1.getFilteredValues(true, true),
[ [
[1, ['From','By Air (hrs)','By Rail (hrs)']], [1, ['From','By Air (hrs)','By Rail (hrs)']],
[6, ['Adelaide','3.1','38']], [6, ['Adelaide','3.1','38']],
[7, ['Adelaide','2','20.25']], [7, ['Adelaide','2','20.25']],
[8, ['Adelaide','2.15','40']] [8, ['Adelaide','2.15','40']]
], ],
'Get filtered table data with headers and excluded columns' 'Get filtered table values with headers and excluded columns'
); );
deepEqual( deepEqual(
@ -586,6 +773,20 @@ function colsVisibilityTests() { // issue 94
}); });
test('Extension Sanity checks', function() {
deepEqual(
tf1.hasExtension('colsVisibility'),
true,
'ColsVisibility in extensions registry'
);
deepEqual(
tf1.hasExtension('myExtension'),
true,
'myExtension in extensions registry'
);
});
test('Destroy', function() { test('Destroy', function() {
tf1.destroy(); tf1.destroy();
deepEqual(tf1.isInitialized(), false, 'Filters removed'); deepEqual(tf1.isInitialized(), false, 'Filters removed');

View file

@ -2,8 +2,9 @@
var tf = new TableFilter('demo', { var tf = new TableFilter('demo', {
base_path: '../dist/tablefilter/', base_path: '../dist/tablefilter/',
auto_filter: true, auto_filter: {
auto_filter_delay: 1000 delay: 1000
}
}); });
tf.init(); tf.init();
window.tf = tf; window.tf = tf;
@ -14,6 +15,18 @@
deepEqual(tf.autoFilter, true, 'Auto filtering enabled'); deepEqual(tf.autoFilter, true, 'Auto filtering enabled');
deepEqual(tf.autoFilterDelay, 1000, 'Expected filtering delay'); deepEqual(tf.autoFilterDelay, 1000, 'Expected filtering delay');
}); });
test('Blur input filter', function() {
// setup
var filter = tf.getFilterElement(0);
filter.focus();
// act
filter.blur();
// assert
deepEqual(tf.isUserTyping, false, 'User not typing');
deepEqual(tf.autoFilterTimer, null, 'Auto filter timer cleared');
});
module('Remove feature'); module('Remove feature');
test('Auto filter feature disabled', function() { test('Auto filter feature disabled', function() {

109
test/test-cell-parser.html Normal file
View file

@ -0,0 +1,109 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>TableFilter filter with cell parser</title>
<link rel="stylesheet" href="libs/qunit/qunit.css">
<script src="libs/qunit/qunit.js"></script>
<script src="libs/polyfill.js"></script>
</head>
<body>
<table id="demo">
<thead>
<tr>
<th></th>
<th>From</th>
<th>Destination</th>
<th>Road Distance (km)</th>
<th>By Air (hrs)</th>
<th>By Rail (hrs)</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<input type="checkbox" disabled="disabled"
value="" checked="checked">
</td>
<td><strong>Sydney</strong></td>
<td>Adelaide</td>
<td>1412</td>
<td>1.4</td>
<td>25.3</td>
</tr>
<tr>
<td>
<input type="checkbox" disabled="disabled"
value="">
</td>
<td><strong>Sydney</strong></td>
<td>Brisbane</td>
<td>982</td>
<td>1.5</td>
<td>16</td>
</tr>
<tr>
<td>
<input type="checkbox" disabled="disabled"
value="" checked="checked">
</td>
<td><strong>Sydney</strong></td>
<td>Canberra</td>
<td>286</td>
<td>.6</td>
<td>4.3</td>
</tr>
<tr>
<td>
<input type="checkbox" disabled="disabled"
value="" checked="checked">
</td>
<td><strong>Sydney</strong></td>
<td>Melbourne</td>
<td>872</td>
<td>1.1</td>
<td>10.5</td>
</tr>
<tr>
<td>
<input type="checkbox" disabled="disabled"
value="">
</td>
<td><strong>Adelaide</strong></td>
<td>Perth</td>
<td>2781</td>
<td>3.1</td>
<td>38</td>
</tr>
<tr>
<td>
<input type="checkbox" disabled="disabled"
value="" checked="checked">
</td>
<td><strong>Adelaide</strong></td>
<td>Alice Springs</td>
<td>1533</td>
<td>2</td>
<td>20.25</td>
</tr>
<tr>
<td>
<input type="checkbox" disabled="disabled"
value="">
</td>
<td><strong>Adelaide</strong></td>
<td>Brisbane</td>
<td>2045</td>
<td>2.15</td>
<td>40</td>
</tr>
</tbody>
</table>
<script src="../dist/tablefilter/tablefilter.js"></script>
<script src="test-cell-parser.js"></script>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
</body>
</html>

80
test/test-cell-parser.js Normal file
View file

@ -0,0 +1,80 @@
(function(win, TableFilter){
var tf = new TableFilter('demo', {
base_path: '../dist/tablefilter/',
col_0: 'select',
cell_parser: {
cols: [0],
parse: function(tf, cell) {
var chk = cell.getElementsByTagName('input')[0];
if (chk.checked) {
return 'yes';
} else {
return 'no';
}
}
}
});
tf.init();
module('Sanity checks');
test('Sanity checks', function() {
deepEqual(tf instanceof TableFilter, true, 'TableFilter instanciated');
deepEqual(tf.cellParser.cols.length, 1,
'Columns implementing cell parser');
deepEqual(typeof tf.cellParser.parse, 'function', 'Parse function');
deepEqual(
tf.getFilterElement(0).nodeName, 'SELECT', 'Expected filter type');
});
module('Behaviour');
test('Can filter with parsed value', function() {
// setup
tf.setFilterValue(0, 'yes');
// act
tf.filter();
// assert
deepEqual(tf.getValidRows(), [2, 4, 5, 7], 'Number of parsed values');
});
test('Can parse with custom function', function() {
// setup
var cell = tf.dom().rows[3].cells[0];
// act
var value = tf.getCellValue(cell);
// assert
deepEqual(value, 'no', 'Value returned by custom cell parser');
});
test('Should not parse with custom function if no columns defined',
function() {
// setup
var initialCellParser = tf.cellParser;
var hit = 0;
var cell = tf.dom().rows[3].cells[0];
tf.cellParser.cols = [];
tf.cellParser.parse = function() {
hit++;
};
// act
tf.getCellValue(cell);
// assert
deepEqual(hit, 0, 'Cell parser not invoked');
tf.cellParser = initialCellParser;
}
);
module('Tear-down');
test('can destroy', function() {
tf.destroy();
deepEqual(tf.isInitialized(), false, 'Filters removed');
});
})(window, TableFilter);

View file

@ -41,7 +41,7 @@ test('Can refresh all drop-down filters', function() {
tf.clearFilters(); tf.clearFilters();
var build = checkList.build; var build = checkList.build;
var hit = 0; var hit = 0;
checkList.build = function() { hit++ }; checkList.build = function() { hit++; };
//act //act
checkList.refreshAll(); checkList.refreshAll();
@ -100,18 +100,43 @@ test('Can sort options', function() {
tf.destroy(); tf.destroy();
tf = new TableFilter('demo', { tf = new TableFilter('demo', {
base_path: '../dist/tablefilter/', base_path: '../dist/tablefilter/',
col_0: 'checklist',
col_1: 'checklist',
col_2: 'checklist', col_2: 'checklist',
col_3: 'checklist', col_3: 'checklist',
col_4: 'checklist', col_4: 'checklist',
sort_num_asc: [2, 3], col_types: ['string', 'string', 'number', 'number', 'number'],
sort_num_desc: [4] sort_filter_options_asc: [0, 2, 3],
sort_filter_options_desc: [1, 4]
}); });
tf.init(); tf.init();
var flt0 = id(tf.fltIds[0]);
var flt1 = id(tf.fltIds[1]);
var flt2 = id(tf.fltIds[2]); var flt2 = id(tf.fltIds[2]);
var flt3 = id(tf.fltIds[3]); var flt3 = id(tf.fltIds[3]);
var flt4 = id(tf.fltIds[4]); var flt4 = id(tf.fltIds[4]);
deepEqual(
flt0.getElementsByTagName('li')[1].firstChild.firstChild.value,
'Adelaide',
'First option value for column 0'
);
deepEqual(
flt0.getElementsByTagName('li')[2].firstChild.firstChild.value,
'Sydney',
'Last option value for column 0'
);
deepEqual(
flt1.getElementsByTagName('li')[1].firstChild.firstChild.value,
'Perth',
'First option value for column 1'
);
deepEqual(
flt1.getElementsByTagName('li')[6].firstChild.firstChild.value,
'Adelaide',
'Last option value for column 1'
);
deepEqual( deepEqual(
flt2.getElementsByTagName('li')[1].firstChild.firstChild.value, flt2.getElementsByTagName('li')[1].firstChild.firstChild.value,
'286', '286',
@ -181,6 +206,55 @@ test('Can select empty and non-empty options', function() {
'Filter 3 options values attribute'); 'Filter 3 options values attribute');
}); });
// issue 714, clear filter text
module('Clear filter text');
test('Can define clear filter text for each column', function() {
tf.clearFilters();
tf.destroy();
tf = new TableFilter('demo', {
base_path: '../dist/tablefilter/',
col_2: 'checklist',
col_3: 'checklist',
col_4: 'checklist',
clear_filter_text: [null, null, 'clear 2', 'clear 3', 'clear 4']
});
tf.init();
var flt2 = tf.getFilterElement(2).getElementsByTagName('li');
var flt3 = tf.getFilterElement(3).getElementsByTagName('li');
var flt4 = tf.getFilterElement(4).getElementsByTagName('li');
deepEqual(flt2[0].getElementsByTagName('label')[0].innerText,
'clear 2', 'clear text filter 2');
deepEqual(flt3[0].getElementsByTagName('label')[0].innerText,
'clear 3', 'clear text filter 3');
deepEqual(flt4[0].getElementsByTagName('label')[0].innerText,
'clear 4', 'clear text filter 4');
});
test('Can define clear filter text globally', function() {
tf.clearFilters();
tf.destroy();
tf = new TableFilter('demo', {
base_path: '../dist/tablefilter/',
col_2: 'checklist',
col_3: 'checklist',
col_4: 'checklist',
clear_filter_text: 'reset'
});
tf.init();
var flt2 = tf.getFilterElement(2).getElementsByTagName('li');
var flt3 = tf.getFilterElement(3).getElementsByTagName('li');
var flt4 = tf.getFilterElement(4).getElementsByTagName('li');
deepEqual(flt2[0].getElementsByTagName('label')[0].innerText,
'reset', 'clear text filter 2');
deepEqual(flt3[0].getElementsByTagName('label')[0].innerText,
'reset', 'clear text filter 3');
deepEqual(flt4[0].getElementsByTagName('label')[0].innerText,
'reset', 'clear text filter 4');
});
module('Tear down'); module('Tear down');
test('TableFilter removed', function() { test('TableFilter removed', function() {
tf.destroy(); tf.destroy();

View file

@ -8,6 +8,7 @@
<script src="libs/polyfill.js"></script> <script src="libs/polyfill.js"></script>
</head> </head>
<body> <body>
<div id="external-container"></div>
<table id="demo" cellpadding="0" cellspacing="0"> <table id="demo" cellpadding="0" cellspacing="0">
<tbody> <tbody>
<tr> <tr>

View file

@ -6,6 +6,7 @@ var tf = new TableFilter('demo', {
tf.init(); tf.init();
var clearButton = tf.feature('clearButton'); var clearButton = tf.feature('clearButton');
module('Sanity checks'); module('Sanity checks');
test('Clear button component', function() { test('Clear button component', function() {
deepEqual(typeof clearButton, 'object', 'ClearButton instanciated'); deepEqual(typeof clearButton, 'object', 'ClearButton instanciated');
@ -58,6 +59,61 @@ test('Can check is enabled', function() {
deepEqual(clearButton.enabled, true, 'enabled'); deepEqual(clearButton.enabled, true, 'enabled');
}); });
module('Behaviour');
test('Cannot init if already initialised', function() {
// setup
clearButton.initialized = true;
var emit = clearButton.emitter.emit;
var hit = 0;
clearButton.emitter.emit = function() {
hit++;
};
// act
clearButton.init();
// assert
deepEqual(hit, 0, 'does not initialise');
clearButton.emitter.emit = emit;
});
test('onClick does nothing if not enabled', function() {
// setup
clearButton.disable();
var clearFilters = clearButton.tf.clearFilters;
var hit = 0;
clearButton.tf.clearFilters = function() {
hit++;
};
// act
clearButton.onClick();
// assert
deepEqual(hit, 0, 'onClick does nothing');
clearButton.tf.clearFilters = clearFilters;
});
test('onClick calls clearFilters if enabled', function() {
// setup
clearButton.enable();
var clearFilters = clearButton.tf.clearFilters;
var hit = 0;
clearButton.tf.clearFilters = function() {
hit++;
};
// act
clearButton.onClick();
// assert
deepEqual(hit, 1, 'onClick calls clearFilters');
clearButton.tf.clearFilters = clearFilters;
});
module('UI elements'); module('UI elements');
test('ClearButton UI elements', function() { test('ClearButton UI elements', function() {
var container = clearButton.container; var container = clearButton.container;
@ -73,7 +129,7 @@ test('Remove UI', function() {
deepEqual(btnResetEl, null, 'Clear button is removed'); deepEqual(btnResetEl, null, 'Clear button is removed');
}); });
test('Re-set UI', function() { test('Re-set UI with no icons and text button', function() {
clearButton.destroy(); clearButton.destroy();
tf.enableIcons = false; tf.enableIcons = false;
clearButton.html = null; clearButton.html = null;
@ -85,6 +141,40 @@ test('Re-set UI', function() {
deepEqual(btnResetEl.innerText, 'Clear', 'Clear button text'); deepEqual(btnResetEl.innerText, 'Clear', 'Clear button text');
}); });
test('Destroy and init with text button and icons enabled', function() {
tf.destroy();
tf = new TableFilter('demo', {
base_path: '../dist/tablefilter/',
btn_reset: {
text: 'Clear all'
}
});
tf.init();
clearButton = tf.feature('clearButton');
var btnResetEl = clearButton.element;
deepEqual(btnResetEl.nodeName, 'A', 'Clear button tag changed');
deepEqual(btnResetEl.innerText, 'Clear all', 'Clear button text');
});
test('Destroy and init in external container', function() {
tf.destroy();
tf = new TableFilter('demo', {
base_path: '../dist/tablefilter/',
btn_reset: {
target_id: 'external-container'
}
});
tf.init();
clearButton = tf.feature('clearButton');
deepEqual(clearButton.element.nodeName, 'INPUT', 'Clear button tag');
deepEqual(clearButton.container.parentNode.id, 'external-container',
'container id');
});
module('Tear-down'); module('Tear-down');
test('can destroy TableFilter DOM elements', function() { test('can destroy TableFilter DOM elements', function() {
tf.destroy(); tf.destroy();

View file

@ -6,8 +6,9 @@ var totRowIndex = table.getElementsByTagName('tr').length;
tf = new TableFilter('demo', { tf = new TableFilter('demo', {
base_path: '../dist/tablefilter/', base_path: '../dist/tablefilter/',
col_types: ['string', 'string', 'number', 'number', 'number'], col_types: ['string', 'string', 'number', 'number', 'number'],
paging: true, paging: {
paging_length: 4, length: 4
},
rows_always_visible: [ rows_always_visible: [
totRowIndex-6, totRowIndex-6,
totRowIndex-5, totRowIndex-5,

View file

@ -140,6 +140,61 @@ test('Can make column calculations', function() {
deepEqual(result2, 2781, 'columnCalc max'); deepEqual(result2, 2781, 'columnCalc max');
}); });
test('Can make column calculations with formated results', function() {
// setup
var colOps = tf.extension('colOps');
colOps.formatResults[2] = { suffix: ' Km' };
colOps.formatResults[4] = { suffix: ' Km' };
colOps.formatResults[6] = { suffix: ' Km' };
tf.colTypes[2] = { type: 'formatted-number', decimal: '.', thousands: ',' };
// act
colOps.calcAll();
// assert
deepEqual(id('mean1').innerHTML, '1,416 Km', 'Formatted mean result');
deepEqual(id('min1').innerHTML, '286 Km', 'Formatted min result');
deepEqual(id('max1').innerHTML, '2,781 Km', 'Formatted max result');
colOps.formatResults[2] = undefined;
colOps.formatResults[4] = undefined;
colOps.formatResults[6] = undefined;
tf.colTypes[2] = undefined;
});
test('Can configure result format', function() {
// setup
var colOps = tf.extension('colOps');
var format = { prefix: '$', suffix: '/item' };
// act
var format = colOps.configureFormat(2, format);
// assert
deepEqual(format.prefix, '$', 'prefix');
deepEqual(format.suffix, '/item', 'suffix');
deepEqual(format.decimal, '', 'decimal separator');
deepEqual(format.integerSeparator, '', 'thousands separator');
});
test('Can configure result format for formatted number column', function() {
// setup
var colOps = tf.extension('colOps');
var format = { prefix: '$', suffix: '/item' };
tf.colTypes = [null, null, null, null, null];
tf.colTypes[3] = { type: 'formatted-number', decimal: ',', thousands: '.' };
// act
var format = colOps.configureFormat(3, format);
// assert
deepEqual(format.prefix, '$', 'prefix');
deepEqual(format.suffix, '/item', 'suffix');
deepEqual(format.decimal, ',', 'decimal separator');
deepEqual(format.integerSeparator, '.', 'thousands separator');
tf.colTypes[3] = undefined;
});
module('Tear-down'); module('Tear-down');
test('can destroy', function() { test('can destroy', function() {
tf.destroy(); tf.destroy();

View file

@ -9,10 +9,12 @@
module('Sanity checks'); module('Sanity checks');
test('Column widths', function() { test('Column widths', function() {
var cols = tf.tbl.getElementsByTagName('col'); var cols = tf.dom().getElementsByTagName('col');
deepEqual(tf instanceof TableFilter, true, 'TableFilter instanciated'); deepEqual(tf instanceof TableFilter, true, 'TableFilter instanciated');
deepEqual(cols[1].style.width, '100px', 'Expected column width'); deepEqual(cols[1].style.width, '100px', 'Expected column width');
deepEqual(cols[4].style.width, '', 'Expected column width'); deepEqual(cols[4].style.width, '', 'Expected column width');
deepEqual(tf.dom().style.width, '645px', 'Table width set');
deepEqual(tf.dom().style.tableLayout, 'fixed', 'Table layout fixed');
}); });
test('Grid layout column widths', function() { test('Grid layout column widths', function() {
@ -20,14 +22,19 @@
tf = null; tf = null;
tf = new TableFilter('demo', { tf = new TableFilter('demo', {
base_path: '../dist/tablefilter/', base_path: '../dist/tablefilter/',
col_widths: ['150px', '100px', '175px', '120px', '200px'], col_widths: ['150px', '100px', '175px', '120px', null],
grid_layout: true, grid_layout: true
sort: false
}); });
tf.init(); tf.init();
var cols = tf.feature('gridLayout').headTbl.getElementsByTagName('col'); var gridLayout = tf.feature('gridLayout');
var cols = gridLayout.headTbl.getElementsByTagName('col');
deepEqual(cols[0].style.width, '150px', 'Expected column width'); deepEqual(cols[0].style.width, '150px', 'Expected column width');
deepEqual(cols[4].style.width, '200px', 'Expected column width'); deepEqual(cols[3].style.width, '120px', 'Expected column width');
deepEqual(
tf.dom().style.width === gridLayout.headTbl.style.width,
true,
'Content and headers table have same width'
);
}); });
})(window, TableFilter); })(window, TableFilter);

Some files were not shown because too many files have changed in this diff Show more