1
0
Fork 0
mirror of https://github.com/koalyptus/TableFilter.git synced 2024-06-04 23:12:22 +02:00

Compare commits

...

1411 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
koalyptus e5f8013034 Merge pull request #403 from koalyptus/402-col-ops
Fixed ColOps firing colum-calc twice, made operation setting handling more devensive
2017-02-12 00:01:56 +11:00
Max Guglielmi a1581a6ea1 Fixed ColOps firing colum-calc twice, made operation setting handling more devensive 2017-02-11 23:47:40 +11:00
koalyptus f81ce3f533 Merge pull request #401 from koalyptus/greenkeeper-grunt-webpack-2.0.1
Migrate to webpack 2
2017-02-04 12:34:06 +11:00
Max Guglielmi d3cece2424 Removed commented-out code left-over 2017-02-04 12:22:02 +11:00
Max Guglielmi 7351798ea4 Removed commented out code 2017-02-04 12:09:20 +11:00
Max Guglielmi ccc7c27032 Continued fixing tests 2017-02-04 01:00:29 +11:00
Max Guglielmi e17b34d98a Started fixing failing unit tests due to promise based implementation of dynamic requires 2017-02-03 23:58:50 +11:00
Max Guglielmi 8cb947a6e5 Started migration to webpack 2 2017-02-03 17:04:07 +11:00
Max Guglielmi 00b339954b Migrating to webpack 2 2017-01-29 22:50:12 +11:00
koalyptus 2fa3ef4140 Merge pull request #396 from koalyptus/greenkeeper-grunt-webpack-2.0.1
Update grunt-webpack to version 2.0.1 🚀
2017-01-29 22:38:28 +11:00
greenkeeperio-bot fe3e2dcb67 chore(package): update grunt-webpack to version 2.0.1
https://greenkeeper.io/
2017-01-28 08:46:12 +11:00
koalyptus f9bd89af04 Merge pull request #394 from koalyptus/358-increase-coverage
358 increase coverage
2017-01-26 22:14:02 +11:00
Max Guglielmi 2742716de4 Prepared dist 2017-01-26 20:14:34 +11:00
Max Guglielmi b3910ca837 Increasing TableFilter class Coverage 2017-01-24 14:06:29 +11:00
koalyptus b608d8c778 Merge pull request #393 from koalyptus/358-increase-coverage
Expanded no filters unit tests
2017-01-23 14:04:25 +11:00
Max Guglielmi 2e3e68bb6f Expanded no filters unit tests 2017-01-23 13:55:09 +11:00
koalyptus 787f97eeb2 Merge pull request #392 from koalyptus/358-increase-coverage
358 increase coverage
2017-01-21 10:59:42 +11:00
Max Guglielmi 9a7e8f6982 Added date filtering test case with data range and operators 2017-01-21 10:51:38 +11:00
Max Guglielmi 44af1dc552 Added doco comment to getCellValue + added date filtering tests 2017-01-21 10:40:45 +11:00
Max Guglielmi 8c9a033c67 Merge branch 'master' into 358-increase-coverage 2017-01-19 13:04:48 +11:00
koalyptus 0d6530fe8d Merge pull request #391 from koalyptus/390-get-cell-content-api
390 get cell content api
2017-01-18 21:53:19 +11:00
Max Guglielmi b91cf53ac1 Fixed unit tests 2017-01-18 21:29:00 +11:00
Max Guglielmi 7e5cd343d2 Changed signature od getTableData and getFilteredData 2017-01-17 14:20:11 +11:00
Max Guglielmi b15f3ed396 Started getCellData vs getCellValue 2017-01-16 14:04:55 +11:00
Max Guglielmi 385317eeff Merge branch '332-colops-refactor' into 390-get-cell-content-api 2017-01-16 13:15:41 +11:00
Max Guglielmi 2aecbfd424 Updated doc comment 2017-01-16 13:12:21 +11:00
koalyptus 47d350470c Merge pull request #389 from koalyptus/332-colops-refactor
332 colops refactor
2017-01-15 17:49:08 +11:00
Max Guglielmi 4acb352edc Address PR feedback (2) 2017-01-15 17:30:48 +11:00
Max Guglielmi ff99b14f6b Address PR feedback 2017-01-15 17:26:35 +11:00
Max Guglielmi 51f8521ddd Prepare PR 2017-01-15 16:39:14 +11:00
Max Guglielmi 0fcfe0208d Merge branch 'master' into 332-colops-refactor 2017-01-15 16:31:36 +11:00
Max Guglielmi ed164cc64f Included starter.html in dist folder 2017-01-15 16:30:52 +11:00
Max Guglielmi c773927945 Lowered max-statements and complexity values in .eslintrc 2017-01-15 16:29:50 +11:00
Max Guglielmi 77e606cf12 Cleaned code 2017-01-15 14:57:52 +11:00
Max Guglielmi dcfe5d44c7 Added comments 2017-01-15 00:09:28 +11:00
Max Guglielmi 1f5ad88a39 Added columnCalc helper method 2017-01-13 17:05:39 +11:00
koalyptus b4a1d207b7 Merge pull request #388 from koalyptus/greenkeeper-diacritics-1.3.0
Update diacritics to version 1.3.0 🚀
2017-01-13 07:50:53 +11:00
greenkeeperio-bot 5ea5a88560 chore(package): update diacritics to version 1.3.0
https://greenkeeper.io/
2017-01-13 07:21:19 +11:00
koalyptus 98f230e14f Merge pull request #387 from koalyptus/greenkeeper-string-replace-webpack-plugin-0.0.5
Update string-replace-webpack-plugin to version 0.0.5 🚀
2017-01-13 06:35:01 +11:00
greenkeeperio-bot c2fef2aac8 chore(package): update string-replace-webpack-plugin to version 0.0.5
https://greenkeeper.io/
2017-01-13 01:44:14 +11:00
Max Guglielmi 995eda0498 Fixed unit tests 2017-01-12 23:42:58 +11:00
Max Guglielmi d1daa51391 Continued refactoring 2017-01-12 14:07:21 +11:00
Max Guglielmi 9787edf857 Continued adding calc helpers 2017-01-11 17:13:38 +11:00
Max Guglielmi 926d4e80b5 Added specific calculation methods 2017-01-11 14:13:57 +11:00
Max Guglielmi 12af93cd17 Extracted writeResult method 2017-01-10 14:07:16 +11:00
Max Guglielmi 284da0fde1 Renamed some vars for better readability 2017-01-09 14:02:43 +11:00
koalyptus dc5b7ab41a Merge pull request #386 from koalyptus/384-cols-visibility-popup-autoclosable
Made cols visibility popup auto-closable on click-away
2017-01-07 23:01:40 +11:00
Max Guglielmi 1d9c1a435b Made cols visibility popup auto-closable on click-away 2017-01-07 22:51:49 +11:00
koalyptus a3716371f8 Merge pull request #383 from koalyptus/380-no-rows
Fixed dist build files
2017-01-05 08:13:59 +11:00
Max Guglielmi b2700c9972 Fixed dist build files 2017-01-05 08:05:57 +11:00
koalyptus 2cc5b597ec Merge pull request #382 from koalyptus/380-no-rows
Fix instantiation with 1 row
2017-01-04 14:16:47 +11:00
Max Guglielmi 9d8744392a Fix instantiation with 1 row 2017-01-04 14:09:18 +11:00
koalyptus 231b8bffaa Merge pull request #379 from koalyptus/358-increase-coverage
358 increase coverage
2017-01-03 14:14:13 +11:00
Max Guglielmi c4a1c47176 Expanded events tests for AlternateRows 2017-01-03 14:08:21 +11:00
Max Guglielmi 222587f1f3 Merge branch 'master' into 358-increase-coverage 2017-01-03 13:07:41 +11:00
koalyptus 0c89a3eef9 Merge pull request #377 from koalyptus/376-fix-help-popup-close-button
Fixed closed button in help popup
2017-01-01 22:21:30 +11:00
Max Guglielmi 90b3f21332 Fixed closed button in help popup 2017-01-01 22:14:27 +11:00
koalyptus b802d7bd50 Merge pull request #375 from koalyptus/320-ezedittable-integration
320 ezedittable integration
2017-01-01 17:46:13 +11:00
Max Guglielmi 312d8b1b9c Removed commented out code 2017-01-01 17:35:18 +11:00
Max Guglielmi 556bf1c264 Added unit tests 2017-01-01 17:31:48 +11:00
koalyptus c1f0d71bcb Merge pull request #374 from koalyptus/373-auto-closable-help-popup
Made help container auto-closable when user clicks away
2016-12-27 21:50:30 +11:00
Max Guglielmi c9c4d351a1 Made help container auto-closable when user clicks away (2) 2016-12-27 21:37:08 +11:00
Max Guglielmi 7e779a0242 Made help container auto-closable when user clicks away 2016-12-27 21:20:16 +11:00
koalyptus 72dbf6ba27 Merge pull request #372 from koalyptus/issue-319-todos
Added missing source maps
2016-12-25 00:01:17 +11:00
Max Guglielmi 8af1cab7ff Added missing source maps 2016-12-24 23:55:31 +11:00
koalyptus ed30bc7d93 Merge pull request #371 from koalyptus/issue-319-todos
Addressed destroy TODO
2016-12-24 23:50:07 +11:00
Max Guglielmi f41f268975 Addressed destroy TODO 2016-12-24 23:35:26 +11:00
koalyptus 7aaf192386 Merge pull request #370 from koalyptus/issue-319-todos
Assigned empty function to callbacks
2016-12-22 22:15:23 +11:00
Max Guglielmi c75fbe169c Assigned empty function to callbacks 2016-12-22 22:01:59 +11:00
koalyptus 8481b69061 Merge pull request #369 from koalyptus/issue-319-todos
Missing starter
2016-12-21 22:00:29 +11:00
Max Guglielmi 8af59ef676 Missing starter 2016-12-21 21:53:03 +11:00
koalyptus 9e5216ebc1 Merge pull request #368 from koalyptus/issue-319-todos
Issue 319 todos
2016-12-21 21:07:53 +11:00
Max Guglielmi b6b798b548 Removed commented out comment 2016-12-21 20:58:35 +11:00
Max Guglielmi 4711b71b80 Added comments 2016-12-21 20:54:21 +11:00
Max Guglielmi 6b43172199 Started moving hasArg function outside filter method 2016-12-20 14:16:53 +11:00
koalyptus bdb728a817 Merge pull request #367 from koalyptus/issue-319-todos
Issue 319 todos
2016-12-19 14:01:52 +11:00
Max Guglielmi 7ef31a4c62 Moved highlight function into HighlightKeywords module 2016-12-19 13:51:48 +11:00
Max Guglielmi 47deeb1893 Removing highlight function from filter method 2016-12-18 22:44:23 +11:00
Max Guglielmi dd6d03a521 Merge branch 'master' into issue-319-todos 2016-12-18 21:47:13 +11:00
koalyptus ec36d4c39d Merge pull request #366 from koalyptus/365-alternate-rows-and-sort-column-at-start
365 alternate rows and sort column at start
2016-12-18 00:48:32 +11:00
Max Guglielmi f9f99798e4 Addressing zebra rows with sort columnt at start option 2016-12-18 00:23:57 +11:00
Max Guglielmi 9b93b2fc26 Started addressing alternate rows bug in conjunction with sorting a column at start 2016-12-16 14:06:00 +11:00
Max Guglielmi 558236a6ac Merge branch 'master' into issue-319-todos 2016-12-11 09:37:00 +11:00
koalyptus 0f337c8fe9 Merge pull request #363 from koalyptus/358-increase-coverage
358 increase coverage
2016-12-09 23:56:07 +11:00
Max Guglielmi 11ca10cdfd Bumped version 2016-12-09 23:33:37 +11:00
Max Guglielmi 5dcd756414 Enlarged AlternateRows code coverage 2016-12-09 23:25:42 +11:00
koalyptus 54866f958f Merge pull request #361 from koalyptus/358-increase-coverage
Increasing coverage
2016-12-09 14:48:03 +11:00
Max Guglielmi e54ac4b84f Increasing coverage 2016-12-09 14:14:08 +11:00
koalyptus d7da92f9e4 Merge pull request #360 from koalyptus/358-increase-coverage
Continued increasing coverage
2016-12-08 22:28:15 +11:00
Max Guglielmi 5adf82abc7 Uncommented test code 2016-12-08 22:19:16 +11:00
Max Guglielmi 8dee7d0cfb Continued increasing coverage 2016-12-08 22:16:47 +11:00
koalyptus 143cbffd63 Merge pull request #359 from koalyptus/358-increase-coverage
Testing codecov
2016-12-08 14:33:00 +11:00
Max Guglielmi 0b1f4b67f5 Testing codecov 2016-12-08 14:21:39 +11:00
koalyptus d096de8852 Merge pull request #357 from koalyptus/307-code-coverage-2
307 code coverage 2
2016-12-08 00:27:18 +11:00
Max Guglielmi b1a67d8a80 Added codecov badge 2016-12-08 00:16:14 +11:00
Max Guglielmi 87fb91cea5 Modified travis yaml 2016-12-07 23:54:13 +11:00
Max Guglielmi 4b1146c385 Added and configured isparta and codecov (1) 2016-12-07 23:48:28 +11:00
Max Guglielmi 7b2b040cc9 Started playing with babel-instanbul loader 2016-12-04 22:48:57 +11:00
Max Guglielmi 5d8f81ab78 take 1 2016-12-04 10:36:39 +11:00
koalyptus 5cebe6c217 Merge pull request #355 from koalyptus/140-clear-text-per-filter
140 clear text per filter
2016-12-01 21:49:11 +11:00
Max Guglielmi 29a8265efd Fixed typo 2016-12-01 21:39:08 +11:00
Max Guglielmi d5ede81ba7 Unrelate: fixed in linked filters disabled demo column types 2016-12-01 21:34:03 +11:00
Max Guglielmi 2d60de24b6 Fixed unit tests 2016-12-01 21:29:38 +11:00
Max Guglielmi 7ede842828 Made renamed displayAllText into clearFilterText and made it accepting an array 2016-12-01 13:58:09 +11:00
koalyptus 99a814db94 Merge pull request #353 from koalyptus/317-guidelines
317 guidelines
2016-11-26 20:52:18 +11:00
Max Guglielmi f44ce0678d Added missing starter.html 2016-11-26 20:43:00 +11:00
Max Guglielmi a3b9d0e37c Updated README 2016-11-26 20:30:00 +11:00
Max Guglielmi 606d2e0fed Added contribuing file 2016-11-26 17:43:59 +11:00
koalyptus afa4d68563 Merge pull request #351 from koalyptus/347-sorting-date-column-blank-values
Addressing sorting date columns with blank values
2016-11-24 14:26:10 +11:00
Max Guglielmi 0cd9854634 Addressing sorting date columns with blank values 2016-11-24 14:14:55 +11:00
koalyptus 5e7ff39b04 Merge pull request #346 from koalyptus/345-popup-filters-container-with
Added popup_adjust_to_container configuration option to PopupFilter
2016-11-22 14:21:50 +11:00
Max Guglielmi 27a083444f Renamed popup_adjust_to_container to popup_filters_adjust_to_container 2016-11-22 14:15:28 +11:00
Max Guglielmi 57548bd3c0 Added popup_adjust_to_container configuration option to PopupFilter 2016-11-22 14:01:36 +11:00
koalyptus 873d79c58a Merge pull request #344 from koalyptus/318-transparent-theme
318 transparent theme
2016-11-20 00:53:12 +11:00
Max Guglielmi d7413372f8 Continued transparent theme 2016-11-20 00:32:49 +11:00
Max Guglielmi 0ed1ac7d1e Started transparent theme 2016-11-19 23:42:37 +11:00
koalyptus f59b0f056b Merge pull request #343 from koalyptus/greenkeeper-babel-eslint-7.1.1
Update babel-eslint to version 7.1.1 🚀
2016-11-18 17:29:25 +11:00
greenkeeperio-bot 061270774c chore(package): update babel-eslint to version 7.1.1
https://greenkeeper.io/
2016-11-18 10:06:21 +11:00
koalyptus a5178ecace Merge pull request #341 from koalyptus/issue-339-popup-filters
Issue 339 popup filters
2016-11-18 00:22:40 +11:00
Max Guglielmi f52f52f0ae Updated unit tests 2016-11-18 00:01:33 +11:00
Max Guglielmi 88a6ed17fc Started enhancing multiple selection filter types behaviour in popup mode 2016-11-17 13:05:25 +11:00
koalyptus eb5a733f03 Merge pull request #338 from koalyptus/issue-319-todos
Issue 319 todos
2016-11-15 21:25:58 +11:00
Max Guglielmi 0b95fdc79d Addressed PR #338 2016-11-15 21:17:15 +11:00
Max Guglielmi 7a78e9d980 Prepared dist 2016-11-15 17:38:23 +11:00
Max Guglielmi fd9c257e52 Simplified WTFs in dropdown and checklist 2016-11-15 16:49:19 +11:00
Max Guglielmi 782073fa14 Started addressing WTFs... 2016-11-14 14:10:42 +11:00
koalyptus f73f3d62d9 Merge pull request #337 from koalyptus/issue-319-todos
Issue 319 todos
2016-11-10 16:27:06 +11:00
Max Guglielmi cbe5d8ef71 Removed commented out code left-overs (2) 2016-11-10 15:56:30 +11:00
Max Guglielmi 777d8df76e Removed commented out code left-overs 2016-11-10 15:50:31 +11:00
Max Guglielmi a50e0fa4bc Removed element IDs from PopupFilter and CheckList 2016-11-10 15:44:38 +11:00
Max Guglielmi 7370173811 Removed unnecessary DOM element IDs 2016-11-10 14:16:57 +11:00
Max Guglielmi 9db430c1d1 Started id builder helper 2016-11-08 22:40:54 +11:00
koalyptus 3e977fa6e5 Merge pull request #336 from koalyptus/issue-319-todos
Removed element IDs from paging
2016-11-05 22:21:33 +11:00
koalyptus f4960e250b Merge pull request #335 from koalyptus/greenkeeper-sugar-date-2.0.2
Update sugar-date to version 2.0.2 🚀
2016-11-05 22:09:55 +11:00
Max Guglielmi e8a2ada208 Removed element IDs from paging 2016-11-05 22:08:32 +11:00
greenkeeperio-bot ff975005b4 chore(package): update sugar-date to version 2.0.2
https://greenkeeper.io/
2016-11-05 16:29:26 +11:00
koalyptus f6a2377be9 Merge pull request #334 from koalyptus/issue-319-todos
Removed element IDs from GridLayout
2016-11-03 22:18:52 +11:00
Max Guglielmi 3ff52002e4 Removed element IDs from GridLayout 2016-11-03 22:08:03 +11:00
koalyptus 15c2035064 Merge pull request #333 from koalyptus/issue-319-todos
Addressed #332 and continued #319
2016-11-02 23:13:57 +11:00
Max Guglielmi b99405997a Addressed #332 and continued #319 2016-11-02 23:01:31 +11:00
koalyptus df6a18b3d9 Merge pull request #331 from koalyptus/issue-319-todos
Removed DOM element IDs from StatusBar, PopupFilter and FiltersVisibility
2016-11-02 14:57:30 +11:00
Max Guglielmi ad3335e488 Added missing starter.html 2016-11-02 14:40:20 +11:00
Max Guglielmi 0644368cd6 Removed DOM element IDs from StatusBar, PopupFilter and FiltersVisibility (2) 2016-11-02 14:17:59 +11:00
Max Guglielmi adb9539ee3 Removed DOM element IDs from StatusBar, PopupFilter and FiltersVisibility 2016-11-02 14:13:44 +11:00
koalyptus 904e47957d Merge pull request #330 from koalyptus/issue-319-todos
Removed element IDs from Loader and NoResults
2016-11-01 20:15:15 +11:00
Max Guglielmi eeffb5b102 Removed element IDs from Loader and NoResults 2016-11-01 20:02:15 +11:00
koalyptus 597be6faed Merge pull request #329 from koalyptus/issue-319-todos
Removed element IDs from Help and RowsCounter
2016-11-01 15:55:18 +11:00
Max Guglielmi 21305e2e62 Removed element IDs from Help and RowsCounter 2016-11-01 13:58:25 +11:00
koalyptus d9f28e4908 Merge pull request #328 from koalyptus/issue-319-todos
Removed clear button container ID
2016-10-31 22:33:47 +11:00
Max Guglielmi 85c62a7bff Fixed test-api.js indentation 2016-10-31 22:27:45 +11:00
Max Guglielmi 0b72eb55b0 Removed clear button container ID 2016-10-31 22:18:21 +11:00
koalyptus 3299742898 Merge pull request #325 from koalyptus/issue-319-todos
Issue 319 todos
2016-10-28 09:54:56 +11:00
Max Guglielmi 94ea4a9d69 dist package 2016-10-28 09:46:46 +11:00
Max Guglielmi 81d7a529ff Stored events list into const in Loader class 2016-10-27 13:33:42 +11:00
koalyptus 4af3db82df Merge pull request #324 from koalyptus/greenkeeper-babel-eslint-7.1.0
Update babel-eslint to version 7.1.0 🚀
2016-10-27 09:28:57 +11:00
greenkeeperio-bot c4c90e3c15 chore(package): update babel-eslint to version 7.1.0
https://greenkeeper.io/
2016-10-27 05:45:40 +11:00
koalyptus 2eedc8dd60 Merge pull request #321 from koalyptus/issue-314-diacritics
Issue 314 diacritics
2016-10-22 19:52:15 +11:00
Max Guglielmi 111a4dd246 Added unit tests 2016-10-22 19:38:03 +11:00
Max Guglielmi d57ede865f Implemented ignore diacritics feature 2016-10-22 13:07:57 +11:00
koalyptus ef7abbf0d6 Merge pull request #316 from koalyptus/date-type-tests
Date type tests
2016-10-19 13:54:41 +11:00
Max Guglielmi a885c8caab Issue #313 Made locale.addFormat more defensive 2016-10-19 13:39:59 +11:00
Max Guglielmi 9cbc364a92 Merge branch 'master' into date-type-tests 2016-10-17 12:03:21 +11:00
koalyptus f5a989d977 Merge pull request #312 from koalyptus/date-type-tests
Date type tests
2016-10-13 13:25:30 +11:00
Max Guglielmi 32fa832a6e Fixing date tests 2016-10-13 13:19:39 +11:00
Max Guglielmi 66f36a7531 Finalised dateType unit tests 2016-10-12 18:07:12 +11:00
Max Guglielmi c5b4251039 Started dateType unit tests 2016-10-12 14:15:19 +11:00
koalyptus d26ed8e2b9 Merge pull request #310 from koalyptus/issue-309-keyword-highlighting-bug
Addressed issue-309
2016-10-10 18:32:34 +11:00
Max Guglielmi 288af8b94e Addressed issue-309 2016-10-10 18:16:39 +11:00
koalyptus 5d0671f445 Merge pull request #308 from koalyptus/greenkeeper-clean-webpack-plugin-0.1.12
chore(package): update clean-webpack-plugin to version 0.1.12
2016-10-09 14:24:56 +11:00
greenkeeperio-bot 95236a22ae chore(package): update clean-webpack-plugin to version 0.1.12
https://greenkeeper.io/
2016-10-09 13:07:43 +11:00
koalyptus 715a768203 Merge pull request #306 from koalyptus/issue-300-colops-unit-tests
Issue 300 colops unit tests
2016-10-08 11:59:14 +11:00
Max Guglielmi 028932e53c Expanded colOps extension tests 2016-10-08 11:50:34 +11:00
Max Guglielmi 42fb664228 initial commit 2016-10-07 23:08:13 +11:00
koalyptus fedf365400 Merge pull request #304 from koalyptus/issue-231-col-types
Issue 231 col types
2016-10-05 13:20:31 +11:00
Max Guglielmi 0f0ea9f2c4 Addressed PR feedback 2016-10-03 17:07:50 +11:00
Max Guglielmi e19fc2839e Removed legacy date helper 2016-10-03 15:26:24 +11:00
Max Guglielmi 83de328c2b Updated dev dependencies 2016-10-03 14:36:39 +11:00
Max Guglielmi b6a4a35bfa Updated dependencies versions 2016-10-01 22:43:43 +10:00
Max Guglielmi b0f62e5015 Merge branch 'master' into issue-231-col-types 2016-09-30 14:29:24 +10:00
koalyptus aa457177c3 Merge pull request #302 from koalyptus/greenkeeper-babel-eslint-7.0.0
Update babel-eslint to version 7.0.0 🚀
2016-09-29 13:07:57 +10:00
greenkeeperio-bot 1c4c21b085 chore(package): update babel-eslint to version 7.0.0
https://greenkeeper.io/
2016-09-28 02:44:36 +10:00
Max Guglielmi e276729f1d Improved sort column types handling 2016-09-25 23:44:41 +10:00
Max Guglielmi b882404fe3 Removed col_date_type option from test-empty-cells-filtering 2016-09-25 12:16:42 +10:00
Max Guglielmi e73471e10a Fixed unit tests 2016-09-24 22:17:01 +10:00
Max Guglielmi 07ba2b7718 Merged master in 2016-09-22 14:29:44 +10:00
koalyptus 6f1742d412 Merge pull request #299 from koalyptus/issue-298-calc-broken
Issue 298 calc broken
2016-09-22 14:10:51 +10:00
Max Guglielmi 91b72ed3a2 Fixed broken column calculation extension (continued) 2016-09-22 14:01:50 +10:00
Max Guglielmi 36e6a92fb5 Fixed broken column calculation extension... 2016-09-22 13:54:28 +10:00
Max Guglielmi 8b0bad54cc Fixed tests 2016-09-21 20:24:36 +10:00
Max Guglielmi 0be164c99f Fixed demos 2016-09-21 15:35:45 +10:00
Max Guglielmi 8fa502b2c4 Merged master in, added doco comments to dateType 2016-09-20 23:45:09 +10:00
koalyptus 494e4656ef Merge pull request #296 from koalyptus/issue-295-grouped-headers-popup-filters
Addressing #295
2016-09-20 13:57:06 +10:00
Max Guglielmi 033a6516cf Initial commit 2016-09-20 13:40:38 +10:00
Max Guglielmi bfe7293619 Re-refactored number type, continued 2016-09-19 20:35:34 +10:00
Max Guglielmi 7ecb53a701 Re-refactored number type 2016-09-19 17:37:45 +10:00
Max Guglielmi a0707554bb Continued date 2016-09-17 19:15:25 +10:00
Max Guglielmi d656ec90b0 Continued sort adapter 2016-09-15 23:39:43 +10:00
Max Guglielmi c70aa29523 Continued date type 2016-09-14 18:03:45 +10:00
Max Guglielmi a3c4f2158b Started date type 2016-09-14 00:30:18 +10:00
Max Guglielmi 035801dc7e Initial commit 2016-09-11 00:07:46 +10:00
koalyptus 08b244cbc4 Merge pull request #293 from npmcdn-to-unpkg-bot/npmcdn-to-unpkg
Replace npmcdn.com with unpkg.com
2016-09-08 09:47:04 +10:00
npmcdn-to-unpkg-bot a29c10099e Replace npmcdn.com with unpkg.com 2016-09-07 14:13:49 +01:00
koalyptus eb857e3766 Merge pull request #292 from koalyptus/issue-197-index-js
Added index.js
2016-09-07 21:44:11 +10:00
Max Guglielmi 51453d6191 Added index.js 2016-09-07 21:37:22 +10:00
koalyptus 90bc10b52a Merge pull request #291 from koalyptus/issue-264-sortable-adapter
Issue 264 sortable adapter
2016-09-06 11:54:06 +10:00
Max Guglielmi 32ea4a28cc Finalised sortable table adapter 2016-09-06 11:45:27 +10:00
Max Guglielmi a0019df507 Started adapterSortabletable doco 2016-09-05 23:05:20 +10:00
Max Guglielmi 2bed4c656a Finalised grid layout doco 2016-09-05 19:39:57 +10:00
koalyptus f394ef236a Merge pull request #290 from koalyptus/issue-264-filters-visibility
Added comments for auto-generated docs
2016-09-04 18:30:03 +10:00
Max Guglielmi 37c6b70f7e Added comments for auto-generated docs 2016-09-04 18:17:54 +10:00
koalyptus f0607403c8 Merge pull request #289 from koalyptus/issue-264-cols-visibility
Issue 264 cols visibility
2016-09-03 23:40:53 +10:00
Max Guglielmi af75fe5236 Continued commenting for auto-documentation 2016-09-03 23:30:31 +10:00
Max Guglielmi b20d3c1726 Initial commit 2016-09-03 13:19:55 +10:00
koalyptus 35b2b2d173 Merge pull request #288 from koalyptus/issue-264-advanced-grid
initial commit
2016-09-02 19:57:01 +10:00
Max Guglielmi c723b962bf initial commit 2016-09-02 19:26:21 +10:00
koalyptus 84b5287d73 Merge pull request #287 from koalyptus/refactor-col-ops
Refactor col ops
2016-09-02 13:41:03 +10:00
Max Guglielmi aee9c11551 Fixed doco 2016-09-02 13:32:59 +10:00
Max Guglielmi a173feb26f Started ColOps 2016-09-01 18:27:02 +10:00
Max Guglielmi 6d32d6b5bd Moved clear button CSS class definition in ClearButton class 2016-09-01 18:07:24 +10:00
koalyptus 8ab9fca0e1 Merge pull request #286 from koalyptus/issue-264-autodoc
Finalised TableFilter documentation
2016-08-31 21:18:55 +10:00
Max Guglielmi 7ea7e5be5c Finalised TableFilter documentation 2016-08-31 21:13:01 +10:00
koalyptus 9e43398ab2 Merge pull request #285 from koalyptus/issue-264-autodoc
Issue 264 autodoc
2016-08-29 19:11:20 +10:00
Max Guglielmi 17ce8759ac Continued documentation for TableFilter 2016-08-29 19:03:32 +10:00
Max Guglielmi 3fb33c3a3d Merge branch 'master' into issue-264-autodoc 2016-08-24 14:23:26 +10:00
koalyptus c5c17c1659 Merge pull request #282 from archisgore/master
URL Encode State Hash
2016-08-23 15:14:04 +10:00
Archis Gore 03a5d251a1 Bumped package version
And ran grunt to update some files,
as well as validate all tests.
2016-08-22 20:44:06 -07:00
Archis Gore fb2f201f29 URL Encode State Hash
You'll notice a mild asymmetry in how hash was
saved vs retrieved.

The retrieval was:
    JSON.parse(decodeUrlComponent(hash))

The save was:
    JSON.stringify(hash)

I modified it to:
    JSON.stringify(encodeUrlComponent(hash))

The reason I noticed this is in one of my apps,
I wanted to be able to copy/share a stateful filter URL.

However without the url encoding, those auto-parsers
of URLs were missing the full filter.

TESTING CONDUCTED:
1. Updated the Hash unit tests to both parse the
   encoded string, as well as generate it.

2. Ran "grunt", which has built/tested/jslinted
   the code.
2016-08-22 09:31:03 -07:00
koalyptus 48ce8bf3db Merge pull request #281 from koalyptus/issue-264-autodoc
Issue 264 autodoc
2016-08-17 17:50:55 +10:00
Max Guglielmi e770b13320 Additional comments in TableFilter 2016-08-17 17:31:41 +10:00
Max Guglielmi 900e5b1b2e Merge branch 'master' into issue-264-autodoc 2016-08-17 16:48:19 +10:00
koalyptus a14a27a920 Merge pull request #280 from koalyptus/issue-264-autodoc
Continued TableFilter
2016-08-14 14:23:52 +10:00
Max Guglielmi ed2f638bf2 Continued TableFilter 2016-08-14 14:14:52 +10:00
koalyptus 2ea8830ecf Merge pull request #279 from koalyptus/issue-264-autodoc
Started comments for auto-generated doc in TableFilter
2016-08-11 17:44:47 +10:00
Max Guglielmi 34cc60ace9 Started comments for auto-generated doc in TableFilter 2016-08-11 17:25:00 +10:00
koalyptus 4d08db4874 Merge pull request #277 from koalyptus/issue-264-doco
Issue 264 doco
2016-08-08 19:06:47 +10:00
Max Guglielmi d222f32674 Added comments to Storage for auto-generated documentation 2016-08-08 17:22:25 +10:00
Max Guglielmi 4f5fa9b708 Merged master in 2016-08-08 17:01:03 +10:00
koalyptus d5d2ec0554 Merge pull request #276 from koalyptus/greenkeeper-grunt-gh-pages-2.0.0
Update grunt-gh-pages to version 2.0.0 🚀
2016-08-08 09:22:14 +10:00
greenkeeperio-bot 60b85d2221 chore(package): update grunt-gh-pages to version 2.0.0
https://greenkeeper.io/
2016-08-08 02:24:36 +10:00
koalyptus 895d9978a0 Merge pull request #275 from koalyptus/issue-264-doco
Issue 264 doco
2016-08-07 01:01:41 +10:00
Max Guglielmi f43ccbfd50 Added comments to StatusBar for auto-generated documentation 2016-08-07 00:48:00 +10:00
Max Guglielmi 0b1256d571 Added comments to State for auto-generated documentation 2016-08-06 19:46:26 +10:00
koalyptus 3dc579f176 Merge pull request #274 from koalyptus/issue-264-doco
Issue 264 doco
2016-08-06 01:38:07 +10:00
Max Guglielmi dc7ffd0321 Shortened RowsCounter properties names 2016-08-06 01:26:53 +10:00
Max Guglielmi 912433a032 Replaced var with let in RowsCounter 2016-08-06 00:53:32 +10:00
koalyptus 3edf79b035 Merge pull request #272 from koalyptus/issue-264-doco
Issue 264 doco
2016-08-04 16:24:19 +10:00
Max Guglielmi b5dafdb173 Shortened PopupFilter properties names 2016-08-04 16:11:19 +10:00
Max Guglielmi 10f843430d Added comments to PopupFilter for auto-generated documentation 2016-08-04 15:40:02 +10:00
Max Guglielmi 96ded0a079 Merged master in 2016-08-04 12:43:57 +10:00
koalyptus 31891cafa3 Merge pull request #268 from koalyptus/greenkeeper-grunt-esdoc-0.0.4
Update grunt-esdoc to version 0.0.4 🚀
2016-08-04 12:29:20 +10:00
greenkeeperio-bot 5639b16594 chore(package): update grunt-esdoc to version 0.0.4
https://greenkeeper.io/
2016-08-03 09:08:35 +10:00
Max Guglielmi 330755f78c Stashing changes 2016-08-01 09:28:33 +10:00
koalyptus bb34fa1ded Merge pull request #267 from koalyptus/issue-264-doco
Issue 264 doco
2016-07-31 22:03:27 +10:00
Max Guglielmi 01a34e082c Added comments to paging 2016-07-31 21:49:38 +10:00
Max Guglielmi 8c3597be4b Fixed no results container width for all browsers 2016-07-31 18:36:47 +10:00
Max Guglielmi 3fec7e3562 Merge branch 'master' into issue-264-doco 2016-07-31 18:17:34 +10:00
koalyptus c11674178e Merge pull request #266 from koalyptus/issue-264-doco
Issue 264 doco
2016-07-30 18:10:47 +10:00
Max Guglielmi 5e316bc778 Added tests for searching numeric columns with strings 2016-07-30 17:59:08 +10:00
Max Guglielmi a962c04213 Fixed no results container width calculation 2016-07-30 16:45:58 +10:00
Max Guglielmi 8c29e2c51d Merge branch 'master' into issue-264-doco 2016-07-28 17:37:38 +10:00
Max Guglielmi d5ee78a0ff Aligned comment in Loader 2016-07-28 17:37:03 +10:00
koalyptus 7616498fa6 Merge pull request #265 from koalyptus/issue-264-doco
Added comments for doco to HightlightKeyword and Loader
2016-07-27 18:27:35 +10:00
Max Guglielmi 2f042e68dd Added comments for doco to HightlightKeyword and Loader 2016-07-27 17:21:30 +10:00
koalyptus c0c0f1925b Merge pull request #262 from koalyptus/misc-refactor
Added documentation badge
2016-07-23 19:34:18 +10:00
Max Guglielmi a14bb9d6b8 Added documentation badge 2016-07-23 19:24:21 +10:00
koalyptus 82046dcbee Merge pull request #261 from koalyptus/misc-refactor
Misc refactor
2016-07-23 19:00:04 +10:00
Max Guglielmi 714fa5d91a Grunted 2016-07-23 18:48:15 +10:00
Max Guglielmi 04d854c669 Bumped version 2016-07-23 18:35:10 +10:00
Max Guglielmi fb56fab0c7 Added comments for autogenerated documentation (hash, help) 2016-07-23 18:34:19 +10:00
koalyptus d52e58ec74 Merge pull request #259 from archisgore/master
Store the Sync wrapper in a variable for clean removal.
2016-07-15 14:15:52 +10:00
Archis Gore be23ac7285 Bumped up package version 2016-07-14 21:05:00 -07:00
Archis Gore e1e56daac0 Ran full grunt - updated build dates apparently. 2016-07-14 21:03:45 -07:00
Archis Gore 21d45aa6b6 Removed whitespaces 2016-07-14 20:19:15 -07:00
Archis Gore 8d7a7d77e6 Responded to feedback
1. Moved comment above a line to ensure that
   maximum line length of 80 characters is not breached.

2. Removed a mistaken ()=> which was left behind (that would have
   introduced the exact problem this change was intended to solve.)
2016-07-14 15:11:58 -07:00
Archis Gore 86ef087310 Store the Sync wrapper in a variable for clean removal.
This commit primarily fixes this issue:
https://github.com/koalyptus/TableFilter/issues/258

The fix here is to store a Sync call closed over "this" straight within
the object we're referencing. This having access to that object, we can
always retrieve the exact function reference/pointer/instance for removal
from handling events.
2016-07-13 20:06:58 -07:00
koalyptus 0775470b49 Merge pull request #256 from koalyptus/greenkeeper-babel-eslint-6.1.2
Update babel-eslint to version 6.1.2 🚀
2016-07-10 17:21:51 +10:00
greenkeeperio-bot f63d15e0a3 chore(package): update babel-eslint to version 6.1.2
https://greenkeeper.io/
2016-07-10 01:46:55 +10:00
koalyptus 969824c029 Merge pull request #255 from koalyptus/issue-197-grid-layout-refactor
Issue 197 grid layout refactor
2016-07-09 22:02:56 +10:00
Max Guglielmi 3899aee53c Continued refactoring grid layout 2016-07-09 21:51:32 +10:00
koalyptus e92e96b828 Merge pull request #254 from koalyptus/greenkeeper-babel-eslint-6.1.1
Update babel-eslint to version 6.1.1 🚀
2016-07-09 17:05:59 +10:00
greenkeeperio-bot 6e009e84d0 chore(package): update babel-eslint to version 6.1.1
https://greenkeeper.io/
2016-07-09 04:30:36 +10:00
koalyptus 1405e9728f Merge pull request #252 from koalyptus/greenkeeper-grunt-eslint-19.0.0
Update grunt-eslint to version 19.0.0 🚀
2016-07-03 20:37:34 +10:00
greenkeeperio-bot 1c44fc970b chore(package): update grunt-eslint to version 19.0.0
https://greenkeeper.io/
2016-07-02 22:02:45 +10:00
Max Guglielmi 9594b9de50 Removed commented out code 2016-07-02 20:30:36 +10:00
Max Guglielmi 96237553bd Initial commit 2016-07-02 20:25:23 +10:00
koalyptus 49f55fc751 Merge pull request #251 from koalyptus/issue-246-callback-fired-twice
Issue 246 callback fired twice
2016-07-02 14:48:30 +10:00
Max Guglielmi fa271c5445 Fixed failing unit test 2016-07-02 14:43:07 +10:00
Max Guglielmi b61bac1494 Uncommented out code 2016-07-02 14:09:43 +10:00
Max Guglielmi 603de740a3 Fixed checklist option click event 2016-07-02 14:06:12 +10:00
koalyptus 4134359406 Merge pull request #249 from koalyptus/issue-246-callback-fired-twice
Issue 246 callback fired twice
2016-06-25 22:20:02 +10:00
Max Guglielmi f135d3776d Issue 245 fix, sort arrow making header jump 2016-06-25 22:07:58 +10:00
Max Guglielmi d031e31c0c Fixed on_after_filter callback fired twice from checklist filter 2016-06-25 21:19:58 +10:00
Max Guglielmi 6b8783b830 Initial commit 2016-06-24 17:48:04 +10:00
koalyptus 9a7f9296d0 Merge pull request #248 from koalyptus/greenkeeper-babel-eslint-6.1.0
Update babel-eslint to version 6.1.0 🚀
2016-06-23 09:17:55 +10:00
greenkeeperio-bot aabf116a3a chore(package): update babel-eslint to version 6.1.0
https://greenkeeper.io/
2016-06-23 06:43:30 +10:00
koalyptus e5b6115b54 Merge pull request #247 from koalyptus/greenkeeper-babel-eslint-6.0.5
Update babel-eslint to version 6.0.5 🚀
2016-06-21 11:02:26 +10:00
greenkeeperio-bot 837a266d74 chore(package): update babel-eslint to version 6.0.5
https://greenkeeper.io/
2016-06-21 07:18:54 +10:00
koalyptus 4b11f2ddfa Merge pull request #244 from koalyptus/issue-243-grid-layout-toggling
More desensive coding in sort feature
2016-06-19 15:22:28 +10:00
Max Guglielmi c5fd43d150 More desensive coding in sort feature 2016-06-19 15:07:49 +10:00
koalyptus 856bd7d81a Merge pull request #242 from koalyptus/issue-241-on-filter-loaded
Addressed issue 241, can filter in filters loaded callback
2016-06-15 11:47:18 +10:00
Max Guglielmi 35579453a6 Addressed issue 241, can filter in filters loaded callback 2016-06-15 11:29:20 +10:00
koalyptus bb289549c8 Merge pull request #240 from koalyptus/issue-233-dom-changes-unit-tests
Issue 233 dom changes unit tests
2016-06-13 19:28:39 +10:00
Max Guglielmi c4b3579e08 Added DOM changes unit tests 2016-06-13 19:17:13 +10:00
Max Guglielmi 7c2eb8ad4c Merged issue-197-misc-refactor in 2016-06-13 12:49:27 +10:00
Max Guglielmi d0360c01e5 Contunued 2016-06-13 11:01:20 +10:00
Max Guglielmi e4ab8be82f Initial commit 2016-06-10 23:03:46 +10:00
Max Guglielmi 794a40a11e Added comments to constants for auto-generated docs 2016-06-05 18:54:14 +10:00
Max Guglielmi 6070d9b52f Renamed GridLayout properties 2016-06-05 18:44:21 +10:00
koalyptus 1cd4f9e9b8 Merge pull request #239 from koalyptus/issue-238-non-empty-option-persistence
Issue 238 non empty option persistence
2016-06-05 12:36:51 +10:00
Max Guglielmi d845e7c8e4 Added missing starter.html 2016-06-05 12:19:47 +10:00
Max Guglielmi a965265977 Added test case 2016-06-05 12:15:34 +10:00
Max Guglielmi 0172dea15f Added comments to checklist module for autogenerated docs 2016-06-05 01:41:44 +10:00
Max Guglielmi 0e403e6f09 Fixed empty-option and non-empty-option persistence 2016-06-05 00:28:55 +10:00
koalyptus cd9964db46 Merge pull request #236 from koalyptus/issue-197-misc
Issue 197 misc
2016-06-02 16:09:43 +10:00
Max Guglielmi 2e2515586e Refactored Event module 2016-06-02 14:13:56 +10:00
Max Guglielmi f5848c7b8e Enhanced removeNbFormat helper 2016-06-02 13:31:58 +10:00
koalyptus 9c094e6efe Merge pull request #235 from koalyptus/issue-197-misc
Issue 197 misc
2016-05-31 20:15:33 +10:00
Max Guglielmi 8e5aba04e2 Removed unused TableFilter properties, added eslint rule 2016-05-31 19:22:21 +10:00
Max Guglielmi 42842b52b5 Merge branch 'master' into issue-197-misc 2016-05-31 16:50:02 +10:00
koalyptus 403bef7920 Merge pull request #234 from koalyptus/greenkeeper-grunt-esdoc-0.0.3
Update grunt-esdoc to version 0.0.3 🚀
2016-05-31 16:47:51 +10:00
greenkeeperio-bot 52f8cbd55d chore(package): update grunt-esdoc to version 0.0.3
https://greenkeeper.io/
2016-05-31 11:25:42 +10:00
koalyptus 9790a1ef84 Merge pull request #232 from koalyptus/issue-197-misc
Issue 197 misc
2016-05-29 20:57:28 +10:00
Max Guglielmi 3f58be9f8c Finalised hasGrid removal 2016-05-29 20:44:27 +10:00
Max Guglielmi 7c6ec56fa3 Renamed _hasGrid to initialized and hasGrid to isInitialized 2016-05-27 17:40:22 +10:00
koalyptus 80ff22c02b Merge pull request #230 from koalyptus/issue-197-misc
Issue 197 misc
2016-05-26 17:43:03 +10:00
Max Guglielmi 4095fcf888 Added unit tests to rowscounter module 2016-05-26 17:23:21 +10:00
Max Guglielmi b23aeea53a Killed the nbVisibleRows property on TableFilter 2016-05-26 14:36:36 +10:00
Max Guglielmi 73f72ce959 Killed matchCase TableFilter property replaced by caseSensitive 2016-05-26 12:21:27 +10:00
koalyptus 6134ef3293 Merge pull request #229 from koalyptus/issue-197-misc
Issue 197 misc
2016-05-25 17:44:47 +10:00
Max Guglielmi 7d84c7d09e Refactored dom module 2016-05-25 17:31:53 +10:00
Max Guglielmi 9fec6eb6ef Started refactoring Dom module 2016-05-24 18:42:11 +10:00
Max Guglielmi 35f23d46eb Merge branch 'master' into issue-197-misc 2016-05-24 12:55:48 +10:00
koalyptus 31473c6537 Merge pull request #227 from koalyptus/greenkeeper-webpack-1.13.1
chore(package): update webpack to version 1.13.1
2016-05-23 10:52:49 +10:00
koalyptus 971408cecd Merge pull request #226 from koalyptus/issue-197-misc
Issue 197 misc
2016-05-21 11:49:10 +10:00
Max Guglielmi 3434185dbe Refactored date helper module 2016-05-21 11:33:49 +10:00
Max Guglielmi b6c4fd6675 Refactored string module 2016-05-20 18:08:39 +10:00
Max Guglielmi 64f197866a Refactored helpers module 2016-05-20 17:21:42 +10:00
Max Guglielmi f3fb49bd3d Refactored sort module 2016-05-20 17:14:05 +10:00
Max Guglielmi c849418e2f Refactored array module 2016-05-20 16:58:54 +10:00
greenkeeperio-bot 8c1b3014a6 chore(package): update webpack to version 1.13.1
https://greenkeeper.io/
2016-05-20 16:53:48 +10:00
Max Guglielmi e3b9525091 Updated README as per issue 225 2016-05-20 16:41:20 +10:00
Max Guglielmi a3c554aab8 Merge branch 'master' into issue-197-misc 2016-05-20 16:33:28 +10:00
koalyptus 27ce9873ec Merge pull request #223 from koalyptus/issue-220
Removed nbRows property and replaced its usage by getRowsNb method
2016-05-19 17:49:23 +10:00
Max Guglielmi dbf44d488a Removed nbRows property and replaced its usage by getRowsnb method 2016-05-19 17:38:18 +10:00
koalyptus 457ad1032a Merge pull request #222 from koalyptus/issue-217-filtering
Issue 217 filtering
2016-05-19 12:57:27 +10:00
Max Guglielmi bc8e3c34a8 Prepared build 2016-05-19 12:50:18 +10:00
Max Guglielmi b38f216409 Fixed issue 217 2016-05-19 12:35:27 +10:00
koalyptus 7f30796d60 Merge pull request #216 from koalyptus/greenkeeper-webpack-dev-server-1.14.1
chore(package): update webpack-dev-server to version 1.14.1
2016-05-16 15:12:51 +10:00
greenkeeperio-bot 6a9e89c73a chore(package): update webpack-dev-server to version 1.14.1
https://greenkeeper.io/
2016-05-16 09:10:01 +10:00
koalyptus 62894bdf64 Merge pull request #215 from koalyptus/issue-197-misc
Removed unused TableFilter properties related to legacy persistence implementation
2016-05-15 19:30:32 +10:00
Max Guglielmi 540b3b9e2a Removed unused TableFilter properties related to legacy persistence implementation 2016-05-15 19:19:30 +10:00
koalyptus d4b14b13a7 Merge pull request #214 from koalyptus/issue-197-misc
Issue 197 misc
2016-05-15 13:47:28 +10:00
Max Guglielmi 924884dfd0 Added eqeqeq eslint rule (2) 2016-05-15 13:40:32 +10:00
Max Guglielmi be3903d2eb Added eqeqeq eslint rule 2016-05-15 13:33:16 +10:00
Max Guglielmi 0d58349432 Refactored types module 2016-05-15 12:56:12 +10:00
koalyptus 25b1a6cd5b Merge pull request #213 from koalyptus/issue-197-feature-base-class-for-extensions
Issue 197 feature base class for extensions
2016-05-14 22:30:05 +10:00
Max Guglielmi fcdda9269d Added sorceType parserOptions to eslintrc file to fix build 2016-05-14 22:23:13 +10:00
Max Guglielmi d5dcc38cc9 Finalised extending extensions with Feature base class 2016-05-14 22:09:28 +10:00
Max Guglielmi 6f3fe2eb23 Started making extension extend Feature base class 2016-05-14 20:04:00 +10:00
koalyptus 49664d8dfc Merge pull request #212 from koalyptus/issue-210-fix-obsolete-link-in-readme
built package
2016-05-12 21:44:21 +10:00
Max Guglielmi 03eb1ecb38 built package 2016-05-12 21:37:41 +10:00
koalyptus 47ff546182 Merge pull request #208 from koalyptus/issue-197-misc-refactoring
Fixed IE regression related to drop-down getValues method
2016-05-08 18:13:47 +10:00
Max Guglielmi d3aac7476e Fixed IE regression related to drop-down getValues method 2016-05-08 18:03:39 +10:00
koalyptus 9d801d2f83 Merge pull request #207 from koalyptus/issue-197-misc-refactoring
Missed window refs
2016-05-08 16:31:11 +10:00
Max Guglielmi a1317ec130 Missed window refs 2016-05-08 16:14:40 +10:00
koalyptus ea6344e37a Merge pull request #206 from koalyptus/issue-197-misc-refactoring
Issue 197 misc refactoring
2016-05-08 15:44:49 +10:00
Max Guglielmi 075427c37c Added root module 2016-05-08 15:33:19 +10:00
Max Guglielmi f67bb8e15c Added root module 2016-05-08 15:26:52 +10:00
koalyptus d558667586 Merge pull request #205 from koalyptus/issue-197-misc-refactoring
Issue 197 misc refactoring
2016-05-08 13:22:39 +10:00
Max Guglielmi 55cab197cc Added starter.html file 2016-05-08 13:10:02 +10:00
Max Guglielmi ec44825c13 Added index.js for npm 2016-05-08 13:05:39 +10:00
Max Guglielmi 472d349689 Fixed issue 204, made selectOptions in checklist feature more defensive 2016-05-08 12:53:58 +10:00
Max Guglielmi dd3fb09da2 Extended const file 2016-05-08 11:48:51 +10:00
Max Guglielmi 96399df765 Removed commented out code 2016-05-07 22:08:43 +10:00
Max Guglielmi 8a2a7c7ba7 Created constants file, added filter types constants 2016-05-07 21:59:42 +10:00
Max Guglielmi cf34009205 Merge branch 'master' into issue-197-misc-refactoring 2016-05-07 20:27:04 +10:00
koalyptus 03aaf7f650 Merge pull request #203 from koalyptus/issue-202-search-term
Issue 202 search term
2016-05-07 20:09:31 +10:00
Max Guglielmi b3d2ead151 Fixed failing single filter tests 2016-05-07 19:54:22 +10:00
Max Guglielmi 4965cd5360 Added unit tests 2016-05-07 19:20:42 +10:00
Max Guglielmi 9a694ba263 Fixed search inconsistency with numeric column types 2016-05-07 14:33:17 +10:00
koalyptus e75e6897fd Merge pull request #201 from koalyptus/issue-197-misc-refactoring
Issue 197 misc refactoring
2016-05-04 22:13:55 +10:00
Max Guglielmi 5f667f733f Added getValues method to select and checklist filter types + added unit tests 2016-05-04 22:02:22 +10:00
Max Guglielmi bebcd45647 Merge branch 'master' into issue-197-misc-refactoring 2016-05-04 20:03:45 +10:00
koalyptus 0e626a3a62 Merge pull request #172 from koalyptus/greenkeeper-grunt-1.0.1
Update grunt to version 1.0.1 🚀
2016-05-04 20:02:42 +10:00
Max Guglielmi 762eb0be14 Updated babel-core dependency 2016-05-04 19:55:39 +10:00
Max Guglielmi 5a5f89cd52 Upgraded node version in travis.yaml 2016-05-04 19:48:19 +10:00
Max Guglielmi 6afef2915b Merged master in and fixed conflicts 2016-05-04 19:34:09 +10:00
koalyptus 610974e1c9 Merge pull request #198 from koalyptus/issue-197-misc-refactoring
Removed Evt object
2016-05-01 20:14:27 +10:00
Max Guglielmi 88183ac770 Removed Evt object 2016-05-01 19:57:23 +10:00
koalyptus 2b3a728d91 Merge pull request #196 from koalyptus/issue-177-extend-persistence
Issue 177 extend persistence
2016-04-30 13:10:17 +10:00
Max Guglielmi 88bcc4c3b5 Updated README 2016-04-30 12:58:15 +10:00
Max Guglielmi 1ee1e306fd Started decommissioning legacy persistence implementation 2016-04-30 11:45:04 +10:00
Max Guglielmi 7c97b70873 Merge branch 'master' into issue-177-extend-persistence 2016-04-30 10:40:22 +10:00
Max Guglielmi 3be600a070 Synced with Greenkeeper 2016-04-29 17:20:19 +10:00
koalyptus 74d0e99a1a Merge pull request #194 from koalyptus/issue-177-extend-persistence
Issue 177 extend persistence
2016-04-28 14:15:24 +10:00
Max Guglielmi ac8337fe4b Fixing issue #193 2016-04-28 14:05:24 +10:00
Max Guglielmi 578b1c7313 Merge branch 'master' into issue-177-extend-persistence 2016-04-28 13:39:10 +10:00
koalyptus 76d53b1001 Merge pull request #192 from koalyptus/greenkeeper-clean-webpack-plugin-0.1.9
chore(package): update clean-webpack-plugin to version 0.1.9
2016-04-27 17:50:01 +10:00
greenkeeperio-bot deef9aad5e chore(package): update clean-webpack-plugin to version 0.1.9
https://greenkeeper.io/
2016-04-27 15:59:01 +10:00
koalyptus 02668ed843 Merge pull request #191 from koalyptus/issue-177-extend-persistence
Fixed issue with filters visibility persistence event
2016-04-26 19:36:18 +10:00
Max Guglielmi 361d90cae0 Fixed issue with filters visibility persistence event 2016-04-26 19:22:02 +10:00
greenkeeperio-bot 3336664b70 chore(package): update grunt to version 1.0.1
https://greenkeeper.io/
2016-04-26 16:17:56 +10:00
koalyptus df1028acbc Merge pull request #190 from koalyptus/greenkeeper-babel-eslint-6.0.4
Update babel-eslint to version 6.0.4 🚀
2016-04-26 16:17:41 +10:00
greenkeeperio-bot 56c0f8bd36 chore(package): update babel-eslint to version 6.0.4
https://greenkeeper.io/
2016-04-26 00:01:23 +02:00
koalyptus d75787c21a Merge pull request #189 from koalyptus/issue-177-extend-persistence
Issue 177 extend persistence
2016-04-24 19:24:04 +02:00
Max Guglielmi 2a89916681 Prod build 2016-04-24 19:07:55 +02:00
Max Guglielmi b7156566ce Fixed tests 2016-04-24 19:00:36 +02:00
Max Guglielmi e188110cb2 Updated relevant unit tests for filters persistence 2016-04-24 18:47:01 +02:00
Max Guglielmi 574a371ba4 Started filters visibility persistence 2016-04-24 17:12:45 +02:00
Max Guglielmi d33824a508 Merge branch 'master' into issue-177-extend-persistence 2016-04-24 14:51:31 +02:00
koalyptus 31d0f843f7 Merge pull request #188 from koalyptus/greenkeeper-babel-core-6.7.7
chore(package): update babel-core to version 6.7.7
2016-04-23 22:56:55 +02:00
koalyptus 096f7027a2 Merge pull request #186 from koalyptus/greenkeeper-script-loader-0.7.0
Update script-loader to version 0.7.0 🚀
2016-04-22 15:11:25 +02:00
greenkeeperio-bot db33c6b26d chore(package): update script-loader to version 0.7.0
https://greenkeeper.io/
2016-04-21 19:50:26 +02:00
greenkeeperio-bot c977357b25 chore(package): update babel-core to version 6.7.7
https://greenkeeper.io/
2016-04-21 05:51:46 +02:00
koalyptus 40cdf1c64e Merge pull request #185 from koalyptus/issue-177-extend-persistence
Issue 177 extend persistence
2016-04-20 17:06:48 +02:00
Max Guglielmi 638892fd14 Merged master in 2016-04-20 16:30:41 +02:00
Max Guglielmi 1d29ec9f81 Merge branch 'master' into issue-177-extend-persistence 2016-04-20 16:04:12 +02:00
Max Guglielmi 16d221913d Upadated unit tests 2016-04-20 16:03:35 +02:00
Max Guglielmi f3760a0dcd Continued columns visibility persistence 2016-04-20 10:41:20 +02:00
koalyptus 73c7a6eec6 Merge pull request #183 from koalyptus/greenkeeper-babel-eslint-6.0.3
Update babel-eslint to version 6.0.3 🚀
2016-04-20 09:53:27 +02:00
greenkeeperio-bot c5347ae4fe chore(package): update babel-eslint to version 6.0.3
https://greenkeeper.io/
2016-04-20 05:46:28 +02:00
Max Guglielmi ae6c2eee6b Continued columns visibility persistence 2016-04-19 15:28:37 +02:00
Max Guglielmi 29d58d3a45 Continued columns visibility persistence 2016-04-18 11:04:50 +02:00
Max Guglielmi 0900d81dfd Started columns visibility persistence 2016-04-17 11:59:52 +02:00
Max Guglielmi f48a16e954 Merge branch 'master' into issue-177-extend-persistence 2016-04-17 11:28:22 +02:00
koalyptus 01b4cf5f3a Merge pull request #181 from koalyptus/greenkeeper-grunt-eslint-18.1.0
Update grunt-eslint to version 18.1.0 🚀
2016-04-15 17:23:18 +02:00
greenkeeperio-bot 88de0ba17c chore(package): update grunt-eslint to version 18.1.0
http://greenkeeper.io/
2016-04-15 15:05:22 +02:00
koalyptus 7dd8a3189a Merge pull request #179 from koalyptus/issue-177-extend-persistence
Issue 177 extend persistence
2016-04-14 10:35:57 +02:00
Max Guglielmi ed840793b4 Updated examples 2016-04-14 10:22:44 +02:00
Max Guglielmi 0004afe9bb dist build 2016-04-13 19:03:05 +02:00
Max Guglielmi 711f3a696b Updated unit tests 2016-04-13 18:37:56 +02:00
Max Guglielmi 9156bdbb9d Finalised sort persistence 2016-04-13 18:28:12 +02:00
Max Guglielmi 139eaf998e continued sort persistence 2016-04-12 18:39:20 +02:00
Max Guglielmi 974c9c95e9 Initial commit 2016-04-12 09:49:54 +02:00
koalyptus 87d63f04ae Merge pull request #176 from koalyptus/issue-43-persistence
Issue 43 persistence
2016-04-10 10:58:39 +02:00
Max Guglielmi eb9374f48d Page number is now updated on filters clearing 2016-04-10 10:46:20 +02:00
Max Guglielmi 531198c81f Merge branch 'master' into issue-43-persistence 2016-04-10 10:33:02 +02:00
koalyptus 6d92ea3979 Merge pull request #175 from koalyptus/issue-43-persistence
Issue 43 persistence
2016-04-08 18:36:33 +02:00
Max Guglielmi 2eae85d950 Rebuilt demos 2016-04-08 18:22:58 +02:00
Max Guglielmi 9045e85484 Added activateFilter public method 2016-04-08 18:19:52 +02:00
Max Guglielmi 8c2108b3ab Added unit tests 2016-04-08 17:43:55 +02:00
Max Guglielmi f731b6c79c Added cookie persistence 2016-04-08 12:13:29 +02:00
Max Guglielmi 2656435d00 Continued storage class 2016-04-07 18:34:25 +02:00
Max Guglielmi 680e13840d Initial commit 2016-04-07 12:13:54 +02:00
koalyptus 135af7bfda Merge pull request #173 from koalyptus/issue-163-active-filter
Issue 163 active filter
2016-04-06 09:15:18 +02:00
Max Guglielmi ccdde872f4 Updated API unit tests 2016-04-06 08:50:32 +02:00
Max Guglielmi 3e13e787a1 Added getActiveFilterId and setActiveFilterId methods 2016-04-05 18:09:21 +02:00
Max Guglielmi 50b7ab616b Initial commit 2016-04-05 10:51:56 +02:00
koalyptus 4c416d5fbf Merge pull request #170 from koalyptus/issue-169-responsive-table
Issue 169 responsive table
2016-04-04 11:33:20 +02:00
Max Guglielmi 091bdf267a Prod build 2016-04-04 11:22:32 +02:00
Max Guglielmi 48b0fd27f6 Added responsive table option, updated unit tests 2016-04-04 11:08:57 +02:00
koalyptus aec61c390d Merge pull request #168 from koalyptus/greenkeeper-babel-eslint-6.0.2
Update babel-eslint to version 6.0.2 🚀
2016-04-03 22:32:03 +02:00
greenkeeperio-bot 8513160cc7 chore(package): update babel-eslint to version 6.0.2
http://greenkeeper.io/
2016-04-01 10:20:02 +11:00
koalyptus 1e0af118d1 Merge pull request #166 from koalyptus/issue-165-linked-filters-regression
Initial commit
2016-03-30 19:09:27 +11:00
Max Guglielmi 3c5511a28a Initial commit 2016-03-30 18:53:16 +11:00
koalyptus a8c8eab984 Merge pull request #164 from koalyptus/issue-162-gettext-performance-issue
Enhanced getText method, added test case
2016-03-29 18:26:39 +11:00
Max Guglielmi b22b0f663c Enhanced getText method, added test case 2016-03-29 18:18:03 +11:00
koalyptus c97bf15218 Merge pull request #161 from koalyptus/greenkeeper-babel-eslint-6.0.0
Update babel-eslint to version 6.0.0 🚀
2016-03-27 08:51:27 +11:00
greenkeeperio-bot 8b985f67fe chore(package): update babel-eslint to version 6.0.0
http://greenkeeper.io/
2016-03-26 15:02:00 +11:00
koalyptus 953c7b7e4e Merge pull request #152 from koalyptus/issue-135-remove-estraverse-dependency
Updated babel-core and removed estraverse dependencies
2016-03-24 17:53:52 +11:00
Max Guglielmi c58cee5fa7 Reverting to babel-eslint 2016-03-24 17:48:55 +11:00
Max Guglielmi 4fc67df95e Reverting to babel-eslint 3.1.30 2016-03-24 17:45:01 +11:00
Max Guglielmi dfc842b2ed Reverting to babel-eslint 2016-03-24 17:41:24 +11:00
Max Guglielmi 22ecda6411 Trying again 2016-03-24 17:30:53 +11:00
koalyptus 237531fd96 Merge pull request #159 from koalyptus/issue-155-highlight-keywords-fix
Issue 155 highlight keywords fix
2016-03-24 12:26:49 +11:00
Max Guglielmi 39b7a56491 Bumbed node_js version in travis.yaml 2016-03-24 12:16:02 +11:00
Max Guglielmi f38f05e15b Added a TODO 2016-03-24 12:07:32 +11:00
Max Guglielmi 2fb84174dd Removed commented out code 2016-03-24 10:56:59 +11:00
Max Guglielmi 8001582c2b Added unit tests 2016-03-24 10:52:23 +11:00
Max Guglielmi cda05accb5 Initial commit 2016-03-23 19:02:48 +11:00
koalyptus 2faac66509 Merge pull request #158 from koalyptus/issue-127-stateful-url
Fixed hash deep linking on Firefox
2016-03-21 18:43:44 +11:00
Max Guglielmi df5cd45da1 Fixed hash deep linking on Firefox 2016-03-21 18:36:46 +11:00
koalyptus e880368825 Merge pull request #157 from koalyptus/issue-127-stateful-url
Fixed help button regression due to feature module refactoring
2016-03-21 10:52:24 +11:00
Max Guglielmi 11fab705fa Fixed help button regression due to feature module refactoring 2016-03-21 10:41:21 +11:00
koalyptus 786d4cb476 Merge pull request #156 from koalyptus/issue-127-stateful-url
Issue 127 stateful url
2016-03-21 09:33:32 +11:00
Max Guglielmi 209d89582e Remove commented out code left-over 2016-03-21 09:25:17 +11:00
Max Guglielmi 6cd10dd9bf Addressing PR review 2016-03-20 23:02:12 +11:00
Max Guglielmi 250787391e Prepare build for PR 2016-03-20 22:53:10 +11:00
Max Guglielmi a62a41cbc4 Added hash unit tests 2016-03-20 22:44:41 +11:00
Max Guglielmi ea604b76ba Added state unit tests 2016-03-20 22:09:08 +11:00
Max Guglielmi 1e3f51db10 Added state unit tests 2016-03-20 22:07:52 +11:00
Max Guglielmi 4a8613f68b Added comments 2016-03-20 19:56:18 +11:00
Max Guglielmi e4a048fd2d Fixed circular events issue with state and hash 2016-03-20 16:15:15 +11:00
Max Guglielmi f45fae30ee Merged master in 2016-03-20 14:51:08 +11:00
Max Guglielmi 9e7253b0df Removed unused imports 2016-03-20 13:22:32 +11:00
Max Guglielmi a75e6902f8 splitted into state and hash modules 2016-03-20 01:10:59 +11:00
Max Guglielmi ad04da9051 Fixed tests 2016-03-18 17:58:32 +11:00
koalyptus 07c5ae827d Merge pull request #154 from andreyjamer/master
Changed babel config to fix plugin in IE<=10
2016-03-17 09:08:56 +11:00
Akulov Andrey c6ef352b9b Update package.json 2016-03-16 17:02:49 +05:00
Akulov Andrey b945191dfc Update package.json 2016-03-16 15:21:16 +05:00
Akulov Andrey 01027bae68 Update webpack.config.js 2016-03-16 15:18:36 +05:00
Max Guglielmi 6334667767 Renamed long custom event names, added hashchange event 2016-03-16 18:08:26 +11:00
Max Guglielmi b55bd0119a Continued stateful class 2016-03-15 18:18:51 +11:00
Max Guglielmi 975dc35059 Initial commit 2016-03-14 17:49:23 +11:00
Max Guglielmi b710c1216b Initial commit 2016-03-13 23:15:26 +11:00
Max Guglielmi 65dae9cd5b Updated babel-eslint 2016-03-13 17:20:38 +11:00
Max Guglielmi e924e1570b Updated babel-core and removed estraverse dependencies 2016-03-13 17:14:33 +11:00
koalyptus 7e9de15870 Merge pull request #150 from koalyptus/greenkeeper-babel-core-6.7.2
chore(package): update babel-core to version 6.7.2
2016-03-13 16:46:05 +11:00
koalyptus fcaccaaa5b Merge pull request #149 from koalyptus/greenkeeper-grunt-contrib-watch-1.0.0
Update grunt-contrib-watch to version 1.0.0 🚀
2016-03-13 10:21:37 +11:00
greenkeeperio-bot 1f26e468c9 chore(package): update grunt-contrib-watch to version 1.0.0
http://greenkeeper.io/
2016-03-13 09:16:26 +11:00
koalyptus 87232bf5dd Merge pull request #147 from koalyptus/issue-141-linked-filters-IE
Issue 141 linked filters ie
2016-03-11 17:08:47 +11:00
Max Guglielmi cbf1078b6c Added starter file 2016-03-11 17:03:57 +11:00
Max Guglielmi f9af8bf321 Generated build 2016-03-11 16:59:14 +11:00
Max Guglielmi 37d47a5adc Added unit tests 2016-03-11 16:55:42 +11:00
Max Guglielmi ff7ee786c3 Merge branch 'master' into issue-141-linked-filters-IE 2016-03-11 12:17:50 +11:00
Max Guglielmi c1a6cd9220 Initial commit for fixing linked filters with grid layout mode 2016-03-11 12:16:06 +11:00
greenkeeperio-bot f32b0291e8 chore(package): update babel-core to version 6.7.2
http://greenkeeper.io/
2016-03-11 10:05:19 +11:00
koalyptus 3d61bf5e20 Merge pull request #146 from koalyptus/greenkeeper-estraverse-4.2.0
Update estraverse to version 4.2.0 🚀
2016-03-11 09:36:13 +11:00
greenkeeperio-bot 31bbb61d5f chore(package): update estraverse to version 4.2.0
http://greenkeeper.io/
2016-03-11 08:56:35 +11:00
koalyptus 7017859b1f Merge pull request #145 from koalyptus/issue-141-linked-filters-IE
Issue 141 linked filters ie
2016-03-10 17:45:13 +11:00
Max Guglielmi fb90965444 Built and bumped version 2016-03-10 17:37:07 +11:00
Max Guglielmi 86722da61f Initial commit 2016-03-10 17:31:36 +11:00
koalyptus 6ebc378811 Merge pull request #144 from koalyptus/greenkeeper-babel-core-6.7.0
chore(package): update babel-core to version 6.7.0
2016-03-10 14:31:12 +11:00
greenkeeperio-bot c44371492d chore(package): update babel-core to version 6.7.0
http://greenkeeper.io/
2016-03-09 12:15:37 +11:00
koalyptus 9c9136f7f1 Merge pull request #143 from koalyptus/greenkeeper-grunt-contrib-stylus-1.2.0
chore(package): update grunt-contrib-stylus to version 1.2.0
2016-03-09 10:02:26 +11:00
greenkeeperio-bot fc5ceb2187 chore(package): update grunt-contrib-stylus to version 1.2.0
http://greenkeeper.io/
2016-03-09 08:47:06 +11:00
koalyptus fd5ae2e284 Merge pull request #138 from koalyptus/issue-110-grid-layout-no-headers
Initial commit
2016-03-06 21:33:30 +11:00
Max Guglielmi 70c1a4e384 Initial commit 2016-03-06 21:24:29 +11:00
koalyptus a066aa977e Merge pull request #137 from koalyptus/greenkeeper-babel-core-6.6.5
Greenkeeper babel core 6.6.5
2016-03-05 18:30:14 +11:00
Max Guglielmi c19b38a2df Merge branch 'master' into greenkeeper-babel-core-6.6.5 2016-03-05 18:25:07 +11:00
koalyptus f95f0eb749 Merge pull request #136 from koalyptus/greenkeeper-grunt-contrib-stylus-1.1.0
Greenkeeper grunt contrib stylus 1.1.0
2016-03-05 18:22:54 +11:00
Max Guglielmi 27ff11597b Merge branch 'master' into greenkeeper-grunt-contrib-stylus-1.1.0 2016-03-05 18:17:48 +11:00
koalyptus d37825eef2 Merge pull request #133 from koalyptus/greenkeeper-grunt-contrib-copy-1.0.0
Update grunt-contrib-copy to version 1.0.0 🚀
2016-03-05 18:15:25 +11:00
Max Guglielmi 9f5fba25e3 Trying estraverse-fb package to fix es-lint build error (https://github.com/eslint/eslint/issues/5476) 2016-03-05 18:09:17 +11:00
Max Guglielmi b7d61e714a Updating babel-eslint to 4.1.8 2016-03-05 18:06:01 +11:00
Max Guglielmi 7572d350ef Trying estraverse-fb package to fix es-lint build error (https://github.com/eslint/eslint/issues/5476) 2016-03-05 18:02:44 +11:00
Max Guglielmi 4f66b7410e Trying to fix build with babel-eslint 6.0.0-beta.1 2016-03-05 17:57:28 +11:00
Max Guglielmi e6725d3b63 Merged master in, fixed conflict 2016-03-05 17:32:10 +11:00
koalyptus c2f6bb5a7c Merge pull request #134 from koalyptus/greenkeeper-grunt-contrib-connect-1.0.0
Update grunt-contrib-connect to version 1.0.0 🚀
2016-03-05 17:27:23 +11:00
greenkeeperio-bot c81f3d5128 chore(package): update grunt-contrib-connect to version 1.0.0
http://greenkeeper.io/
2016-03-05 13:38:14 +11:00
greenkeeperio-bot 73c7a0a654 chore(package): update babel-core to version 6.6.5
http://greenkeeper.io/
2016-03-05 10:47:20 +11:00
greenkeeperio-bot 9c52832323 chore(package): update grunt-contrib-copy to version 1.0.0
http://greenkeeper.io/
2016-03-05 07:56:47 +11:00
greenkeeperio-bot 07f11c79e9 chore(package): update grunt-contrib-stylus to version 1.1.0
http://greenkeeper.io/
2016-03-05 04:39:36 +11:00
koalyptus 11519f76d1 Merge pull request #132 from koalyptus/greenkeeper-babel-core-6.6.4
chore(package): update babel-core to version 6.6.4
2016-03-04 09:10:50 +11:00
greenkeeperio-bot 10afa1c172 chore(package): update babel-core to version 6.6.4
http://greenkeeper.io/
2016-03-03 09:11:45 +11:00
koalyptus 44474c9ac8 Merge pull request #131 from koalyptus/issue-91-eslint
Issue 91 eslint
2016-03-01 13:09:49 +11:00
Max Guglielmi 0d41632c05 Merged master in again 2016-03-01 13:03:31 +11:00
Max Guglielmi d344f02484 Resolved conflicts 2016-03-01 12:56:47 +11:00
Max Guglielmi e540eabfc6 Merged master in 2016-03-01 12:49:49 +11:00
koalyptus a88d01b317 Merge pull request #130 from koalyptus/greenkeeper-babel-core-6.5.2
chore(package): update babel-core to version 6.5.2
2016-03-01 12:44:30 +11:00
Max Guglielmi 49307f42eb Merge branch 'master' into issue-91-eslint 2016-03-01 12:40:40 +11:00
Max Guglielmi b8993685f0 Included starter.html 2016-03-01 12:38:58 +11:00
Max Guglielmi 305d1d4679 Merged master in 2016-03-01 12:33:46 +11:00
koalyptus 791da3a5c3 Merge pull request #129 from koalyptus/greenkeeper-babel-preset-es2015-6.5.0
chore(package): update babel-preset-es2015 to version 6.5.0
2016-03-01 09:12:05 +11:00
koalyptus bd3db40a18 Merge pull request #128 from koalyptus/greenkeeper-babel-core-6.6.0
chore(package): update babel-core to version 6.6.0
2016-03-01 09:01:21 +11:00
greenkeeperio-bot 53b6405068 chore(package): update babel-core to version 6.6.0
http://greenkeeper.io/
2016-03-01 08:48:31 +11:00
greenkeeperio-bot 4ee7402f2c chore(package): update babel-preset-es2015 to version 6.5.0
http://greenkeeper.io/
2016-03-01 08:34:02 +11:00
greenkeeperio-bot d77cf15690 chore(package): update babel-core to version 6.5.2
http://greenkeeper.io/
2016-03-01 08:24:58 +11:00
Max Guglielmi 63076678d6 Fixed doco 2016-02-28 23:01:26 +11:00
Max Guglielmi 4a78062d89 Merge branch 'master' into issue-91-eslint 2016-02-28 20:59:51 +11:00
Max Guglielmi 52be1d6928 Added masx-statements to eslint 2016-02-28 20:59:01 +11:00
koalyptus a4d31faa3a Merge pull request #126 from koalyptus/greenkeeper-update-all
Update all dependencies 🌴
2016-02-28 20:34:31 +11:00
greenkeeperio-bot cef0d48ff1 chore(package): update dependencies
http://greenkeeper.io/
2016-02-28 18:46:49 +11:00
Max Guglielmi 25eba79a6b Merge branch 'master' into issue-91-eslint 2016-02-24 16:17:05 +11:00
koalyptus ea53940cca Merge pull request #124 from koalyptus/issue-91-eslint
Issue 91 eslint
2016-02-22 18:52:27 +11:00
Max Guglielmi f6707547f9 Removed unused argument in setColWidths 2016-02-22 18:41:41 +11:00
Max Guglielmi 6f0a009200 Extended eslint to tests 2016-02-22 18:14:58 +11:00
Max Guglielmi 1691f38368 Fixed linked filters with 2 checklist filters 2016-02-20 18:00:03 +11:00
Max Guglielmi 4e8d4ec9da Initial commit 2016-02-16 18:41:47 +11:00
koalyptus 1910d93b9f Merge pull request #121 from koalyptus/issue-92-external-filters-tests
Added external filters unit tests
2016-02-13 23:36:56 +11:00
Max Guglielmi 803e0a7d03 Added external filters unit tests 2016-02-13 23:27:28 +11:00
koalyptus 665909e02f Merge pull request #119 from koalyptus/issue-117-active-column-css-fix
Issue 117 active column css fix
2016-02-06 14:20:38 +11:00
Max Guglielmi 279bc1ca60 Improved store module interface 2016-02-06 14:08:46 +11:00
Max Guglielmi 40069e9652 Fixed active column styling for all themes 2016-02-06 12:04:11 +11:00
koalyptus c806c8278e Merge pull request #115 from koalyptus/issue-93-grouped-headers-tests
Initial commit
2016-02-04 09:27:41 +11:00
Max Guglielmi 6b7ce2e4b4 Addressed PR comments 2016-02-04 09:18:47 +11:00
Max Guglielmi 866d34d538 Initial commit 2016-02-03 18:34:46 +11:00
koalyptus d0ad41148b Merge pull request #114 from koalyptus/issue-113-filter-options-sorting
Fixed sorting for filter options with numeric values
2016-02-02 18:32:21 +11:00
Max Guglielmi 69f0c6fcc8 Fixed sorting for filter options with numeric values 2016-02-02 18:24:16 +11:00
koalyptus 9f992b0cba Merge pull request #111 from koalyptus/issue-109-no-headers
Added no headers unit test
2016-02-01 18:18:14 +11:00
Max Guglielmi eee964346a Added no headers unit test 2016-02-01 18:11:45 +11:00
koalyptus 8335d35c39 Merge pull request #108 from koalyptus/pub-sub-refactoring
Pub sub refactoring
2016-01-27 22:10:20 +11:00
Max Guglielmi 5112a28775 Fixed case match in filtering logic + setFilterValue with no filters 2016-01-27 21:53:36 +11:00
koalyptus 378ca84d15 Merge pull request #107 from koalyptus/issue-106-selectOptions-helper
Issue 106 select options helper
2016-01-25 16:57:19 +11:00
Max Guglielmi 079e027ba3 Improved getFilterValue and setFilterValue API interface 2016-01-25 16:44:33 +11:00
Max Guglielmi 65fe2d1838 Started normalising get/set filter values 2016-01-23 22:52:41 +11:00
Max Guglielmi 9b1c98c307 Continued simplifying setFilterValue 2016-01-21 18:29:09 +11:00
Max Guglielmi df802d0c0b Initial commit 2016-01-20 17:14:32 +11:00
koalyptus 800751d015 Merge pull request #105 from koalyptus/issue-104-reduce-features-coupling
Issue 104 reduce features coupling
2016-01-19 23:29:04 +11:00
Max Guglielmi 183aab6f84 Removed commented out code 2016-01-19 23:19:34 +11:00
Max Guglielmi 08f94b254f Updated help feature tests 2016-01-19 23:13:34 +11:00
Max Guglielmi 45b8ae13ae Added highlight-keyword event 2016-01-18 17:36:10 +11:00
Max Guglielmi e5a67eeee9 Removed Cookie dependency in TableFilter class 2016-01-18 17:11:33 +11:00
koalyptus 885b957d31 Merge pull request #103 from koalyptus/issue-98-refactor-reset-logic
Issue 98 refactor reset logic
2016-01-17 18:48:38 +11:00
Max Guglielmi db80c7c381 Reduced jshint maxcomplexity and maxstatements 2016-01-17 18:31:15 +11:00
Max Guglielmi 7a57101ace Cleaned code 2016-01-17 18:27:12 +11:00
Max Guglielmi cf8a7fbc66 Merged pub-sub-refactoring in for issue 99 2016-01-17 18:08:59 +11:00
Max Guglielmi 0c032efbd8 Removed _resetGridValues logic 2016-01-17 17:56:15 +11:00
Max Guglielmi 6b14415976 Merged master in for issue 99 2016-01-16 12:29:24 +11:00
koalyptus c22f9a5c6a Merge pull request #101 from koalyptus/issue-99-getheaderstext-popup-filters
Fixed getHeaderText helper method with popup filters, updated corresponding unit tests
2016-01-15 18:19:56 +11:00
Max Guglielmi 0a209f342a Fixed getHeaderText helper method with popup filters, updated corresponding unit tests 2016-01-15 18:11:41 +11:00
Max Guglielmi bd9740c419 Cleaned destroy method of TableFilter class 2016-01-14 21:13:19 +11:00
Max Guglielmi ada1374ade Fixed tests for reset feature behaviour unit test (grid-layout, paging) 2016-01-14 19:35:46 +11:00
Max Guglielmi 3db685f0c9 Started disconnecting _resetGrid 2016-01-13 17:45:44 +11:00
Max Guglielmi 671bd18ee6 Added unit tests for select filter with disabled onchange event 2016-01-13 15:22:46 +11:00
Max Guglielmi 4e2ae18aff Continued pub-sub refactoring 2016-01-12 17:46:27 +11:00
Max Guglielmi 5568663f46 initial commit 2016-01-11 18:35:21 +11:00
koalyptus 24cd54f23c Merge pull request #97 from koalyptus/issue-90-init-refactor
Issue 90 init refactor
2016-01-11 12:51:21 +11:00
Max Guglielmi 8427f58b2f Added watermark tests, removed commented out code 2016-01-11 12:41:25 +11:00
Max Guglielmi 93d902f235 Removed dropdown and checklist persistence logic 2016-01-10 20:41:01 +11:00
Max Guglielmi fbd8fa52d2 Added tests for dropdown change event 2016-01-09 20:22:57 +11:00
Max Guglielmi fe2e06e637 Added _buildSubmit button method 2016-01-09 13:42:33 +11:00
Max Guglielmi 4a7f935272 Added the _buildInputFilter method 2016-01-08 17:44:22 +11:00
Max Guglielmi cf876c730f Merge branch 'pub-sub-refactoring' into issue-90-init-refactor 2016-01-08 15:21:02 +11:00
Max Guglielmi c9b5a28f3a Merged master in for issue 94 2016-01-08 09:17:16 +11:00
koalyptus 2a51fdf0b2 Merge pull request #96 from koalyptus/issue-94-getfiltereddata-with-columnsvisibility-extension
Issue 94, excludeHiddenCols param for APIs
2016-01-07 18:37:22 +11:00
Max Guglielmi 20aa5c2e9c Issue 94, excludeHiddenCols param for APIs 2016-01-07 18:29:27 +11:00
Max Guglielmi 010d9add36 Added init to drop-down and check-list filters 2016-01-06 18:12:16 +11:00
Max Guglielmi 2a0ed49314 Initial commit 2016-01-04 17:59:30 +11:00
koalyptus ba7228cca1 Merge pull request #89 from koalyptus/issue-88-remove-evtmanager
Issue 88 remove evtmanager
2016-01-03 14:08:02 +11:00
Max Guglielmi 1109888366 Reduced jshint cyclomatic complexity values 2016-01-03 13:58:07 +11:00
Max Guglielmi fd8d5c759c Improved emitter logic 2016-01-03 13:49:04 +11:00
Max Guglielmi ea478ec500 Continued refactoring EvtManager 2016-01-03 01:33:31 +11:00
Max Guglielmi b3e236e111 Initial commit 2016-01-02 19:18:44 +11:00
koalyptus b41f7b25c6 Merge pull request #87 from koalyptus/issue-86-cell-processed-event
Added cell-processed event, improved alternateRows
2016-01-02 14:50:04 +11:00
Max Guglielmi 9964032b88 Added cell-processed event, improved alternateRows 2016-01-02 14:43:00 +11:00
koalyptus fa4fe6dddf Merge pull request #85 from koalyptus/issue-84-row-processed-event
Issue 84 row processed event
2015-12-31 15:27:57 +11:00
Max Guglielmi 62eb69e491 Uncommented line in unit test 2015-12-31 15:23:24 +11:00
Max Guglielmi 7b47726aee Fixed unit tests 2015-12-31 15:20:51 +11:00
Max Guglielmi 114d508c97 Continued row-processed event 2015-12-31 12:56:50 +11:00
Max Guglielmi 8e3416e24c Started row-processed event 2015-12-30 17:59:20 +11:00
koalyptus 5f8287ad36 Merge pull request #83 from koalyptus/issue-82-before-filtering-event
Issue 82 before filtering event
2015-12-30 17:01:58 +11:00
Max Guglielmi f96e9b97b8 Hooked up into the before-filtering event 2015-12-30 16:56:44 +11:00
Max Guglielmi 9ab5f5fb9d Hooked-up highlight keyword feature 2015-12-29 17:13:08 +11:00
Max Guglielmi 5da3079c13 Added comments to emitter class 2015-12-29 17:05:36 +11:00
koalyptus 784eeea4a1 Merge pull request #81 from koalyptus/issue-80-pub-sub-pattern
Issue 80 pub sub pattern
2015-12-28 18:06:06 +11:00
Max Guglielmi b0eea0bf3a Included starter.html into git 2015-12-28 17:54:22 +11:00
Max Guglielmi da9f8ad885 Finalised unit tests, removed applyProps method in tablefilter class 2015-12-28 17:53:03 +11:00
Max Guglielmi b20e9899b1 Added unit tests for emiitter 2015-12-28 11:18:55 +11:00
Max Guglielmi 4fcfaf1ec7 Added emitter class, started implementing pub-sub pattern (rowsCounter) 2015-12-27 22:08:14 +11:00
244 changed files with 44854 additions and 8335 deletions

15
.editorconfig Normal file
View file

@ -0,0 +1,15 @@
# editorconfig.org
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
# Trailing whitespace is significant in markdown files.
[*.md]
trim_trailing_whitespace = false

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
}
}
}]
}

37
.eslintrc Normal file
View file

@ -0,0 +1,37 @@
{
"parser": "babel-eslint",
"parserOptions": {
"sourceType": "module",
"ecmaFeatures": { "modules": true }
},
"rules": {
"max-len": [2, 80, 2, {"ignoreUrls": true}],
"indent": [2, 4, {"SwitchCase": 1}],
"semi": ["error", "always"],
"no-trailing-spaces": 2,
"no-multi-spaces": 2,
"array-bracket-spacing": 2,
"keyword-spacing": ["error", { "after": true, "before": true }],
"max-depth": [2, 7],
"max-statements": [2, 133],
"complexity": [2, 45],
"no-unused-vars": 2,
"no-eval": 2,
"no-underscore-dangle": 0,
"no-loop-func": 2,
"no-floating-decimal": 2,
"curly": 2,
"eqeqeq": [2, "smart"],
"quotes": [2, "single"],
"new-cap": 2,
"radix": [2, "always"]
},
"env": {
"es6": true,
"browser": true,
"node": false
},
"globals": {
"__webpack_public_path__": false
}
}

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/

3
.gitignore vendored
View file

@ -1,9 +1,10 @@
demos
docs
node_modules
report
.grunt
npm-debug.log
*.js.map
.codio
.settings
.vscode

View file

@ -1,17 +0,0 @@
{
"-W024": true,
"scripturl": true,
"evil": true,
"curly": true,
"indent": 4,
"es3": true,
"esnext": true,
"unused": true,
"maxlen" : 80,
"trailing": true,
"quotmark": "single",
"immed": true,
"maxstatements": 198,
"maxdepth": 7,
"maxcomplexity": 104
}

View file

@ -1,13 +1,53 @@
language: node_js
node_js:
- '0.10'
- '8.9.4'
before_script:
- npm install grunt-cli -g
- npm install grunt-cli -g
- npm install codecov -g
script:
- grunt test deploy
- npm test
- npm run codecov
- npm run build:all
branches:
only:
- 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:
global:
- secure: A1G8GvJkV0rjy7XCTVdOpTHy3xaoSZZAbMWhI+ikrqBqd8mRz+sB71FhRusouTcYdsT5VfF9Io2doS8LKAeP0TNC34Pp0uvjtsvarzn8a/oNEOuqR3Ub0ws2bmbZIZc+wOpgErKOj1H1QSJAUpd6ZjIuEAbOVXlhGBJz3zUCmcpRDh32CpFKC62oFWeGlvttxPciLLzBfKgkVKEGhPtdGP/xCHL1MCQptYVHZiXwWsaIQ5wHFO6KCVlRrPgdfOL+Yce3mT02iXH6ZjW6U6zA6vYQVQZVD873AkU5RmirYblW+jW1wdvu4UXI71lSH6Z3uXRVnrw1b0TsLVTjP9ZUbCtkTHtLbxYzeDjEukxKoCjpAppIhOtaNIxrdA8oKJAabQYp5X+QK6lkosy0zdT5u2B1+g8unZhsf0y//7lgLUe04iQ7sc1Q6AHiiEGtByaXg4BHNW53bUfKgNnbV4+IbXf8rz5wWOxL2/yWAU/GoiszjqRQfajAXCpSf6SyMjXjhhvQdeFn+Cz6FwdtaxH+tOIY0Hq9Gqy1xrLIkv/httd3O+AbhLrU1c/M0MwlFQue7GeJb7ZyF3KsK7bXvoz2dEqvzHd98NZXiQEqFXCIs77uVh4eZMoYrbEyrkOAgkUZNQYhHh9fuvfynJ/zgUvyA0v3GUvBebq3ybYKD/vqX7s=

128
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,128 @@
# Contributing to TableFilter
:+1::tada: First off, thanks for taking the time to contribute! :tada::+1:
## Reporting bugs
Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/).
Create an issue and provide the following information.
Explain the problem and include additional details to help maintainers reproduce
the problem:
* **Use a clear, concise and descriptive title** for the issue to identify the
problem.
* **Describe the exact steps which reproduce the problem** in as many details
as possible.
* **Provide specific examples to demonstrate the steps**. Include links to
files or GitHub projects, or copy/pasteable snippets, which you use in those
examples. If you're providing snippets in the issue, use
[Markdown code blocks](https://guides.github.com/features/mastering-markdown/#GitHub-flavored-markdown).
Do not paste large snippets completely unrelated to the issue.
* **Describe the behavior you observed after following the steps** and point
out what exactly is the problem with that behavior.
* **Explain which behavior you expected to see instead and why.**
* Do not hesitate to **include screenshots and animated GIFs** which show you
following the described steps and clearly demonstrate the problem.
You can use [this tool](http://www.cockos.com/licecap/) to record GIFs on macOS
and Windows, and [this tool](https://github.com/colinkeenan/silentcast) or
[this tool](https://github.com/GNOME/byzanz) on Linux.
### Template for submitting bug reports
[Short description of problem here]
**Reproduction steps:**
1. [First Step]
2. [Second Step]
3. [Other Steps...]
**Expected behavior:**
[Describe expected behavior here]
**Observed behavior:**
[Describe observed behavior here]
**Screenshots and GIFs**
![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]
**Additional information:**
* Problem started happening recently, didn't happen in an older version of
TableFilter: [Yes/No]
* Problem can be reliably reproduced, doesn't happen randomly: [Yes/No]
## Suggesting enhancements and features
Enhancement and feature suggestions are tracked as
[GitHub issues](https://guides.github.com/features/issues/).
Create an issue and provide the following information:
* **Use a clear and descriptive title** for the issue to identify the
suggestion.
* **Provide a step-by-step description of the suggested enhancement/feature**
in as many details as possible.
* When applicable **describe the current behavior** and
**explain which behavior you expected to see instead** and why.
* **Include screenshots and animated GIFs** which help you demonstrate the
steps or point out the part of TableFilter which the suggestion is related to.
You can use [this tool](http://www.cockos.com/licecap/) to record GIFs on macOS
and Windows, and [this tool](https://github.com/colinkeenan/silentcast) or
[this tool](https://github.com/GNOME/byzanz) on Linux.
* **Explain why this enhancement would be useful** to most TableFilter users.
### Template for submitting enhancement and feature suggestions
[Short description of suggestion]
**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)
**TableFilter Version:** [Enter TableFilter version here]
**Browser and version:** [Enter Browser name and version here]
**OS and version:** [Enter OS name and version here]
## Code contribution
TableFilter welcomes contributions from anyone and everyone. If you want to get
your hands dirty:
### Pull requests
In general, we follow the "fork-and-pull" Git workflow.
1. **Fork** the repo on GitHub
2. **Clone** the project to your own machine
3. **Commit** changes to your own branch
- 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.3. **Ensure** build is working with `npm run dist` command
4. **Push** your work back up to your fork
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!
## Donations
Support this project by donating [here](http://www.tablefilter.com/donate.html).
Thanks to all those who supported this project in the past and those who will
in the future!

View file

@ -1,28 +1,26 @@
module.exports = function (grunt) {
var webpack = require('webpack');
var webpackConfig = require('./webpack.config.js');
var fs = require('fs');
var path = require('path');
var testDir = 'test';
var testHost = 'http://localhost:8000/';
var pkg = grunt.file.readJSON('package.json');
var repo = 'github.com/koalyptus/TableFilter';
grunt.initConfig({
jshint: {
src: [
'Gruntfile.js',
'webpack.config.js',
'src/**/*.js'
],
options: {
jshintrc: '.jshintrc'
}
},
qunit: {
options: {
'--web-security': 'no',
coverage: {
disposeCollector: true,
src: ['dist/tablefilter/*.js'],
instrumentedFiles: 'report/temp/',
htmlReport: 'report/coverage',
coberturaReport: 'report/',
lcovReport: 'report/',
jsonReport: 'report',
linesThresholdPct: 80
}
},
all: {
options: {
urls: getTestFiles(testDir, testHost)
@ -82,21 +80,21 @@ module.exports = function (grunt) {
{
pattern: /{NAME}/ig,
replacement: pkg.name
},{
}, {
pattern: /{VERSION}/ig,
replacement: pkg.version
},{
}, {
pattern: /{EZEDITTABLE_LINK}/ig,
replacement: '<a href="http://edittable.free.fr/' +
'zip.php?f=ezEditTable.zip&amp;p=1"' +
'target="_blank" title="ezEditTable is a ' +
'javascript code aimed at enhancing regular ' +
'HTML tables by adding features such as ' +
'inline editing components, advanced ' +
'selection and keyboard navigation ' +
'- Developed by '+ pkg.author.name +'">' +
'ezEditTable</a>'
},{
'zip.php?f=ezEditTable.zip&amp;p=1"' +
'target="_blank" title="ezEditTable is a ' +
'javascript code aimed at enhancing regular ' +
'HTML tables by adding features such as ' +
'inline editing components, advanced ' +
'selection and keyboard navigation ' +
'- Developed by ' + pkg.author.name + '">' +
'ezEditTable</a>'
}, {
pattern: /<!-- @import (.*?) -->/ig,
replacement: function (match, p1) {
return grunt.file.read('static/' + p1);
@ -109,26 +107,6 @@ module.exports = function (grunt) {
clean: ['demos/starter.html'],
'webpack-dev-server': {
options: {
webpack: webpack.dev,
publicPath: '/dist/'
},
start: {
keepAlive: true,
webpack: {
devtool: 'eval',
debug: true
}
}
},
webpack: {
options: webpackConfig,
build: webpackConfig.build,
dev: webpackConfig.dev
},
watch: {
app: {
files: ['src/**/*', 'static/style/**/*'],
@ -146,202 +124,79 @@ module.exports = function (grunt) {
}
},
babel: {
options: {
sourceMap: true,
modules: 'amd',
compact: false,
presets: ['es2015']
// temporary shell commands while decommissioning grunt
shell: {
eslint: {
command: 'npm run lint'
},
dist: {
files: [{
expand: true,
cwd: 'src',
src: ['**/*.js'],
dest: 'dist/tablefilter'
}]
}
},
esdoc: {
dist: {
options: {
source: 'src',
destination: 'docs/docs',
title: pkg.name + ' v' + pkg.version
}
}
},
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: 'dist/tablefilter/style/tablefilter.css'
},{
src: ['static/style/extensions/colsVisibility.styl'],
dest: 'dist/tablefilter/style/colsVisibility.css'
},{
src: ['static/style/extensions/filtersVisibility.styl'],
dest: 'dist/tablefilter/style/filtersVisibility.css'
},{
src: ['static/style/themes/default/*.styl'],
dest:
'dist/tablefilter/style/themes/default/default.css'
},{
src: ['static/style/themes/mytheme/*.styl'],
dest:
'dist/tablefilter/style/themes/mytheme/mytheme.css'
},{
src: ['static/style/themes/skyblue/*.styl'],
dest:
'dist/tablefilter/style/themes/skyblue/skyblue.css'
}
]
}
},
'gh-pages': {
options: {
branch: 'gh-pages',
add: true
esdoc: {
command: 'npm run esdoc'
},
'publish-lib': {
options: {
base: 'dist',
repo: 'https://' + repo,
message: 'publish TableFilter lib to gh-pages (cli)'
},
src: ['**/*']
build: {
command: 'npm run build'
},
'publish-readme': {
options: {
base: './',
repo: 'https://' + repo,
message: 'publish README and LICENSE to gh-pages (cli)'
},
src: ['README.md', 'LICENSE']
dev: {
command: 'npm run dev'
},
'publish-docs': {
options: {
base: 'docs',
repo: 'https://' + repo,
message: 'publish Docs to gh-pages (cli)'
},
src: ['**/*']
test: {
command: 'npm run build:test'
},
'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: ['**/*']
'build-css': {
command: 'npm run build:css'
}
}
});
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-qunit');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-string-replace');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-webpack');
grunt.loadNpmTasks('grunt-babel');
grunt.loadNpmTasks('grunt-esdoc');
grunt.loadNpmTasks('grunt-contrib-stylus');
grunt.loadNpmTasks('grunt-gh-pages');
grunt.loadNpmTasks('grunt-shell');
grunt.loadNpmTasks('grunt-qunit-istanbul');
grunt.registerTask('default', ['build', 'test', 'build-demos']);
grunt.registerTask('eslint', ['shell:eslint']);
grunt.registerTask('esdoc', ['shell:esdoc']);
// Development server
grunt.registerTask('server', ['webpack-dev-server:start']);
grunt.registerTask('default', ['test', 'build', 'build-demos']);
// Dev dev/build/watch cycle
grunt.registerTask('dev',
['jshint', 'webpack:dev', 'copy:dist', 'stylus:compile', 'watch:app']);
['eslint', 'shell:dev', 'copy:dist', 'shell:build-css', 'watch:app']);
// Production build
grunt.registerTask('build',
['jshint', 'webpack:build', 'copy:dist', 'stylus:compile']);
['eslint', 'shell:build', 'copy:dist', 'shell:build-css']);
// Build demos
grunt.registerTask('dev-demos', ['build-demos', 'watch:templates']);
grunt.registerTask('build-demos', ['copy:templates', 'copy:assets',
'string-replace:demos', 'copy:starter', 'clean']);
// Transpile with Babel
grunt.registerTask('dev-modules', ['babel', 'copy:dist']);
// Build tests
grunt.registerTask('build-test',
['eslint', 'shell:test', 'copy:dist', 'shell:build-css']);
// Tests
grunt.registerTask('test', ['jshint', 'connect', 'qunit:all']);
// Tests with coverage
grunt.registerTask('test', ['build-test', 'connect', 'qunit:all']);
// Publish to gh-pages
grunt.registerTask('publish', 'Publish from CLI', [
'build', 'build-demos', 'esdoc', 'gh-pages:publish-lib',
'gh-pages:publish-readme', 'gh-pages:publish-docs'
]);
// Deploy to gh-pages
grunt.registerTask('deploy', 'Publish from Travis', [
'build', 'esdoc', 'check-deploy'
// Build all for deployment from travis
grunt.registerTask('build-all', 'Prepare for deployment', [
'build', 'build-demos', 'esdoc'
]);
// Custom task running QUnit tests for specified files.
// Usage example: grunt test-only:test.html,test-help.html
grunt.registerTask('test-only',
'A task that runs only specified tests.',
function(tests) {
if(!tests) {
function (tests) {
if (!tests) {
return;
}
tests = tests.split(',');
var res = [];
tests.forEach(function(itm) {
tests.forEach(function (itm) {
var filePath = path.resolve(testDir, itm);
var parts = filePath.split(path.sep);
res.push(buildTestUrl(testHost, testDir, parts));
@ -350,13 +205,14 @@ module.exports = function (grunt) {
grunt.task.run('connect');
grunt.config('qunit.only.options.urls', res);
grunt.task.run('qunit:only');
});
}
);
function isTestFile(pth) {
var allowedExts = ['.html', '.htm'];
for(var i=0, len=allowedExts.length; i<len; i++){
for (var i = 0, len = allowedExts.length; i < len; i++) {
var ext = allowedExts[i];
if(pth.indexOf(ext) !== -1){
if (pth.indexOf(ext) !== -1) {
return true;
}
}
@ -372,18 +228,17 @@ module.exports = function (grunt) {
// Returns the list of test files from the test folder for qunit task
function getTestFiles(testDir, host) {
var getFiles = function(dir, host) {
var getFiles = function (dir, host) {
var res = [];
var items = fs.readdirSync(dir);
items.forEach(function(itm){
items.forEach(function (itm) {
var fileOrDir = path.resolve(dir, itm);
if(isTestFile(fileOrDir)) {
if (isTestFile(fileOrDir)) {
var parts = fileOrDir.split(path.sep);
res.push(buildTestUrl(host, testDir, parts));
} else {
if(fs.lstatSync(fileOrDir).isDirectory()) {
if (fs.lstatSync(fileOrDir).isDirectory()) {
res = res.concat(getFiles(fileOrDir, host));
}
}
@ -394,43 +249,4 @@ module.exports = function (grunt) {
return getFiles(testDir, host);
}
grunt.registerTask('check-deploy', function() {
var env = process.env;
// need this
this.requires(['build', 'esdoc']);
// only deploy under these conditions
if (env.TRAVIS === 'true' &&
env.TRAVIS_SECURE_ENV_VARS === 'true' &&
env.TRAVIS_PULL_REQUEST === 'false') {
grunt.log.writeln('executing deployment');
// queue deploy
grunt.task.run([
'gh-pages:deploy-lib',
'gh-pages:deploy-readme',
'gh-pages:deploy-docs'
]);
} else {
grunt.log.writeln('skipped deployment');
}
});
// Get a formatted commit message to review changes from the commit log
// github will turn some of these into clickable links
function getDeployMessage() {
var ret = '\n\n';
var env = process.env;
if (env.TRAVIS !== 'true') {
ret += 'missing env vars for travis-ci';
return ret;
}
ret += 'branch: ' + env.TRAVIS_BRANCH + '\n';
ret += 'SHA: ' + env.TRAVIS_COMMIT + '\n';
ret += 'range SHA: ' + env.TRAVIS_COMMIT_RANGE + '\n';
ret += 'build id: ' + env.TRAVIS_BUILD_ID + '\n';
ret += 'build number: ' + env.TRAVIS_BUILD_NUMBER + '\n';
return ret;
}
};

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

118
README.md
View file

@ -1,5 +1,10 @@
TableFilter [![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](https://www.tablefilter.com/docs/badge.svg)](https://www.tablefilter.com/docs/source.html)
[![codecov](https://codecov.io/gh/koalyptus/TableFilter/branch/master/graph/badge.svg)](https://codecov.io/gh/koalyptus/TableFilter)
[![Greenkeeper badge](https://badges.greenkeeper.io/koalyptus/TableFilter.svg)](https://greenkeeper.io/)
[![Donate](https://img.shields.io/badge/donate-%24-green.svg)](https://www.tablefilter.com/donate.html)
# TableFilter
> A Javascript library making HTML tables filterable
@ -10,36 +15,59 @@ users to filter and limit the data displayed within a long table. By default, th
## Features
* Convert a regular HTML table into an advanced grid component providing:
* Advanced columns filtering model
* Sorting and pagination facilities
* Sorting and pagination capabilities
* Complete selection model ([ezEditTable](http://codecanyon.net/item/ezedittable-enhance-html-tables/2425123?ref=koalyptus) extension)
* Extended keyboard navigation ([ezEditTable](http://codecanyon.net/item/ezedittable-enhance-html-tables/2425123?ref=koalyptus) extension)
* Inline cell or row editing ([ezEditTable](http://codecanyon.net/item/ezedittable-enhance-html-tables/2425123?ref=koalyptus) extension)
* Row insertion or deleting ([ezEditTable](http://codecanyon.net/item/ezedittable-enhance-html-tables/2425123?ref=koalyptus) extension)
* And even more behaviors...
* And even more features...
* Attach to an existing HTML table
* Integration with any server-side technology as this is a pure client-side
solution
* Callbacks for all events, and delegates for most actions
* Exhaustive documentation and API
* Exhaustive documentation and powerful API
## Getting started
* Clone the repo using Git:
```shell
git clone --bare https://github.com/koalyptus/TableFilter.git
git clone https://github.com/koalyptus/TableFilter.git
```
* 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
npm install tablefilter --save
```
npm install tablefilter --save-dev
```
* or get the future features from the ``next`` release channel:
```shell
npm install tablefilter@next --save-dev
```
* Alternatively you can also [access these files from unpkg CDN](https://unpkg.com/tablefilter/), download them or point your package manager to them.
## 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:
```shell
<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
```shell
<script>
@ -53,11 +81,11 @@ If the ``base_path`` property is not specified, it will default to ``/tablefilte
```shell
your-page.html
|— tablefilter
```
```
## Development
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):
```shell
npm install -g grunt-cli
@ -68,46 +96,52 @@ Start by installing any dependencies.
```shell
npm install
```
Use the Grunt ``dev`` task to launch a build / watch cycle and start the local
sever on port ``8080``:
Use
```shell
npm run dev
```
command to launch a build / watch cycle and start the local
sever on port ``8080``.
Use
```shell
npm run build
```
command to generate a production build.
The
```shell
npm run dist
```
command will create a production build, run the tests and finally generate
the demos:
To run all the tests and generate the coverage report:
```shell
grunt dev
npm test
```
Use the ``build`` task to generate a production build:
```shell
grunt build
```
The ``default`` Grunt task will create a production build, run the tests and finally generate the demos:
```shell
grunt
```
To run all the tests:
```shell
grunt test
```
and to run specific test(s):
or to run specific test(s):
```shell
grunt test-only:test.html
grunt test-only:test.html,test-sort.html
```
to view the coverage report(s), open the `index.html` under the
`report/coverage` folder or
[online](https://codecov.io/gh/koalyptus/TableFilter).
## Demos
Check out the online [examples](http://koalyptus.github.io/TableFilter/examples) or generate the demos locally:
Check out the online [examples](http://www.tablefilter.com/examples.html)
or generate the demos locally:
```shell
grunt build-demos
npm run build:demos
```
then run the local webserver:
```shell
grunt server
npm start
```
then pick a demo from:
```shell
@ -117,16 +151,18 @@ http://localhost:8080/demos/
## Documentation
Find exhaustive documentation on the configuration options in the [WIKI](https://github.com/koalyptus/TableFilter/wiki) section.
Autogenerated documentation of the ES6 modules is available on the website: [docs](http://koalyptus.github.io/TableFilter/docs)
Autogenerated documentation of the ES6 modules is available on the website: [docs](http://www.tablefilter.com/docs)
If you previously used the HTML Table Filter Generator plugin, verify the configuration
options you are using are still supported: [Obsolete](https://github.com/koalyptus/TableFilter/wiki/Obsolete)
Run this task to generate the documentation in the ``docs/docs`` directory:
```shell
grunt esdoc
npm run esdoc
```
## 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
[MIT](LICENSE)

14
dist/starter.html vendored
View file

@ -1,10 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>tablefilter v0.0.21 - Starter</title>
<title>tablefilter v0.7.3 - Starter</title>
</head>
<body>
<h1>tablefilter v0.0.21</h1>
<h1>tablefilter v0.7.3</h1>
@ -460,10 +460,10 @@
status_bar: true,
mark_active_columns: true,
highlight_keywords: true,
col_number_format: [
null, null, 'US',
'US', 'US', 'US',
'US', 'US', 'US'
col_types: [
'string', 'string', 'number',
'number', 'number', 'number',
'number', 'number', 'number'
],
custom_options: {
cols:[3],
@ -479,7 +479,7 @@
},
col_widths: [
'150px', '100px', '100px',
'70px', '70px', '70px',
'100px', '100px', '100px',
'70px', '60px', '60px'
],
extensions:[{ name: 'sort' }]

View file

@ -1,6 +1 @@
/**
* tablefilter v0.0.21 by Max Guglielmi
* build date: 2015-12-27T03:29:01.000Z
* 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}
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}

View file

@ -1,6 +1 @@
/**
* tablefilter v0.0.21 by Max Guglielmi
* build date: 2015-12-27T03:29:01.000Z
* 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}

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1 @@
/**
* tablefilter v0.0.21 by Max Guglielmi
* build date: 2015-12-27T03:29:01.000Z
* MIT License
*/
table.TF{border-left:1px solid #ccc !important;border-top:none !important;border-right:none !important;border-bottom:none !important;}table.TF th{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;color:#333 !important}table.TF td{border-bottom:1px dotted #999 !important;padding:5px !important}.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}
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.0.21 by Max Guglielmi
* build date: 2015-12-27T03:29:01.000Z
* MIT License
*/
table.TF{border-left:1px dotted #81963b !important;border-top:none !important;border-right:0 !important;border-bottom:none !important;}table.TF th{background:#39424b url("images/bg_headers.jpg") left top repeat-x !important;border-bottom:0 !important;border-right:1px dotted #d0d0d0 !important;border-left:0 !important;border-top:0 !important;color:#fff !important}table.TF td{border-bottom:1px dotted #81963b;border-right:1px dotted #81963b;padding:5px !important}.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}
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.0.21 by Max Guglielmi
* build date: 2015-12-27T03:29:01.000Z
* 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}

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 847 B

View file

@ -0,0 +1 @@
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

3
index.js Normal file
View file

@ -0,0 +1,3 @@
'use strict';
module.exports = require('./dist/tablefilter/tablefilter').TableFilter;

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",
"version": "0.0.21",
"version": "0.7.3",
"description": "A Javascript library making HTML tables filterable and a bit more",
"license": "MIT",
"author": {
@ -22,34 +22,58 @@
"pagination"
],
"scripts": {
"test": "grunt test"
"lint": "eslint src/**/*.js test/*.js *.js",
"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:test": "webpack --colors --config webpack.test.config.js",
"server": "webpack-dev-server --colors --hot --config ./webpack.dev.config.js",
"test": "grunt test",
"codecov": "./node_modules/.bin/codecov",
"esdoc": "esdoc",
"dist": "grunt",
"build:all": "grunt build-all",
"start": "npm run server"
},
"publishConfig": {
"tag": "next"
},
"devDependencies": {
"babel-core": "^6.1.2",
"babel-loader": "^6.0.1",
"babel-preset-es2015": "^6.3.13",
"clean-webpack-plugin": "^0.1.3",
"grunt": "^0.4.5",
"grunt-babel": "^6.0.0",
"grunt-contrib-clean": "^0.6.0",
"grunt-contrib-connect": "^0.10.1",
"grunt-contrib-copy": "^0.8.0",
"grunt-contrib-jshint": "^0.11.2",
"grunt-contrib-qunit": "^0.7.0",
"grunt-contrib-stylus": "^0.22.0",
"grunt-contrib-watch": "^0.6.1",
"grunt-esdoc": "^0.0.1",
"grunt-gh-pages": "^0.10.0",
"grunt-string-replace": "^1.2.0",
"grunt-webpack": "^1.0.8",
"script-loader": "^0.6.1",
"string-replace-webpack-plugin": "^0.0.1",
"webpack": "^1.8.10",
"webpack-dev-server": "^1.8.2"
"@babel/core": "7.10.0",
"@babel/preset-env": "7.10.0",
"babel-eslint": "10.1.0",
"babel-loader": "^8.0.2",
"babel-preset-env": "1.7.0",
"clean-webpack-plugin": "^3.0.0",
"codecov": "3.7.1",
"diacritics": "1.3.0",
"esdoc": "1.1.0",
"esdoc-standard-plugin": "1.0.0",
"eslint": "6.5.0",
"format-number": "3.0.0",
"grunt": "^1.0.1",
"grunt-cli": "1.3.2",
"grunt-contrib-clean": "^2.0.0",
"grunt-contrib-connect": "^2.0.0",
"grunt-contrib-copy": "^1.0.0",
"grunt-contrib-watch": "^1.0.0",
"grunt-qunit-istanbul": "1.1.0",
"grunt-shell": "3.0.0",
"grunt-string-replace": "^1.3.1",
"isparta-loader": "2.0.0",
"script-loader": "^0.7.0",
"string-replace-webpack-plugin": "^0.1.3",
"stylus": "^0.54.5",
"sugar-date": "2.0.6",
"uglifyjs-webpack-plugin": "2.2.0",
"webpack": "^4.38.0",
"webpack-cli": "^3.0.8",
"webpack-dev-server": "^3.1.11"
},
"dependencies": {},
"bugs": {
"url": "https://github.com/koalyptus/TableFilter/issues"
},
"homepage": "http://koalyptus.github.io/TableFilter"
"homepage": "https://www.tablefilter.com"
}

View file

@ -2,16 +2,21 @@
* Array utilities
*/
import Str from './string';
import {matchCase} from './string';
export default {
has: function(arr, val, caseSensitive){
let sCase = caseSensitive===undefined ? false : caseSensitive;
for (var i=0; i<arr.length; i++){
if(Str.matchCase(arr[i].toString(), sCase) == val){
return true;
}
/**
* Checks if given item can be found in the passed collection
* @param {Array} arr collection
* @param {Any} val item to search
* @param {Boolean} caseSensitive respects case if true
* @return {Boolean}
*/
export const has = (arr, val, caseSensitive) => {
let sCase = Boolean(caseSensitive);
for (var i = 0, l = arr.length; i < l; i++) {
if (matchCase(arr[i].toString(), sCase) === val) {
return true;
}
return false;
}
return false;
};

118
src/const.js Normal file
View file

@ -0,0 +1,118 @@
/**
* Filter types
*/
/**
* Input filter type
* @type {String}
*/
export const INPUT = 'input';
/**
* Select filter type
* @type {String}
*/
export const SELECT = 'select';
/**
* Multiple select filter type
* @type {String}
*/
export const MULTIPLE = 'multiple';
/**
* Checklist filter type
* @type {String}
*/
export const CHECKLIST = 'checklist';
/**
* None filter type
* @type {String}
*/
export const NONE = 'none';
/**
* Key codes
*/
/**
* Enter key code
* @type {Number}
*/
export const ENTER_KEY = 13;
/**
* Tab key code
* @type {Number}
*/
export const TAB_KEY = 9;
/**
* Escape key code
* @type {Number}
*/
export const ESC_KEY = 27;
/**
* Up arrow key code
* @type {Number}
*/
export const UP_ARROW_KEY = 38;
/**
* Down arrow key code
* @type {Number}
*/
export const DOWN_ARROW_KEY = 40;
/**
* HTML tags
*/
/**
* Header cell tag
* @type {String}
*/
export const HEADER_TAG = 'TH';
/**
* Cell tag
* @type {String}
*/
export const CELL_TAG = 'TD';
/**
* Data types
*/
/**
* String
* @type {String}
*/
export const STRING = 'string';
/**
* Number
* @type {String}
*/
export const NUMBER = 'number';
/**
* Formatted number
* @type {String}
*/
export const FORMATTED_NUMBER = 'formatted-number';
/**
* Date
* @type {String}
*/
export const DATE = 'date';
/**
* IP address
* @type {String}
*/
export const IP_ADDRESS = 'ipaddress';
/**
* Default values
*/
/**
* Auto filter delay in milliseconds
* @type {Number}
*/
export const AUTO_FILTER_DELAY = 750;

View file

@ -1,28 +1,43 @@
import {root} from './root';
/**
* Cookie utilities
*/
const doc = root.document;
export default {
write(name, value, hours){
/**
* Write a cookie
* @param {String} name Name of the cookie
* @param {String} value Value of the cookie
* @param {Number} hours Cookie duration in hours
*/
write(name, value, hours) {
let expire = '';
if(hours){
if (hours) {
expire = new Date((new Date()).getTime() + hours * 3600000);
expire = '; expires=' + expire.toGMTString();
}
document.cookie = name + '=' + escape(value) + expire;
doc.cookie = name + '=' + escape(value) + expire;
},
read(name){
/**
* Read a cookie
* @param {String} name Name of the cookie
* @returns {String} Value of the cookie
*/
read(name) {
let cookieValue = '',
search = name + '=';
if(document.cookie.length > 0){
let cookie = document.cookie,
if (doc.cookie.length > 0) {
let cookie = doc.cookie,
offset = cookie.indexOf(search);
if(offset !== -1){
if (offset !== -1) {
offset += search.length;
let end = cookie.indexOf(';', offset);
if(end === -1){
if (end === -1) {
end = cookie.length;
}
cookieValue = unescape(cookie.substring(offset, end));
@ -31,28 +46,12 @@ export default {
return cookieValue;
},
remove(name){
/**
* Remove a cookie
* @param {String} name Name of the cookie
*/
remove(name) {
this.write(name, '', -1);
},
valueToArray(name, separator){
if(!separator){
separator = ',';
}
//reads the cookie
let val = this.read(name);
//creates an array with filters' values
let arr = val.split(separator);
return arr;
},
getValueByIndex(name, index, separator){
if(!separator){
separator = ',';
}
//reads the cookie
let val = this.valueToArray(name, separator);
return val[index];
}
};

View file

@ -1,172 +0,0 @@
/**
* Date utilities
*/
export default {
isValid(dateStr, format){
if(!format) {
format = 'DMY';
}
format = format.toUpperCase();
if(format.length != 3) {
if(format === 'DDMMMYYYY'){
let d = this.format(dateStr, format);
dateStr = d.getDate() +'/'+ (d.getMonth()+1) +'/'+
d.getFullYear();
format = 'DMY';
}
}
if((format.indexOf('M') === -1) || (format.indexOf('D') === -1) ||
(format.indexOf('Y') === -1)){
format = 'DMY';
}
let reg1, reg2;
// If the year is first
if(format.substring(0, 1) === 'Y') {
reg1 = /^\d{2}(\-|\/|\.)\d{1,2}\1\d{1,2}$/;
reg2 = /^\d{4}(\-|\/|\.)\d{1,2}\1\d{1,2}$/;
} else if(format.substring(1, 2) === 'Y') { // If the year is second
reg1 = /^\d{1,2}(\-|\/|\.)\d{2}\1\d{1,2}$/;
reg2 = /^\d{1,2}(\-|\/|\.)\d{4}\1\d{1,2}$/;
} else { // The year must be third
reg1 = /^\d{1,2}(\-|\/|\.)\d{1,2}\1\d{2}$/;
reg2 = /^\d{1,2}(\-|\/|\.)\d{1,2}\1\d{4}$/;
}
// If it doesn't conform to the right format (with either a 2 digit year
// or 4 digit year), fail
if(reg1.test(dateStr) === false && reg2.test(dateStr) === false) {
return false;
}
// Split into 3 parts based on what the divider was
let parts = dateStr.split(RegExp.$1);
let mm, dd, yy;
// Check to see if the 3 parts end up making a valid date
if(format.substring(0, 1) === 'M'){
mm = parts[0];
} else if(format.substring(1, 2) === 'M'){
mm = parts[1];
} else {
mm = parts[2];
}
if(format.substring(0, 1) === 'D'){
dd = parts[0];
} else if(format.substring(1, 2) === 'D'){
dd = parts[1];
} else {
dd = parts[2];
}
if(format.substring(0, 1) === 'Y'){
yy = parts[0];
} else if(format.substring(1, 2) === 'Y'){
yy = parts[1];
} else {
yy = parts[2];
}
if(parseInt(yy, 10) <= 50){
yy = (parseInt(yy, 10) + 2000).toString();
}
if(parseInt(yy, 10) <= 99){
yy = (parseInt(yy, 10) + 1900).toString();
}
let dt = new Date(
parseInt(yy, 10), parseInt(mm, 10)-1, parseInt(dd, 10),
0, 0, 0, 0);
if(parseInt(dd, 10) != dt.getDate()){
return false;
}
if(parseInt(mm, 10)-1 != dt.getMonth()){
return false;
}
return true;
},
format(dateStr, formatStr) {
if(!formatStr){
formatStr = 'DMY';
}
if(!dateStr || dateStr === ''){
return new Date(1001, 0, 1);
}
let oDate;
let parts;
switch(formatStr.toUpperCase()){
case 'DDMMMYYYY':
parts = dateStr.replace(/[- \/.]/g,' ').split(' ');
oDate = new Date(y2kDate(parts[2]),mmm2mm(parts[1])-1,parts[0]);
break;
case 'DMY':
/* jshint ignore:start */
parts = dateStr.replace(
/^(0?[1-9]|[12][0-9]|3[01])([- \/.])(0?[1-9]|1[012])([- \/.])((\d\d)?\d\d)$/,'$1 $3 $5').split(' ');
oDate = new Date(y2kDate(parts[2]),parts[1]-1,parts[0]);
/* jshint ignore:end */
break;
case 'MDY':
/* jshint ignore:start */
parts = dateStr.replace(
/^(0?[1-9]|1[012])([- \/.])(0?[1-9]|[12][0-9]|3[01])([- \/.])((\d\d)?\d\d)$/,'$1 $3 $5').split(' ');
oDate = new Date(y2kDate(parts[2]),parts[0]-1,parts[1]);
/* jshint ignore:end */
break;
case 'YMD':
/* jshint ignore:start */
parts = dateStr.replace(/^((\d\d)?\d\d)([- \/.])(0?[1-9]|1[012])([- \/.])(0?[1-9]|[12][0-9]|3[01])$/,'$1 $4 $6').split(' ');
oDate = new Date(y2kDate(parts[0]),parts[1]-1,parts[2]);
/* jshint ignore:end */
break;
default: //in case format is not correct
/* jshint ignore:start */
parts = dateStr.replace(/^(0?[1-9]|[12][0-9]|3[01])([- \/.])(0?[1-9]|1[012])([- \/.])((\d\d)?\d\d)$/,'$1 $3 $5').split(' ');
oDate = new Date(y2kDate(parts[2]),parts[1]-1,parts[0]);
/* jshint ignore:end */
break;
}
return oDate;
}
};
function y2kDate(yr){
if(yr === undefined){
return 0;
}
if(yr.length>2){
return yr;
}
let y;
//>50 belong to 1900
if(yr <= 99 && yr>50){
y = '19' + yr;
}
//<50 belong to 2000
if(yr<50 || yr === '00'){
y = '20' + yr;
}
return y;
}
function mmm2mm(mmm){
if(mmm === undefined){
return 0;
}
let mondigit;
let MONTH_NAMES = [
'january','february','march','april','may','june','july',
'august','september','october','november','december',
'jan','feb','mar','apr','may','jun','jul','aug','sep','oct',
'nov','dec'
];
for(let m_i=0; m_i < MONTH_NAMES.length; m_i++){
let month_name = MONTH_NAMES[m_i];
if (mmm.toLowerCase() === month_name){
mondigit = m_i+1;
break;
}
}
if(mondigit > 11 || mondigit < 23){
mondigit = mondigit - 12;
}
if(mondigit < 1 || mondigit > 12){
return 0;
}
return mondigit;
}

View file

@ -1,151 +1,192 @@
import {root} from './root';
import {isArray, isString, isUndef} from './types';
import {trim} from './string';
/**
* DOM utilities
*/
export default {
const doc = root.document;
/**
* Returns text + text of children of given node
* @param {NodeElement} node
* @return {String}
*/
getText(node){
let s = node.textContent || node.innerText ||
node.innerHTML.replace(/<[^<>]+>/g, '');
s = s.replace(/^\s+/, '').replace(/\s+$/, '');
return s;
},
/**
* Returns text + text of children of given node
* @param {NodeElement} node
* @return {String}
*/
export const getText = (node) => {
if (isUndef(node.textContent)) {
return trim(node.innerText);
}
return trim(node.textContent);
};
/**
* Creates an html element with given collection of attributes
* @param {String} tag a string of the html tag to create
* @param {Array} an undetermined number of arrays containing the with 2
* items, the attribute name and its value ['id','myId']
* @return {Object} created element
*/
create(tag){
if(!tag || tag===''){
return;
/**
* Returns the first text node contained in the supplied node
* @param {NodeElement} node node
* @return {String}
*/
export const getFirstTextNode = (node) => {
for (let i = 0; i < node.childNodes.length; i++) {
let n = node.childNodes[i];
if (n.nodeType === 3) {
return n.data;
}
let el = document.createElement(tag),
args = arguments;
if(args.length > 1){
for(let i=0; i<args.length; i++){
let argtype = typeof args[i];
if(argtype.toLowerCase() === 'object' && args[i].length === 2){
el.setAttribute(args[i][0], args[i][1]);
}
}
}
return el;
},
/**
* Removes passed node from DOM
* @param {DOMElement} node
* @return {DOMElement} old node reference
*/
remove(node){
return node.parentNode.removeChild(node);
},
/**
* Returns a text node with given text
* @param {String} txt
* @return {Object}
*/
text(txt){
return document.createTextNode(txt);
},
hasClass(ele, cls){
if(!ele){ return false; }
if(supportsClassList()){
return ele.classList.contains(cls);
}
return ele.className.match(new RegExp('(\\s|^)'+ cls +'(\\s|$)'));
},
addClass(ele, cls){
if(!ele){ return; }
if(supportsClassList()){
ele.classList.add(cls);
return;
}
if(ele.className === ''){
ele.className = cls;
}
else if(!this.hasClass(ele, cls)){
ele.className += ' ' + cls;
}
},
removeClass(ele, cls){
if(!ele){ return; }
if(supportsClassList()){
ele.classList.remove(cls);
return;
}
let reg = new RegExp('(\\s|^)'+ cls +'(\\s|$)', 'g');
ele.className = ele.className.replace(reg, '');
},
/**
* Creates and returns an option element
* @param {String} text option text
* @param {String} value option value
* @param {Boolean} isSel whether option is selected
* @return {Object} option element
*/
createOpt(text, value, isSel){
let isSelected = isSel ? true : false,
opt = isSelected ?
this.create('option', ['value',value], ['selected','true']) :
this.create('option', ['value',value]);
opt.appendChild(this.text(text));
return opt;
},
/**
* Creates and returns a checklist item
* @param {Number} chkIndex index of check item
* @param {String} chkValue check item value
* @param {String} labelText check item label text
* @return {Object} li DOM element
*/
createCheckItem(chkIndex, chkValue, labelText){
let li = this.create('li'),
label = this.create('label', ['for', chkIndex]),
check = this.create('input',
['id', chkIndex],
['name', chkIndex],
['type', 'checkbox'],
['value', chkValue]
);
label.appendChild(check);
label.appendChild(this.text(labelText));
li.appendChild(label);
li.label = label;
li.check = check;
return li;
},
id(key){
return document.getElementById(key);
},
tag(o, tagname){
return o.getElementsByTagName(tagname);
}
};
/**
* Creates an html element with given collection of attributes
* @param {String} tag html tag name
* @param {Array} an undetermined number of arrays containing the with 2
* items, the attribute name and its value ['id','myId']
* @return {Object} created element
*/
export const createElm = (...args) => {
let tag = args[0];
if (!isString(tag)) {
return null;
}
let el = doc.createElement(tag);
for (let i = 0; i < args.length; i++) {
let arg = args[i];
if (isArray(arg) && arg.length === 2) {
el.setAttribute(arg[0], arg[1]);
}
}
return el;
};
/**
* Removes passed node from DOM
* @param {DOMElement} node
* @return {DOMElement} old node reference
*/
export const removeElm = (node) => node.parentNode.removeChild(node);
/**
* Returns a text node with given text
* @param {String} txt
* @return {Object}
*/
export const createText = (txt) => doc.createTextNode(txt);
/**
* Determine whether the passed elements is assigned the given class
* @param {DOMElement} ele DOM element
* @param {String} cls CSS class name
* @returns {Boolean}
*/
export const hasClass = (ele, cls) => {
if (isUndef(ele)) {
return false;
}
if (supportsClassList()) {
return ele.classList.contains(cls);
}
return ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
};
/**
* Adds the specified class to the passed element
* @param {DOMElement} ele DOM element
* @param {String} cls CSS class name
*/
export const addClass = (ele, cls) => {
if (isUndef(ele)) {
return;
}
if (supportsClassList()) {
ele.classList.add(cls);
return;
}
if (ele.className === '') {
ele.className = cls;
}
else if (!hasClass(ele, cls)) {
ele.className += ' ' + cls;
}
};
/**
* Removes the specified class to the passed element
* @param {DOMElement} ele DOM element
* @param {String} cls CSS class name
*/
export const removeClass = (ele, cls) => {
if (isUndef(ele)) {
return;
}
if (supportsClassList()) {
ele.classList.remove(cls);
return;
}
let reg = new RegExp('(\\s|^)' + cls + '(\\s|$)', 'g');
ele.className = ele.className.replace(reg, '');
};
/**
* Creates and returns an option element
* @param {String} text option text
* @param {String} value option value
* @param {Boolean} isSel whether option is selected
* @return {Object} option element
*/
export const createOpt = (text, value, isSel) => {
let isSelected = isSel ? true : false;
let opt = isSelected ?
createElm('option', ['value', value], ['selected', 'true']) :
createElm('option', ['value', value]);
opt.appendChild(createText(text));
return opt;
};
/**
* Creates and returns a checklist item
* @param {String} id index of check item
* @param {String} chkValue check item value
* @param {String} labelText check item label text
* @param {Array} extraAttr array containing attribute name and its value
* @return {Object} li DOM element
*/
export const createCheckItem = (id, chkValue, labelText, extraAttr = []) => {
let li = createElm('li');
let label = createElm('label', ['for', id]);
let check = createElm('input',
['id', id],
['name', id],
['type', 'checkbox'],
['value', chkValue],
extraAttr
);
label.appendChild(check);
label.appendChild(createText(labelText));
li.appendChild(label);
li.label = label;
li.check = check;
return li;
};
/**
* Returns the element matching the supplied Id
* @param {String} id Element identifier
* @return {DOMElement}
*/
export const elm = (id) => doc.getElementById(id);
/**
* Returns list of element matching the supplied tag name
* @param {String} tagname Tag name
* @return {NodeList}
*/
export const tag = (o, tagname) => o.getElementsByTagName(tagname);
// HTML5 classList API
function supportsClassList(){
return document.documentElement.classList;
function supportsClassList() {
return doc.documentElement.classList;
}

53
src/emitter.js Normal file
View file

@ -0,0 +1,53 @@
/**
* Event emitter class
*/
export class Emitter {
/**
* Creates an instance of Emitter.
*/
constructor() {
/**
* Events object
* @type {Object}
*/
this.events = {};
}
/**
* Subscribe to an event
* @param {Array} evts Collection of event names
* @param {Function} fn Function invoked when event is emitted
*/
on(evts, fn) {
evts.forEach((evt) => {
this.events[evt] = this.events[evt] || [];
this.events[evt].push(fn);
});
}
/**
* Unsubscribe to an event
* @param {Array} evts Collection of event names
* @param {Function} fn Function invoked when event is emitted
*/
off(evts, fn) {
evts.forEach((evt) => {
if (evt in this.events) {
this.events[evt].splice(this.events[evt].indexOf(fn), 1);
}
});
}
/**
* Emit an event
* @param {String} evt Event name followed by any other argument passed to
* the invoked function
*/
emit(evt /*, args...*/) {
if (evt in this.events) {
for (let i = 0; i < this.events[evt].length; i++) {
this.events[evt][i].apply(this, [].slice.call(arguments, 1));
}
}
}
}

View file

@ -1,53 +1,124 @@
import {root} from './root';
/**
* DOM event utilities
*/
export default {
add(obj, type, func, capture){
if(obj.addEventListener){
obj.addEventListener(type, func, capture);
}
else if(obj.attachEvent){
obj.attachEvent('on'+type, func);
} else {
obj['on'+type] = func;
}
},
remove(obj, type, func, capture){
if(obj.detachEvent){
obj.detachEvent('on'+type,func);
}
else if(obj.removeEventListener){
obj.removeEventListener(type, func, capture);
} else {
obj['on'+type] = null;
}
},
stop(evt){
if(!evt){
evt = window.event;
}
if(evt.stopPropagation){
evt.stopPropagation();
} else {
evt.cancelBubble = true;
}
},
cancel(evt){
if(!evt){
evt = window.event;
}
if(evt.preventDefault) {
evt.preventDefault();
} else {
evt.returnValue = false;
}
},
target(evt){
return (evt && evt.target) || (window.event && window.event.srcElement);
},
keyCode(evt){
return evt.charCode ? evt.charCode :
(evt.keyCode ? evt.keyCode: (evt.which ? evt.which : 0));
/**
* Add event handler for specified event on passed element
*
* @param {DOMElement} obj Element
* @param {String} type Event type
* @param {Function} Handler
* @param {Boolean} capture Specifiy whether the event should be executed in
* the capturing or in the bubbling phase
*/
export const addEvt = (obj, type, func, capture) => {
if (obj.addEventListener) {
obj.addEventListener(type, func, capture);
}
else if (obj.attachEvent) {
obj.attachEvent('on' + type, func);
} else {
obj['on' + type] = func;
}
};
/**
* Remove event handler for specified event on passed element
*
* @param {DOMElement} obj Element
* @param {String} type Event type
* @param {Function} Handler
* @param {Boolean} capture Specifiy whether the event should be executed in
* the capturing or in the bubbling phase
*/
export const removeEvt = (obj, type, func, capture) => {
if (obj.removeEventListener) {
obj.removeEventListener(type, func, capture);
} else if (obj.detachEvent) {
obj.detachEvent('on' + type, func);
} else {
obj['on' + type] = null;
}
};
/**
* Prevents further propagation of the current event in the bubbling phase
*
* @param {Event} evt Event on the DOM
*/
export const stopEvt = (evt) => {
if (!evt) {
evt = root.event;
}
if (evt.stopPropagation) {
evt.stopPropagation();
} else {
evt.cancelBubble = true;
}
};
/**
* Cancels the event if it is cancelable, without stopping further
* propagation of the event.
*
* @param {Event} evt Event on the DOM
*/
export const cancelEvt = (evt) => {
if (!evt) {
evt = root.event;
}
if (evt.preventDefault) {
evt.preventDefault();
} else {
evt.returnValue = false;
}
};
/**
* Reference to the object that dispatched the event
*
* @param {Event} evt Event on the DOM
* @returns {DOMElement}
*/
export const targetEvt = (evt) => {
if (!evt) {
evt = root.event;
}
return evt.target || evt.srcElement;
};
/**
* Returns the Unicode value of pressed key
*
* @param {Event} evt Event on the DOM
* @returns {Number}
*/
export const keyCode = (evt) => {
return evt.charCode ? evt.charCode :
(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,116 +1,190 @@
import Dom from '../../dom';
import {Feature} from '../../feature';
import {tag} from '../../dom';
import {INPUT} from '../../const';
import {defaultsStr} from '../../settings';
import {root} from '../../root';
const INSTANTIATION_ERROR = `Failed to instantiate EditTable object.
\n"ezEditTable" dependency not found.`;
/**
* Adapter module for ezEditTable, an external library providing advanced
* grid features (selection and edition):
* http://codecanyon.net/item/ezedittable-enhance-html-tables/2425123?ref=koalyptus
*/
export default class AdapterEzEditTable extends Feature {
export default class AdapterEzEditTable {
/**
* Adapter module for ezEditTable, an external library providing advanced
* grid features (selection and edition):
* http://codecanyon.net/item/ezedittable-enhance-html-tables/2425123?ref=koalyptus
* Creates an instance of AdapterEzEditTable
*
* @param {Object} tf TableFilter instance
* @param {TableFilter} tf TableFilter instance
* @param {Object} cfg Configuration options for ezEditTable library
*/
constructor(tf, cfg){
// ezEditTable config
this.initialized = false;
this.desc = cfg.description || 'ezEditTable adapter';
this.filename = cfg.filename || 'ezEditTable.js';
constructor(tf, cfg) {
super(tf, AdapterEzEditTable);
/**
* Module description
* @type {String}
*/
this.desc = defaultsStr(cfg.description, 'ezEditTable adapter');
/**
* Filename of ezEditTable library
* @type {String}
*/
this.filename = defaultsStr(cfg.filename, 'ezEditTable.js');
/**
* Path to ezEditTable library
* @type {String}
*/
this.vendorPath = cfg.vendor_path;
/**
* Load ezEditTable stylesheet
* @type {Boolean}
*/
this.loadStylesheet = Boolean(cfg.load_stylesheet);
this.stylesheet = cfg.stylesheet || this.vendorPath + 'ezEditTable.css';
this.stylesheetName = cfg.stylesheet_name || 'ezEditTableCss';
this.err = 'Failed to instantiate EditTable object.\n"ezEditTable" ' +
'dependency not found.';
/**
* Path to ezEditTable stylesheet
* @type {String}
*/
this.stylesheet = defaultsStr(cfg.stylesheet,
this.vendorPath + 'ezEditTable.css');
/**
* Name of ezEditTable stylesheet
* @type {String}
*/
this.stylesheetName = defaultsStr(cfg.stylesheet_name,
'ezEditTableCss');
// 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 ?
false : tf.gridLayout;
/**
* ezEditTable instance
* @type {EditTable}
* @private
*/
this._ezEditTable = null;
/**
* ezEditTable configuration
* @private
*/
this.cfg = cfg;
this.tf = tf;
this.enable();
}
/**
* Conditionally load ezEditTable library and set advanced grid
* @return {[type]} [description]
*/
init(){
var tf = this.tf;
if(window.EditTable){
init() {
if (this.initialized) {
return;
}
let tf = this.tf;
if (root.EditTable) {
this._setAdvancedGrid();
} else {
var path = this.vendorPath + this.filename;
tf.import(this.filename, path, ()=> { this._setAdvancedGrid(); });
let path = this.vendorPath + this.filename;
tf.import(this.filename, path, () => this._setAdvancedGrid());
}
if(this.loadStylesheet && !tf.isImported(this.stylesheet, 'link')){
if (this.loadStylesheet && !tf.isImported(this.stylesheet, 'link')) {
tf.import(this.stylesheetName, this.stylesheet, null, 'link');
}
// TODO: hack to prevent ezEditTable enter key event hijaking.
// Needs to be fixed in the vendor's library
this.emitter.on(['filter-focus', 'filter-blur'],
() => this._toggleForInputFilter());
/**
* @inherited
*/
this.initialized = true;
}
/**
* Instantiate ezEditTable component for advanced grid features
* @private
*/
_setAdvancedGrid(){
var tf = this.tf;
_setAdvancedGrid() {
let tf = this.tf;
//start row for EditTable constructor needs to be calculated
var startRow,
let startRow,
cfg = this.cfg,
thead = Dom.tag(tf.tbl, 'thead');
thead = tag(tf.dom(), 'thead');
//if thead exists and startRow not specified, startRow is calculated
//automatically by EditTable
if(thead.length > 0 && !cfg.startRow){
if (thead.length > 0 && !cfg.startRow) {
startRow = undefined;
}
//otherwise startRow config property if any or TableFilter refRow
else{
else {
startRow = cfg.startRow || tf.refRow;
}
cfg.base_path = cfg.base_path || tf.basePath + 'ezEditTable/';
var editable = cfg.editable;
var selectable = cfg.selection;
cfg.base_path = cfg.base_path || tf.basePath + 'ezEditTable/';
let editable = cfg.editable;
let selectable = cfg.selection;
if(selectable){
if (selectable) {
cfg.default_selection = cfg.default_selection || 'row';
}
//CSS Styles
cfg.active_cell_css = cfg.active_cell_css || 'ezETSelectedCell';
var _lastValidRowIndex = 0;
var _lastRowIndex = 0;
let _lastValidRowIndex = 0;
let _lastRowIndex = 0;
if(selectable){
if (selectable) {
//Row navigation needs to be calculated according to TableFilter's
//validRowsIndex array
var onAfterSelection = function(et, selectedElm, e){
var slc = et.Selection;
let onAfterSelection = function (et, selectedElm, e) {
let slc = et.Selection;
//Next valid filtered row needs to be selected
var doSelect = function(nextRowIndex){
if(et.defaultSelection === 'row'){
let doSelect = function (nextRowIndex) {
if (et.defaultSelection === 'row') {
/* eslint-disable */
slc.SelectRowByIndex(nextRowIndex);
/* eslint-enable */
} else {
/* eslint-disable */
et.ClearSelections();
var cellIndex = selectedElm.cellIndex,
row = tf.tbl.rows[nextRowIndex];
if(et.defaultSelection === 'both'){
/* eslint-enable */
let cellIndex = selectedElm.cellIndex,
row = tf.dom().rows[nextRowIndex];
if (et.defaultSelection === 'both') {
/* eslint-disable */
slc.SelectRowByIndex(nextRowIndex);
/* eslint-enable */
}
if(row){
if (row) {
/* eslint-disable */
slc.SelectCell(row.cells[cellIndex]);
/* eslint-enable */
}
}
//Table is filtered
if(tf.validRowsIndex.length !== tf.getRowsNb()){
var r = tf.tbl.rows[nextRowIndex];
if(r){
if (tf.validRowsIndex.length !== tf.getRowsNb()) {
let r = tf.dom().rows[nextRowIndex];
if (r) {
r.scrollIntoView(false);
}
if(cell){
if(cell.cellIndex === (tf.getCellsNb()-1) &&
tf.gridLayout){
if (cell) {
if (cell.cellIndex === (tf.getCellsNb() - 1) &&
tf.gridLayout) {
tf.tblCont.scrollLeft = 100000000;
}
else if(cell.cellIndex===0 && tf.gridLayout){
else if (cell.cellIndex === 0 && tf.gridLayout) {
tf.tblCont.scrollLeft = 0;
} else {
cell.scrollIntoView(false);
@ -120,45 +194,48 @@ export default class AdapterEzEditTable {
};
//table is not filtered
if(!tf.validRowsIndex){
if (!tf.validRowsIndex) {
return;
}
var validIndexes = tf.validRowsIndex,
let validIndexes = tf.validRowsIndex,
validIdxLen = validIndexes.length,
row = et.defaultSelection !== 'row' ?
selectedElm.parentNode : selectedElm,
//cell for default_selection = 'both' or 'cell'
cell = selectedElm.nodeName==='TD' ? selectedElm : null,
cell = selectedElm.nodeName === 'TD' ? selectedElm : null,
/* eslint-disable */
keyCode = e !== undefined ? et.Event.GetKey(e) : 0,
/* eslint-enable */
isRowValid = validIndexes.indexOf(row.rowIndex) !== -1,
nextRowIndex,
paging = tf.feature('paging'),
//pgup/pgdown keys
d = (keyCode === 34 || keyCode === 33 ?
(paging && paging.pagingLength || et.nbRowsPerPage) :1);
d = keyCode === 34 || keyCode === 33 ?
(paging && paging.pageLength || et.nbRowsPerPage) :
1;
//If next row is not valid, next valid filtered row needs to be
//calculated
if(!isRowValid){
if (!isRowValid) {
//Selection direction up/down
if(row.rowIndex>_lastRowIndex){
if (row.rowIndex > _lastRowIndex) {
//last row
if(row.rowIndex >= validIndexes[validIdxLen-1]){
nextRowIndex = validIndexes[validIdxLen-1];
if (row.rowIndex >= validIndexes[validIdxLen - 1]) {
nextRowIndex = validIndexes[validIdxLen - 1];
} else {
var calcRowIndex = (_lastValidRowIndex + d);
if(calcRowIndex > (validIdxLen-1)){
nextRowIndex = validIndexes[validIdxLen-1];
let calcRowIndex = (_lastValidRowIndex + d);
if (calcRowIndex > (validIdxLen - 1)) {
nextRowIndex = validIndexes[validIdxLen - 1];
} else {
nextRowIndex = validIndexes[calcRowIndex];
}
}
} else{
} else {
//first row
if(row.rowIndex <= validIndexes[0]){
if (row.rowIndex <= validIndexes[0]) {
nextRowIndex = validIndexes[0];
} else {
var v = validIndexes[_lastValidRowIndex - d];
let v = validIndexes[_lastValidRowIndex - d];
nextRowIndex = v ? v : validIndexes[0];
}
}
@ -167,21 +244,21 @@ export default class AdapterEzEditTable {
} else {
//If filtered row is valid, special calculation for
//pgup/pgdown keys
if(keyCode!==34 && keyCode!==33){
if (keyCode !== 34 && keyCode !== 33) {
_lastValidRowIndex = validIndexes.indexOf(row.rowIndex);
_lastRowIndex = row.rowIndex;
} else {
if(keyCode === 34){ //pgdown
if (keyCode === 34) { //pgdown
//last row
if((_lastValidRowIndex + d) <= (validIdxLen-1)){
if ((_lastValidRowIndex + d) <= (validIdxLen - 1)) {
nextRowIndex = validIndexes[
_lastValidRowIndex + d];
_lastValidRowIndex + d];
} else {
nextRowIndex = [validIdxLen-1];
nextRowIndex = [validIdxLen - 1];
}
} else { //pgup
//first row
if((_lastValidRowIndex - d) <= validIndexes[0]){
if ((_lastValidRowIndex - d) <= validIndexes[0]) {
nextRowIndex = validIndexes[0];
} else {
nextRowIndex = validIndexes[
@ -197,35 +274,35 @@ export default class AdapterEzEditTable {
//Page navigation has to be enforced whenever selected row is out of
//the current page range
var onBeforeSelection = function(et, selectedElm){
var row = et.defaultSelection !== 'row' ?
let onBeforeSelection = function (et, selectedElm) {
let row = et.defaultSelection !== 'row' ?
selectedElm.parentNode : selectedElm;
if(tf.paging){
if(tf.feature('paging').nbPages > 1){
var paging = tf.feature('paging');
if (tf.paging) {
if (tf.feature('paging').nbPages > 1) {
let paging = tf.feature('paging');
//page length is re-assigned in case it has changed
et.nbRowsPerPage = paging.pagingLength;
var validIndexes = tf.validRowsIndex,
et.nbRowsPerPage = paging.pageLength;
let validIndexes = tf.validRowsIndex,
validIdxLen = validIndexes.length,
pagingEndRow = parseInt(paging.startPagingRow, 10) +
parseInt(paging.pagingLength, 10);
var rowIndex = row.rowIndex;
parseInt(paging.pageLength, 10);
let rowIndex = row.rowIndex;
if((rowIndex === validIndexes[validIdxLen-1]) &&
paging.currentPageNb!==paging.nbPages){
if ((rowIndex === validIndexes[validIdxLen - 1]) &&
paging.currentPageNb !== paging.nbPages) {
paging.setPage('last');
}
else if((rowIndex == validIndexes[0]) &&
paging.currentPageNb!==1){
else if ((rowIndex === validIndexes[0]) &&
paging.currentPageNb !== 1) {
paging.setPage('first');
}
else if(rowIndex > validIndexes[pagingEndRow-1] &&
rowIndex < validIndexes[validIdxLen-1]){
else if (rowIndex > validIndexes[pagingEndRow - 1] &&
rowIndex < validIndexes[validIdxLen - 1]) {
paging.setPage('next');
}
else if(
else if (
rowIndex < validIndexes[paging.startPagingRow] &&
rowIndex > validIndexes[0]){
rowIndex > validIndexes[0]) {
paging.setPage('previous');
}
}
@ -233,17 +310,21 @@ export default class AdapterEzEditTable {
};
//Selected row needs to be visible when paging is activated
if(tf.paging){
tf.feature('paging').onAfterChangePage = function(paging){
var advGrid = paging.tf.extension('advancedGrid');
var et = advGrid._ezEditTable;
var slc = et.Selection;
var row = slc.GetActiveRow();
if(row){
if (tf.paging) {
tf.feature('paging').onAfterChangePage = function (paging) {
let advGrid = paging.tf.extension('advancedGrid');
let et = advGrid._ezEditTable;
let slc = et.Selection;
/* eslint-disable */
let row = slc.GetActiveRow();
/* eslint-enable */
if (row) {
row.scrollIntoView(false);
}
var cell = slc.GetActiveCell();
if(cell){
/* eslint-disable */
let cell = slc.GetActiveCell();
/* eslint-enable */
if (cell) {
cell.scrollIntoView(false);
}
};
@ -251,92 +332,92 @@ export default class AdapterEzEditTable {
//Rows navigation when rows are filtered is performed with the
//EditTable row selection callback events
if(cfg.default_selection==='row'){
var fnB = cfg.on_before_selected_row;
cfg.on_before_selected_row = function(){
onBeforeSelection(arguments[0], arguments[1], arguments[2]);
if(fnB){
fnB.call(
null, arguments[0], arguments[1], arguments[2]);
if (cfg.default_selection === 'row') {
let fnB = cfg.on_before_selected_row;
cfg.on_before_selected_row = function () {
var args = arguments;
onBeforeSelection(args[0], args[1], args[2]);
if (fnB) {
fnB.call(null, args[0], args[1], args[2]);
}
};
var fnA = cfg.on_after_selected_row;
cfg.on_after_selected_row = function(){
onAfterSelection(arguments[0], arguments[1], arguments[2]);
if(fnA){
fnA.call(
null, arguments[0], arguments[1], arguments[2]);
let fnA = cfg.on_after_selected_row;
cfg.on_after_selected_row = function () {
var args = arguments;
onAfterSelection(args[0], args[1], args[2]);
if (fnA) {
fnA.call(null, args[0], args[1], args[2]);
}
};
} else {
var fnD = cfg.on_before_selected_cell;
cfg.on_before_selected_cell = function(){
onBeforeSelection(arguments[0], arguments[1], arguments[2]);
if(fnD){
fnD.call(
null, arguments[0], arguments[1], arguments[2]);
let fnD = cfg.on_before_selected_cell;
cfg.on_before_selected_cell = function () {
var args = arguments;
onBeforeSelection(args[0], args[1], args[2]);
if (fnD) {
fnD.call(null, args[0], args[1], args[2]);
}
};
var fnC = cfg.on_after_selected_cell;
cfg.on_after_selected_cell = function(){
onAfterSelection(arguments[0], arguments[1], arguments[2]);
if(fnC){
fnC.call(
null, arguments[0], arguments[1], arguments[2]);
let fnC = cfg.on_after_selected_cell;
cfg.on_after_selected_cell = function () {
var args = arguments;
onAfterSelection(args[0], args[1], args[2]);
if (fnC) {
fnC.call(null, args[0], args[1], args[2]);
}
};
}
}
if(editable){
if (editable) {
//Added or removed rows, TF rows number needs to be re-calculated
var fnE = cfg.on_added_dom_row;
cfg.on_added_dom_row = function(){
let fnE = cfg.on_added_dom_row;
cfg.on_added_dom_row = function () {
var args = arguments;
tf.nbFilterableRows++;
if(!tf.paging){
tf.feature('rowsCounter').refresh();
if (!tf.paging) {
tf.emitter.emit('rows-changed', tf, this);
} else {
tf.nbRows++;
tf.nbVisibleRows++;
tf.nbFilterableRows++;
tf.paging=false;
tf.paging = false;
tf.feature('paging').destroy();
tf.feature('paging').reset();
}
if(tf.alternateRows){
if (tf.alternateRows) {
tf.feature('alternateRows').init();
}
if(fnE){
fnE.call(null, arguments[0], arguments[1], arguments[2]);
if (fnE) {
fnE.call(null, args[0], args[1], args[2]);
}
};
if(cfg.actions && cfg.actions['delete']){
var fnF = cfg.actions['delete'].on_after_submit;
cfg.actions['delete'].on_after_submit = function(){
if (cfg.actions && cfg.actions['delete']) {
let fnF = cfg.actions['delete'].on_after_submit;
cfg.actions['delete'].on_after_submit = function () {
var args = arguments;
tf.nbFilterableRows--;
if(!tf.paging){
tf.feature('rowsCounter').refresh();
if (!tf.paging) {
tf.emitter.emit('rows-changed', tf, this);
} else {
tf.nbRows--;
tf.nbVisibleRows--;
tf.nbFilterableRows--;
tf.paging=false;
tf.paging = false;
tf.feature('paging').destroy();
tf.feature('paging').reset(false);
}
if(tf.alternateRows){
if (tf.alternateRows) {
tf.feature('alternateRows').init();
}
if(fnF){
fnF.call(null, arguments[0], arguments[1]);
if (fnF) {
fnF.call(null, args[0], args[1]);
}
};
}
}
try{
try {
/* eslint-disable */
this._ezEditTable = new EditTable(tf.id, cfg, startRow);
this._ezEditTable.Init();
} catch(e) { throw new Error(this.err); }
/* eslint-enable */
} catch (e) { throw new Error(INSTANTIATION_ERROR); }
this.initialized = true;
}
@ -344,32 +425,85 @@ export default class AdapterEzEditTable {
/**
* Reset advanced grid when previously removed
*/
reset(){
var ezEditTable = this._ezEditTable;
if(ezEditTable){
if(this.cfg.selection){
reset() {
let ezEditTable = this._ezEditTable;
if (ezEditTable) {
if (this.cfg.selection) {
/* eslint-disable */
ezEditTable.Selection.Set();
/* eslint-enable */
}
if(this.cfg.editable){
if (this.cfg.editable) {
/* eslint-disable */
ezEditTable.Editable.Set();
/* eslint-enable */
}
}
}
/**
* Toggle behaviour
*/
toggle() {
let ezEditTable = this._ezEditTable;
if (ezEditTable.editable) {
/* eslint-disable */
ezEditTable.Editable.Remove();
/* eslint-enable */
} else {
/* eslint-disable */
ezEditTable.Editable.Set();
/* eslint-enable */
}
if (ezEditTable.selection) {
/* eslint-disable */
ezEditTable.Selection.Remove();
/* eslint-enable */
} else {
/* eslint-disable */
ezEditTable.Selection.Set();
/* eslint-enable */
}
}
_toggleForInputFilter() {
let tf = this.tf;
if (!tf.getActiveFilterId()) {
return;
}
let colIndex = tf.getColumnIndexFromFilterId(tf.getActiveFilterId());
let filterType = tf.getFilterType(colIndex);
if (filterType === INPUT) {
this.toggle();
}
}
/**
* Remove advanced grid
*/
destroy(){
var ezEditTable = this._ezEditTable;
if(ezEditTable){
if(this.cfg.selection){
destroy() {
if (!this.initialized) {
return;
}
let ezEditTable = this._ezEditTable;
if (ezEditTable) {
if (this.cfg.selection) {
/* eslint-disable */
ezEditTable.Selection.ClearSelections();
ezEditTable.Selection.Remove();
/* eslint-enable */
}
if(this.cfg.editable){
if (this.cfg.editable) {
/* eslint-disable */
ezEditTable.Editable.Remove();
/* eslint-enable */
}
}
this.emitter.off(['filter-focus', 'filter-blur'],
() => this._toggleForInputFilter());
this.initialized = false;
}
}
AdapterEzEditTable.meta = {altName: 'advancedGrid'};

View file

@ -1,28 +1,127 @@
import Dom from '../../dom';
import Str from '../../string';
import Types from '../../types';
import {Feature} from '../../feature';
import {createText, elm} from '../../dom';
import {isArray, isEmpty, EMPTY_FN} from '../../types';
import {numSortAsc} from '../../sort';
import {FORMATTED_NUMBER} from '../../const';
import formatNumber from 'format-number';
import {defaultsFn, defaultsArr} from '../../settings';
import {bound} from '../../event';
export default class ColOps{
const EVENTS = [
'after-filtering',
'after-page-change',
'after-page-length-change'
];
const SUM = 'sum';
const MEAN = 'mean';
const MIN = 'min';
const MAX = 'max';
const MEDIAN = 'median';
const Q1 = 'q1';
const Q3 = 'q3';
/**
* Column calculations extension
*/
export default class ColOps extends Feature {
/**
* Column calculations
* @param {Object} tf TableFilter instance
* Creates an instance of ColOps
*
* @param {TableFilter} tf TableFilter instance
* @param {Object} opts Configuration object
*/
constructor(tf, opts) {
super(tf, ColOps);
//calls function before col operation
this.onBeforeOperation = Types.isFn(opts.on_before_operation) ?
opts.on_before_operation : null;
//calls function after col operation
this.onAfterOperation = Types.isFn(opts.on_after_operation) ?
opts.on_after_operation : null;
/**
* Callback fired before columns operations start
* @type {Function}
*/
this.onBeforeOperation = defaultsFn(opts.on_before_operation, EMPTY_FN);
/**
* Callback fired after columns operations are completed
* @type {Function}
*/
this.onAfterOperation = defaultsFn(opts.on_after_operation, EMPTY_FN);
/**
* Configuration options
* @type {Object}
*/
this.opts = opts;
this.tf = tf;
/**
* List of DOM element IDs containing column's calculation result
* @type {Array}
*/
this.labelIds = defaultsArr(opts.id, []);
/**
* List of columns' indexes for calculations
* @type {Array}
*/
this.colIndexes = defaultsArr(opts.col, []);
/**
* List of operations - possible values: 'sum', 'mean', 'min', 'max',
* 'median', 'q1', 'q3'
* @type {Array}
*/
this.operations = defaultsArr(opts.operation, []);
/**
* List of write methods used to write the result - possible values:
* 'innerHTML', 'setValue', 'createTextNode'
* @type {Array}
*/
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
* @type {Array}
*/
this.totRowIndexes = defaultsArr(opts.tot_row_index, []);
/**
* List of row indexes excluded from calculations
* @type {Array}
*/
this.excludeRows = defaultsArr(opts.exclude_row, []);
/**
* List of decimal precision for calculation results
* @type {Array}
*/
this.decimalPrecisions = defaultsArr(opts.decimal_precision, 2);
this.enable();
}
init(){
this.calc();
/**
* Initializes ColOps instance
*/
init() {
if (this.initialized) {
return;
}
// subscribe to events
this.emitter.on(EVENTS, bound(this.calcAll, this));
this.calcAll();
/** @inherited */
this.initialized = true;
}
/**
@ -41,275 +140,341 @@ export default class ColOps{
* (1) optimized the routine (now it will only process each column once),
* (2) added calculations for the median, lower and upper quartile.
*/
calc() {
var tf = this.tf;
if(!tf.isFirstLoad && !tf.hasGrid()){
calcAll() {
let tf = this.tf;
if (!tf.isInitialized()) {
return;
}
if(this.onBeforeOperation){
this.onBeforeOperation.call(null, tf);
}
this.onBeforeOperation(tf, this);
this.emitter.emit('before-column-operation', tf, this);
var opts = this.opts,
labelId = opts.id,
colIndex = opts.col,
operation = opts.operation,
outputType = opts.write_method,
totRowIndex = opts.tot_row_index,
excludeRow = opts.exclude_row,
decimalPrecision = Types.isUndef(opts.decimal_precision) ?
2 : opts.decimal_precision;
let { colIndexes, operations: colOperations, outputTypes,
totRowIndexes, excludeRows, formatResults,
decimalPrecisions } = this;
//nuovella: determine unique list of columns to operate on
var ucolIndex = [],
ucolMax = 0;
ucolIndex[ucolMax] = colIndex[0];
let uIndexes = [];
colIndexes.forEach((val) => {
if (uIndexes.indexOf(val) === -1) {
uIndexes.push(val);
}
});
for(var ii=1; ii<colIndex.length; ii++){
var saved = 0;
//see if colIndex[ii] is already in the list of unique indexes
for(var jj=0; jj<=ucolMax; jj++){
if(ucolIndex[jj] === colIndex[ii]){
saved = 1;
let nbCols = uIndexes.length,
rows = tf.dom().rows,
colValues = [];
for (let u = 0; u < nbCols; u++) {
//this retrieves col values
//use uIndexes because we only want to pass through this loop
//once for each column get the values in this unique column
colValues.push(
tf.getVisibleColumnData(uIndexes[u], false, excludeRows)
);
let curValues = colValues[u];
//next: calculate all operations for this column
let result = 0,
operations = [],
precisions = [],
labels = [],
writeType,
formatResult = [],
idx = 0;
for (let k = 0; k < colIndexes.length; k++) {
if (colIndexes[k] !== uIndexes[u]) {
continue;
}
operations[idx] = (colOperations[k] || 'sum').toLowerCase();
precisions[idx] = decimalPrecisions[k];
labels[idx] = this.labelIds[k];
writeType = isArray(outputTypes) ? outputTypes[k] : null;
formatResult[idx] =
this.configureFormat(uIndexes[u], formatResults[k]);
idx++;
}
//if not saved then, save the index;
if (saved === 0){
ucolMax++;
ucolIndex[ucolMax] = colIndex[ii];
for (let i = 0; i < idx; i++) {
// emit values before column calculation
this.emitter.emit(
'before-column-calc',
tf,
this,
uIndexes[u],
curValues,
operations[i],
precisions[i]
);
result = Number(this.calc(curValues, operations[i], null));
// emit column calculation result
this.emitter.emit(
'column-calc',
tf,
this,
uIndexes[u],
result,
operations[i],
precisions[i]
);
// write result in expected DOM element
this.writeResult(
result,
labels[i],
writeType,
precisions[i],
formatResult[i]
);
}//for i
// row(s) with result are always visible
let totRow = totRowIndexes && totRowIndexes[u] ?
rows[totRowIndexes[u]] : null;
if (totRow) {
totRow.style.display = '';
}
}//for u
this.onAfterOperation(tf, this);
this.emitter.emit('after-column-operation', tf, this);
}
/**
* Make desired calculation on specified column.
* @param {Number} colIndex Column index
* @param {String} [operation=SUM] Operation type
* @param {Number} precision Decimal precision
* @returns {Number}
*/
columnCalc(colIndex, operation = SUM, precision) {
let excludeRows = this.excludeRows || [];
let colValues = tf.getVisibleColumnData(colIndex, false, excludeRows);
return Number(this.calc(colValues, operation, precision));
}
/**
* Make calculation on passed values.
* @param {Array} values List of values
* @param {String} [operation=SUM] Optional operation type
* @param {Number} precision Optional result precision
* @returns {Number}
* @private
*/
calc(colValues, operation = SUM, precision) {
let result = 0;
if (operation === Q1 || operation === Q3 || operation === MEDIAN) {
colValues = this.sortColumnValues(colValues, numSortAsc);
}
if(Str.lower(typeof labelId)=='object' &&
Str.lower(typeof colIndex)=='object' &&
Str.lower(typeof operation)=='object'){
var rows = tf.tbl.rows,
colvalues = [];
switch (operation) {
case MEAN:
result = this.calcMean(colValues);
break;
case SUM:
result = this.calcSum(colValues);
break;
case MIN:
result = this.calcMin(colValues);
break;
case MAX:
result = this.calcMax(colValues);
break;
case MEDIAN:
result = this.calcMedian(colValues);
break;
case Q1:
result = this.calcQ1(colValues);
break;
case Q3:
result = this.calcQ3(colValues);
break;
}
for(var ucol=0; ucol<=ucolMax; ucol++){
//this retrieves col values
//use ucolIndex because we only want to pass through this loop
//once for each column get the values in this unique column
colvalues.push(
tf.getColValues(ucolIndex[ucol], false, true, excludeRow));
return isEmpty(precision) ? result : result.toFixed(precision);
}
//next: calculate all operations for this column
var result,
nbvalues=0,
temp,
meanValue=0,
sumValue=0,
minValue=null,
maxValue=null,
q1Value=null,
medValue=null,
q3Value=null,
meanFlag=0,
sumFlag=0,
minFlag=0,
maxFlag=0,
q1Flag=0,
medFlag=0,
q3Flag=0,
theList=[],
opsThisCol=[],
decThisCol=[],
labThisCol=[],
oTypeThisCol=[],
mThisCol=-1;
/**
* Calculate the sum of passed values.
* @param {Array} [values=[]] List of values
* @returns {Number}
*/
calcSum(values = []) {
if (isEmpty(values)) {
return 0;
}
let result = values.reduce((x, y) => Number(x) + Number(y));
return result;
}
for(var k=0; k<colIndex.length; k++){
if(colIndex[k] === ucolIndex[ucol]){
mThisCol++;
opsThisCol[mThisCol]=Str.lower(operation[k]);
decThisCol[mThisCol]=decimalPrecision[k];
labThisCol[mThisCol]=labelId[k];
oTypeThisCol = outputType !== undefined &&
Str.lower(typeof outputType)==='object' ?
outputType[k] : null;
/**
* Calculate the mean of passed values.
* @param {Array} [values=[]] List of values
* @returns {Number}
*/
calcMean(values = []) {
let result = this.calcSum(values) / values.length;
return Number(result);
}
switch(opsThisCol[mThisCol]){
case 'mean':
meanFlag=1;
break;
case 'sum':
sumFlag=1;
break;
case 'min':
minFlag=1;
break;
case 'max':
maxFlag=1;
break;
case 'median':
medFlag=1;
break;
case 'q1':
q1Flag=1;
break;
case 'q3':
q3Flag=1;
break;
}
}
}
/**
* Calculate the max value of passed values.
* @param {Array} [values=[]] List of values
* @returns {Number}
*/
calcMax(values = []) {
return Math.max.apply(null, values);
}
for(var j=0; j<colvalues[ucol].length; j++){
//sort the list for calculation of median and quartiles
if((q1Flag==1)|| (q3Flag==1) || (medFlag==1)){
if (j<colvalues[ucol].length -1){
for(k=j+1; k<colvalues[ucol].length; k++) {
if(eval(colvalues[ucol][k]) <
eval(colvalues[ucol][j])){
temp = colvalues[ucol][j];
colvalues[ucol][j] = colvalues[ucol][k];
colvalues[ucol][k] = temp;
}
}
}
}
var cvalue = parseFloat(colvalues[ucol][j]);
theList[j] = parseFloat(cvalue);
/**
* Calculate the min value of passed values.
* @param {Array} [values=[]] List of values
* @returns {Number}
*/
calcMin(values = []) {
return Math.min.apply(null, values);
}
if(!isNaN(cvalue)){
nbvalues++;
if(sumFlag===1 || meanFlag===1){
sumValue += parseFloat( cvalue );
}
if(minFlag===1){
if(minValue===null){
minValue = parseFloat( cvalue );
} else{
minValue = parseFloat( cvalue ) < minValue ?
parseFloat( cvalue ): minValue;
}
}
if(maxFlag===1){
if (maxValue===null){
maxValue = parseFloat( cvalue );
} else {
maxValue = parseFloat( cvalue ) > maxValue ?
parseFloat( cvalue ): maxValue;
}
}
}
}//for j
if(meanFlag===1){
meanValue = sumValue/nbvalues;
}
if(medFlag===1){
var aux = 0;
if(nbvalues%2 === 1){
aux = Math.floor(nbvalues/2);
medValue = theList[aux];
} else{
medValue =
(theList[nbvalues/2] + theList[((nbvalues/2)-1)])/2;
}
}
var posa;
if(q1Flag===1){
posa=0.0;
posa = Math.floor(nbvalues/4);
if(4*posa == nbvalues){
q1Value = (theList[posa-1] + theList[posa])/2;
} else {
q1Value = theList[posa];
}
}
if (q3Flag===1){
posa=0.0;
var posb=0.0;
posa = Math.floor(nbvalues/4);
if (4*posa === nbvalues){
posb = 3*posa;
q3Value = (theList[posb] + theList[posb-1])/2;
} else {
q3Value = theList[nbvalues-posa-1];
}
}
/**
* Calculate the median of passed values.
* @param {Array} [values=[]] List of values
* @returns {Number}
*/
calcMedian(values = []) {
let nbValues = values.length;
let aux = 0;
if (nbValues % 2 === 1) {
aux = Math.floor(nbValues / 2);
return Number(values[aux]);
}
return (Number(values[nbValues / 2]) +
Number(values[((nbValues / 2) - 1)])) / 2;
}
for(var i=0; i<=mThisCol; i++){
switch( opsThisCol[i] ){
case 'mean':
result=meanValue;
break;
case 'sum':
result=sumValue;
break;
case 'min':
result=minValue;
break;
case 'max':
result=maxValue;
break;
case 'median':
result=medValue;
break;
case 'q1':
result=q1Value;
break;
case 'q3':
result=q3Value;
break;
}
/**
* Calculate the lower quartile of passed values.
* @param {Array} [values=[]] List of values
* @returns {Number}
*/
calcQ1(values = []) {
let nbValues = values.length;
let posa = 0.0;
posa = Math.floor(nbValues / 4);
if (4 * posa === nbValues) {
return (Number(values[posa - 1]) +
Number(values[posa])) / 2;
}
return Number(values[posa]);
}
var precision = !isNaN(decThisCol[i]) ? decThisCol[i] : 2;
/**
* Calculate the upper quartile of passed values.
* @param {Array} [values=[]] List of values
* @returns {Number}
*/
calcQ3(values = []) {
let nbValues = values.length;
let posa = 0.0;
let posb = 0.0;
posa = Math.floor(nbValues / 4);
if (4 * posa === nbValues) {
posb = 3 * posa;
return (Number(values[posb]) +
Number(values[posb - 1])) / 2;
}
return Number(values[nbValues - posa - 1]);
}
//if outputType is defined
if(oTypeThisCol && result){
result = result.toFixed( precision );
/**
* Sort passed values with supplied sorter function.
* @param {Array} [values=[]] List of values to be sorted
* @param {Function} sorter Sorter function
* @returns {Array}
*/
sortColumnValues(values = [], sorter) {
return values.sort(sorter);
}
if(Dom.id(labThisCol[i])){
switch( Str.lower(oTypeThisCol) ){
case 'innerhtml':
if (isNaN(result) || !isFinite(result) ||
nbvalues===0){
Dom.id(labThisCol[i]).innerHTML = '.';
} else{
Dom.id(labThisCol[i]).innerHTML= result;
}
break;
case 'setvalue':
Dom.id( labThisCol[i] ).value = result;
break;
case 'createtextnode':
var oldnode = Dom.id(labThisCol[i])
.firstChild;
var txtnode = Dom.text(result);
Dom.id(labThisCol[i])
.replaceChild(txtnode, oldnode);
break;
}//switch
}
} else {
try{
if(isNaN(result) || !isFinite(result) ||
nbvalues===0){
Dom.id(labThisCol[i]).innerHTML = '.';
} else {
Dom.id(labThisCol[i]).innerHTML =
result.toFixed(precision);
}
} catch(e) {}//catch
}//else
}//for i
/**
* Write calculation result in passed DOM element with supplied write method
* and decimal precision.
* @param {Number} [result=0] Calculation result
* @param {DOMElement} label DOM element
* @param {String} [writeType='innerhtml'] Write method
* @param {Number} [precision=2] Applied decimal precision
* @private
*/
writeResult(result = 0, label, writeType = 'innerhtml',
precision = 2, format = {}) {
let labelElm = elm(label);
// row(s) with result are always visible
var totRow = totRowIndex && totRowIndex[ucol] ?
rows[totRowIndex[ucol]] : null;
if(totRow){
totRow.style.display = '';
}
}//for ucol
}//if typeof
if (!labelElm) {
return;
}
if(this.onAfterOperation){
this.onAfterOperation.call(null, tf);
result = result.toFixed(precision);
if (isNaN(result) || !isFinite(result)) {
result = '';
} else {
result = formatNumber(format)(result);
}
switch (writeType.toLowerCase()) {
case 'innerhtml':
labelElm.innerHTML = result;
break;
case 'setvalue':
labelElm.value = result;
break;
case 'createtextnode':
let oldNode = labelElm.firstChild;
let txtNode = createText(result);
labelElm.replaceChild(txtNode, oldNode);
break;
}
}
destroy(){}
/**
* 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 */
destroy() {
if (!this.initialized) {
return;
}
// unsubscribe to events
this.emitter.off(EVENTS, bound(this.calcAll, this));
this.initialized = false;
}
}

View file

@ -1,273 +1,491 @@
import Dom from '../../dom';
import Types from '../../types';
import Event from '../../event';
import {Feature} from '../../feature';
import {
addClass, removeClass, createCheckItem, createElm, elm, removeElm,
getText, tag
} from '../../dom';
import {isUndef, EMPTY_FN, isNull} from '../../types';
import {addEvt, targetEvt, removeEvt} from '../../event';
import {root} from '../../root';
import {NONE} from '../../const';
import {
defaultsBool, defaultsStr, defaultsFn, defaultsNb, defaultsArr
} from '../../settings';
import {RIGHT} from '../../modules/toolbar';
export default class ColsVisibility{
/**
* Columns Visibility extension
*/
export default class ColsVisibility extends Feature {
/**
* Columns Visibility extension
* @param {Object} tf TableFilter instance
* @param {Object} f Config
* Creates an instance of ColsVisibility
* @param {TableFilter} tf TableFilter instance
* @param {Object} Configuration object
*/
constructor(tf, f){
constructor(tf, f) {
super(tf, ColsVisibility);
// Configuration object
var cfg = tf.config();
let cfg = this.config;
this.initialized = false;
/**
* Module name
* @type {String}
*/
this.name = f.name;
this.desc = f.description || 'Columns visibility manager';
//show/hide cols span element
/**
* Module description
* @type {String}
*/
this.desc = defaultsStr(f.description, 'Columns visibility manager');
/**
* show/hide columns container element
* @private
*/
this.spanEl = null;
//show/hide cols button element
/**
* show/hide columns button element
* @private
*/
this.btnEl = null;
//show/hide cols container div element
/**
* show/hide columns main container element
* @private
*/
this.contEl = null;
//tick to hide or show column
this.tickToHide = f.tick_to_hide===false ? false : true;
//enables/disables cols manager generation
this.manager = f.manager===false ? false : true;
//only if external headers
this.headersTbl = f.headers_table || false;
//only if external headers
this.headersIndex = f.headers_index || 1;
//id of container element
this.contElTgtId = f.container_target_id || null;
//alternative headers text
this.headersText = f.headers_text || null;
//id of button container element
this.btnTgtId = f.btn_target_id || null;
//defines show/hide cols text
this.btnText = f.btn_text || 'Columns&#9660;';
//defines show/hide cols button innerHtml
this.btnHtml = f.btn_html || null;
//defines css class for show/hide cols button
this.btnCssClass = f.btn_css_class || 'colVis';
//defines close link text
this.btnCloseText = f.btn_close_text || 'Close';
//defines close button innerHtml
this.btnCloseHtml = f.btn_close_html || null;
//defines css class for close button
this.btnCloseCssClass = f.btn_close_css_class || this.btnCssClass;
this.stylesheet = f.stylesheet || 'colsVisibility.css';
//span containing show/hide cols button
this.prfx = 'colVis_';
//defines css class span containing show/hide cols
this.spanCssClass = f.span_css_class || 'colVisSpan';
this.prfxCont = this.prfx + 'Cont_';
//defines css class div containing show/hide cols
this.contCssClass = f.cont_css_class || 'colVisCont';
//defines css class for cols list (ul)
this.listCssClass = cfg.list_css_class ||'cols_checklist';
//defines css class for list item (li)
this.listItemCssClass = cfg.checklist_item_css_class ||
'cols_checklist_item';
//defines css class for selected list item (li)
this.listSlcItemCssClass = cfg.checklist_selected_item_css_class ||
'cols_checklist_slc_item';
//text preceding columns list
this.text = f.text || (this.tickToHide ? 'Hide: ' : 'Show: ');
this.atStart = f.at_start || null;
/**
* Enable tick to hide a column, defaults to true
* @type {Boolean}
*/
this.tickToHide = defaultsBool(f.tick_to_hide, true);
/**
* Enable columns manager UI, defaults to true
* @type {Boolean}
*/
this.manager = defaultsBool(f.manager, true);
/**
* Headers HTML table reference only if headers are external
* @type {DOMElement}
*/
this.headersTbl = f.headers_table || null;
/**
* Headers row index only if headers are external
* @type {Number}
*/
this.headersIndex = defaultsNb(f.headers_index, 1);
/**
* ID of main container element
* @type {String}
*/
this.contElTgtId = defaultsStr(f.container_target_id, null);
/**
* Alternative text for column headers in column manager UI
* @type {Array}
*/
this.headersText = defaultsArr(f.headers_text, []);
/**
* ID of button's container element
* @type {String}
*/
this.btnTgtId = defaultsStr(f.btn_target_id, null);
/**
* Button's text, defaults to Columns&#9660;
* @type {String}
*/
this.btnText = defaultsStr(f.btn_text, 'Columns&#9660;');
/**
* Button's inner HTML
* @type {String}
*/
this.btnHtml = defaultsStr(f.btn_html, null);
/**
* Css class for button
* @type {String}
*/
this.btnCssClass = defaultsStr(f.btn_css_class, 'colVis');
/**
* Columns manager UI close link text, defaults to 'Close'
* @type {String}
*/
this.btnCloseText = defaultsStr(f.btn_close_text, 'Close');
/**
* Columns manager UI close link HTML
* @type {String}
*/
this.btnCloseHtml = defaultsStr(f.btn_close_html, null);
/**
* Css for columns manager UI close link
* @type {String}
*/
this.btnCloseCssClass = defaultsStr(f.btn_close_css_class,
this.btnCssClass);
/**
* Extension's stylesheet filename
* @type {String}
*/
this.stylesheet = defaultsStr(f.stylesheet, 'colsVisibility.css');
/**
* Css for columns manager UI span
* @type {String}
*/
this.spanCssClass = defaultsStr(f.span_css_class, 'colVisSpan');
/**
* Css for columns manager UI main container
* @type {String}
*/
this.contCssClass = defaultsStr(f.cont_css_class, 'colVisCont');
/**
* Css for columns manager UI checklist (ul)
* @type {String}
*/
this.listCssClass = defaultsStr(cfg.list_css_class, 'cols_checklist');
/**
* Css for columns manager UI checklist item (li)
* @type {String}
*/
this.listItemCssClass = defaultsStr(cfg.checklist_item_css_class,
'cols_checklist_item');
/**
* Css for columns manager UI checklist item selected state (li)
* @type {String}
*/
this.listSlcItemCssClass = defaultsStr(
cfg.checklist_selected_item_css_class,
'cols_checklist_slc_item'
);
/**
* Text preceding the columns list, defaults to 'Hide' or 'Show'
* depending on tick mode (tick_to_hide option)
* @type {String}
*/
this.text = defaultsStr(f.text, this.tickToHide ? 'Hide: ' : 'Show: ');
/**
* List of columns indexes to be hidden at initialization
* @type {Array}
*/
this.atStart = defaultsArr(f.at_start, []);
/**
* Enable hover behaviour on columns manager button/link
* @type {Boolean}
*/
this.enableHover = Boolean(f.enable_hover);
//enables select all option
/**
* Enable select all option, disabled by default
* @type {Boolean}
*/
this.enableTickAll = Boolean(f.enable_tick_all);
//text preceding columns list
this.tickAllText = f.tick_all_text || 'Select all:';
//array containing hidden columns indexes
/**
* Text for select all option, defaults to 'Select all:'
* @type {String}
*/
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
* @private
*/
this.hiddenCols = [];
this.tblHasColTag = (Dom.tag(tf.tbl,'col').length > 0);
//callback invoked just after cols manager is loaded
this.onLoaded = Types.isFn(f.on_loaded) ? f.on_loaded : null;
//calls function before cols manager is opened
this.onBeforeOpen = Types.isFn(f.on_before_open) ?
f.on_before_open : null;
//calls function after cols manager is opened
this.onAfterOpen = Types.isFn(f.on_after_open) ? f.on_after_open : null;
//calls function before cols manager is closed
this.onBeforeClose = Types.isFn(f.on_before_close) ?
f.on_before_close : null;
//calls function after cols manager is closed
this.onAfterClose = Types.isFn(f.on_after_close) ?
f.on_after_close : null;
/**
* Bound mouseup wrapper
* @private
*/
this.boundMouseup = null;
//callback before col is hidden
this.onBeforeColHidden = Types.isFn(f.on_before_col_hidden) ?
f.on_before_col_hidden : null;
//callback after col is hidden
this.onAfterColHidden = Types.isFn(f.on_after_col_hidden) ?
f.on_after_col_hidden : null;
//callback before col is displayed
this.onBeforeColDisplayed = Types.isFn(f.on_before_col_displayed) ?
f.on_before_col_displayed : null;
//callback after col is displayed
this.onAfterColDisplayed = Types.isFn(f.on_after_col_displayed) ?
f.on_after_col_displayed : null;
/**
* Callback fired when the extension is initialized
* @type {Function}
*/
this.onLoaded = defaultsFn(f.on_loaded, EMPTY_FN);
//Grid layout compatibility
if(tf.gridLayout){
/**
* Callback fired before the columns manager is opened
* @type {Function}
*/
this.onBeforeOpen = defaultsFn(f.on_before_open, EMPTY_FN);
/**
* Callback fired after the columns manager is opened
* @type {Function}
*/
this.onAfterOpen = defaultsFn(f.on_after_open, EMPTY_FN);
/**
* Callback fired before the columns manager is closed
* @type {Function}
*/
this.onBeforeClose = defaultsFn(f.on_before_close, EMPTY_FN);
/**
* Callback fired after the columns manager is closed
* @type {Function}
*/
this.onAfterClose = defaultsFn(f.on_after_close, EMPTY_FN);
/**
* Callback fired before a column is hidden
* @type {Function}
*/
this.onBeforeColHidden = defaultsFn(f.on_before_col_hidden, EMPTY_FN);
/**
* Callback fired after a column is hidden
* @type {Function}
*/
this.onAfterColHidden = defaultsFn(f.on_after_col_hidden, EMPTY_FN);
/**
* Callback fired before a column is displayed
* @type {Function}
*/
this.onBeforeColDisplayed = defaultsFn(f.on_before_col_displayed,
EMPTY_FN);
/**
* Callback fired after a column is displayed
* @type {Function}
*/
this.onAfterColDisplayed = defaultsFn(f.on_after_col_displayed,
EMPTY_FN);
//Grid layout support
if (tf.gridLayout) {
this.headersTbl = tf.feature('gridLayout').headTbl; //headers table
this.headersIndex = 0; //headers index
this.onAfterColDisplayed = function(){};
this.onAfterColHidden = function(){};
}
//Loads extension stylesheet
tf.import(f.name+'Style', tf.stylePath + this.stylesheet, null, 'link');
tf.import(f.name + 'Style', tf.getStylePath() + this.stylesheet, null,
'link');
this.tf = tf;
this.enable();
}
toggle(){
var contDisplay = this.contEl.style.display;
var onBeforeOpen = this.onBeforeOpen;
var onBeforeClose = this.onBeforeClose;
var onAfterOpen = this.onAfterOpen;
var onAfterClose = this.onAfterClose;
/**
* Mouse-up event handler handling popup auto-close behaviour
* @private
*/
onMouseup(evt) {
let targetElm = targetEvt(evt);
if(onBeforeOpen && contDisplay !== 'inline'){
onBeforeOpen.call(null, this);
while (targetElm && targetElm !== this.contEl
&& targetElm !== this.btnEl) {
targetElm = targetElm.parentNode;
}
if(onBeforeClose && contDisplay === 'inline'){
onBeforeClose.call(null, this);
if (targetElm !== this.contEl && targetElm !== this.btnEl) {
this.toggle();
}
return;
}
/**
* Toggle columns manager UI
*/
toggle() {
// ensure mouseup event handler is removed
removeEvt(root, 'mouseup', this.boundMouseup);
let contDisplay = this.contEl.style.display;
if (contDisplay !== 'inline') {
this.onBeforeOpen(this);
}
if (contDisplay === 'inline') {
this.onBeforeClose(this);
}
this.contEl.style.display = contDisplay === 'inline' ?
'none' : 'inline';
NONE : 'inline';
if(onAfterOpen && contDisplay !== 'inline'){
onAfterOpen.call(null, this);
if (contDisplay !== 'inline') {
this.onAfterOpen(this);
addEvt(root, 'mouseup', this.boundMouseup);
}
if(onAfterClose && contDisplay === 'inline'){
onAfterClose.call(null, this);
if (contDisplay === 'inline') {
this.onAfterClose(this);
}
}
checkItem(lbl){
var li = lbl.parentNode;
if(!li || !lbl){
/**
* Check an item in columns manager UI
* @private
*/
checkItem(lbl) {
let li = lbl.parentNode;
if (!li || !lbl) {
return;
}
var isChecked = lbl.firstChild.checked;
var colIndex = lbl.firstChild.getAttribute('id').split('_')[1];
let isChecked = lbl.firstChild.checked;
let colIndex = lbl.firstChild.getAttribute('id').split('_')[1];
colIndex = parseInt(colIndex, 10);
if(isChecked){
Dom.addClass(li, this.listSlcItemCssClass);
if (isChecked) {
addClass(li, this.listSlcItemCssClass);
} else {
Dom.removeClass(li, this.listSlcItemCssClass);
removeClass(li, this.listSlcItemCssClass);
}
var hide = false;
if((this.tickToHide && isChecked) || (!this.tickToHide && !isChecked)){
let hide = false;
if ((this.tickToHide && isChecked) ||
(!this.tickToHide && !isChecked)) {
hide = true;
}
this.setHidden(colIndex, hide);
}
init(){
if(!this.manager){
/**
* Initializes ColsVisibility instance
*/
init() {
if (this.initialized || !this.manager) {
return;
}
this.emitter.emit('initializing-extension', this,
!isNull(this.btnTgtId));
this.emitter.on(['hide-column'],
(tf, colIndex) => this.hideCol(colIndex));
this.buildBtn();
this.buildManager();
/** @inherited */
this.initialized = true;
this.boundMouseup = this.onMouseup.bind(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
// as order is important
this._hideAtStart();
}
/**
* Build main button UI
*/
buildBtn(){
if(this.btnEl){
buildBtn() {
if (this.btnEl) {
return;
}
var tf = this.tf;
var span = Dom.create('span', ['id', this.prfx+tf.id]);
let tf = this.tf;
let span = createElm('span');
span.className = this.spanCssClass;
//Container element (rdiv or custom element)
if(!this.btnTgtId){
tf.setToolbar();
}
var targetEl = !this.btnTgtId ? tf.rDiv : Dom.id(this.btnTgtId);
// Container element (rdiv or custom element)
let targetEl = !this.btnTgtId ?
tf.feature('toolbar').container(this.toolbarPosition) :
elm(this.btnTgtId);
if(!this.btnTgtId){
var firstChild = targetEl.firstChild;
if (!this.btnTgtId) {
let firstChild = targetEl.firstChild;
firstChild.parentNode.insertBefore(span, firstChild);
} else {
targetEl.appendChild(span);
}
if(!this.btnHtml){
var btn = Dom.create('a', ['href','javascript:;']);
if (!this.btnHtml) {
let btn = createElm('a', ['href', 'javascript:;']);
btn.className = this.btnCssClass;
btn.title = this.desc;
btn.innerHTML = this.btnText;
span.appendChild(btn);
if(!this.enableHover){
Event.add(btn, 'click', (evt)=> { this.toggle(evt); });
if (!this.enableHover) {
addEvt(btn, 'click', (evt) => this.toggle(evt));
} else {
Event.add(btn, 'mouseover', (evt)=> { this.toggle(evt); });
addEvt(btn, 'mouseover', (evt) => this.toggle(evt));
}
} else { //Custom html
} else { // Custom html
span.innerHTML = this.btnHtml;
var colVisEl = span.firstChild;
if(!this.enableHover){
Event.add(colVisEl, 'click', (evt)=> { this.toggle(evt); });
let colVisEl = span.firstChild;
if (!this.enableHover) {
addEvt(colVisEl, 'click', (evt) => this.toggle(evt));
} else {
Event.add(colVisEl, 'mouseover', (evt)=> { this.toggle(evt); });
addEvt(colVisEl, 'mouseover', (evt) => this.toggle(evt));
}
}
this.spanEl = span;
this.btnEl = this.spanEl.firstChild;
if(this.onLoaded){
this.onLoaded.call(null, this);
}
this.onLoaded(this);
}
/**
* Build columns manager UI
*/
buildManager(){
var tf = this.tf;
buildManager() {
let tf = this.tf;
var container = !this.contElTgtId ?
Dom.create('div', ['id', this.prfxCont+tf.id]) :
Dom.id(this.contElTgtId);
let container = !this.contElTgtId ?
createElm('div') :
elm(this.contElTgtId);
container.className = this.contCssClass;
//Extension description
var extNameLabel = Dom.create('p');
let extNameLabel = createElm('p');
extNameLabel.innerHTML = this.text;
container.appendChild(extNameLabel);
//Headers list
var ul = Dom.create('ul' ,['id', 'ul'+this.name+'_'+tf.id]);
let ul = createElm('ul');
ul.className = this.listCssClass;
var tbl = this.headersTbl ? this.headersTbl : tf.tbl;
var headerIndex = this.headersTbl ?
let tbl = this.headersTbl || tf.dom();
let headerIndex = this.headersTbl ?
this.headersIndex : tf.getHeadersRowIndex();
var headerRow = tbl.rows[headerIndex];
let headerRow = tbl.rows[headerIndex];
//Tick all option
if(this.enableTickAll){
var li = Dom.createCheckItem(
'col__'+tf.id, this.tickAllText, this.tickAllText);
Dom.addClass(li, this.listItemCssClass);
if (this.enableTickAll) {
let li = createCheckItem('col__' + tf.id, this.tickAllText,
this.tickAllText);
addClass(li, this.listItemCssClass);
ul.appendChild(li);
li.check.checked = !this.tickToHide;
Event.add(li.check, 'click', ()=> {
for(var h = 0; h < headerRow.cells.length; h++){
var itm = Dom.id('col_'+h+'_'+tf.id);
if(itm && li.check.checked !== itm.checked){
addEvt(li.check, 'click', () => {
for (let h = 0; h < headerRow.cells.length; h++) {
let itm = elm('col_' + h + '_' + tf.id);
if (itm && li.check.checked !== itm.checked) {
itm.click();
itm.checked = li.check.checked;
}
@ -275,42 +493,41 @@ export default class ColsVisibility{
});
}
for(var i = 0; i < headerRow.cells.length; i++){
var cell = headerRow.cells[i];
var cellText = this.headersText && this.headersText[i] ?
this.headersText[i] : this._getHeaderText(cell);
var liElm = Dom.createCheckItem(
'col_'+i+'_'+tf.id, cellText, cellText);
Dom.addClass(liElm, this.listItemCssClass);
if(!this.tickToHide){
Dom.addClass(liElm, this.listSlcItemCssClass);
for (let i = 0; i < headerRow.cells.length; i++) {
let cell = headerRow.cells[i];
let cellText = this.headersText[i] || this._getHeaderText(cell);
let liElm = createCheckItem('col_' + i + '_' + tf.id, cellText,
cellText);
addClass(liElm, this.listItemCssClass);
if (!this.tickToHide) {
addClass(liElm, this.listSlcItemCssClass);
}
ul.appendChild(liElm);
if(!this.tickToHide){
if (!this.tickToHide) {
liElm.check.checked = true;
}
Event.add(liElm.check, 'click', (evt)=> {
var elm = Event.target(evt);
var lbl = elm.parentNode;
addEvt(liElm.check, 'click', (evt) => {
let elm = targetEvt(evt);
let lbl = elm.parentNode;
this.checkItem(lbl);
});
}
//separator
var p = Dom.create('p', ['align','center']);
var btn;
let p = createElm('p', ['align', 'center']);
let btn;
//Close link
if(!this.btnCloseHtml){
btn = Dom.create('a', ['href','javascript:;']);
if (!this.btnCloseHtml) {
btn = createElm('a', ['href', 'javascript:;']);
btn.className = this.btnCloseCssClass;
btn.innerHTML = this.btnCloseText;
Event.add(btn, 'click', (evt)=> { this.toggle(evt); });
addEvt(btn, 'click', (evt) => this.toggle(evt));
p.appendChild(btn);
} else {
p.innerHTML = this.btnCloseHtml;
btn = p.firstChild;
Event.add(btn, 'click', (evt)=> { this.toggle(evt); });
addEvt(btn, 'click', (evt) => this.toggle(evt));
}
container.appendChild(ul);
@ -318,88 +535,48 @@ export default class ColsVisibility{
this.btnEl.parentNode.insertBefore(container, this.btnEl);
this.contEl = container;
if(this.atStart){
var a = this.atStart;
for(var k=0; k<a.length; k++){
var itm = Dom.id('col_'+a[k]+'_'+tf.id);
if(itm){
itm.click();
}
}
}
}
/**
* Hide or show specified columns
* @param {Numner} colIndex Column index
* @param {Boolean} hide hide column if true or show if false
* @param {Number} colIndex Column index
* @param {Boolean} hide Hide column if true or show if false
*/
setHidden(colIndex, hide){
var tf = this.tf;
var tbl = tf.tbl;
setHidden(colIndex, hide) {
let tf = this.tf;
let tbl = tf.dom();
if(this.onBeforeColHidden && hide){
this.onBeforeColHidden.call(null, this, colIndex);
}
if(this.onBeforeColDisplayed && !hide){
this.onBeforeColDisplayed.call(null, this, colIndex);
if (hide) {
this.onBeforeColHidden(this, colIndex);
} else {
this.onBeforeColDisplayed(this, colIndex);
}
this._hideCells(tbl, colIndex, hide);
if(this.headersTbl){
this._hideCells(this.headersTbl, colIndex, hide);
this._hideElements(tbl, colIndex, hide);
if (this.headersTbl) {
this._hideElements(this.headersTbl, colIndex, hide);
}
var hiddenCols = this.hiddenCols;
var itemIndex = hiddenCols.indexOf(colIndex);
if(hide){
if(itemIndex === -1){
let hiddenCols = this.hiddenCols;
let itemIndex = hiddenCols.indexOf(colIndex);
if (hide) {
if (itemIndex === -1) {
this.hiddenCols.push(colIndex);
}
} else {
if(itemIndex !== -1){
if (itemIndex !== -1) {
this.hiddenCols.splice(itemIndex, 1);
}
}
var gridLayout;
var headTbl;
var gridColElms;
if(this.onAfterColHidden && 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.gridColElms;
var hiddenWidth = parseInt(
gridColElms[colIndex].style.width, 10);
var headTblW = parseInt(headTbl.style.width, 10);
headTbl.style.width = headTblW - hiddenWidth + 'px';
tbl.style.width = headTbl.style.width;
}
this.onAfterColHidden.call(null, this, colIndex);
}
if(this.onAfterColDisplayed && !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.gridColElms;
var 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.call(null, this, colIndex);
if (hide) {
this.onAfterColHidden(this, colIndex);
this.emitter.emit('column-hidden', tf, this, colIndex,
this.hiddenCols);
} else {
this.onAfterColDisplayed(this, colIndex);
this.emitter.emit('column-shown', tf, this, colIndex,
this.hiddenCols);
}
}
@ -407,13 +584,15 @@ export default class ColsVisibility{
* Show specified column
* @param {Number} colIndex Column index
*/
showCol(colIndex){
if(colIndex === undefined || !this.isColHidden(colIndex)){
showCol(colIndex) {
if (isUndef(colIndex) || !this.isColHidden(colIndex)) {
return;
}
if(this.manager && this.contEl){
var itm = Dom.id('col_'+colIndex+'_'+this.tf.id);
if(itm){ itm.click(); }
if (this.manager && this.contEl) {
let itm = elm('col_' + colIndex + '_' + this.tf.id);
if (itm) {
itm.click();
}
} else {
this.setHidden(colIndex, false);
}
@ -423,13 +602,15 @@ export default class ColsVisibility{
* Hide specified column
* @param {Number} colIndex Column index
*/
hideCol(colIndex){
if(colIndex === undefined || this.isColHidden(colIndex)){
hideCol(colIndex) {
if (isUndef(colIndex) || this.isColHidden(colIndex)) {
return;
}
if(this.manager && this.contEl){
var itm = Dom.id('col_'+colIndex+'_'+this.tf.id);
if(itm){ itm.click(); }
if (this.manager && this.contEl) {
let itm = elm('col_' + colIndex + '_' + this.tf.id);
if (itm) {
itm.click();
}
} else {
this.setHidden(colIndex, true);
}
@ -439,8 +620,8 @@ export default class ColsVisibility{
* Determine if specified column is hidden
* @param {Number} colIndex Column index
*/
isColHidden(colIndex){
if(this.hiddenCols.indexOf(colIndex) !== -1){
isColHidden(colIndex) {
if (this.hiddenCols.indexOf(colIndex) !== -1) {
return true;
}
return false;
@ -450,8 +631,8 @@ export default class ColsVisibility{
* Toggle visibility of specified column
* @param {Number} colIndex Column index
*/
toggleCol(colIndex){
if(colIndex === undefined || this.isColHidden(colIndex)){
toggleCol(colIndex) {
if (isUndef(colIndex) || this.isColHidden(colIndex)) {
this.showCol(colIndex);
} else {
this.hideCol(colIndex);
@ -459,47 +640,53 @@ export default class ColsVisibility{
}
/**
* Returns the indexes of the columns currently hidden
* Return the indexes of the columns currently hidden
* @return {Array} column indexes
*/
getHiddenCols(){
getHiddenCols() {
return this.hiddenCols;
}
/**
* Remove the columns manager
*/
destroy(){
if(!this.btnEl && !this.contEl){
destroy() {
if (!this.initialized) {
return;
}
if(Dom.id(this.contElTgtId)){
Dom.id(this.contElTgtId).innerHTML = '';
if (elm(this.contElTgtId)) {
elm(this.contElTgtId).innerHTML = '';
} else {
this.contEl.innerHTML = '';
Dom.remove(this.contEl);
removeElm(this.contEl);
this.contEl = null;
}
this.btnEl.innerHTML = '';
Dom.remove(this.btnEl);
removeElm(this.btnEl);
this.btnEl = null;
this.emitter.off(['hide-column'],
(tf, colIndex) => this.hideCol(colIndex));
this.boundMouseup = null;
this.initialized = false;
}
_getHeaderText(cell){
if(!cell.hasChildNodes){
_getHeaderText(cell) {
if (!cell.hasChildNodes) {
return '';
}
for(var i=0; i<cell.childNodes.length; i++){
var n = cell.childNodes[i];
if(n.nodeType === 3){
for (let i = 0; i < cell.childNodes.length; i++) {
let n = cell.childNodes[i];
if (n.nodeType === 3) {
return n.nodeValue;
} else if(n.nodeType === 1){
if(n.id && n.id.indexOf('popUp') !== -1){
} else if (n.nodeType === 1) {
if (n.id && n.id.indexOf('popUp') !== -1) {
continue;
} else {
return Dom.getText(n);
return getText(n);
}
}
continue;
@ -507,14 +694,32 @@ export default class ColsVisibility{
return '';
}
_hideCells(tbl, colIndex, hide){
for(var i=0; i<tbl.rows.length; i++){
var row = tbl.rows[i];
var cell = row.cells[colIndex];
if(cell){
cell.style.display = hide ? 'none' : '';
_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++) {
let row = tbl.rows[i];
let cell = row.cells[colIdx];
if (cell) {
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() {
this.atStart.forEach((colIdx) => {
this.hideCol(colIdx);
});
}
}

View file

@ -1,110 +1,225 @@
import Dom from '../../dom';
import Types from '../../types';
import Event from '../../event';
import {Feature} from '../../feature';
import {createElm, removeElm, elm} from '../../dom';
import {EMPTY_FN, isNull} from '../../types';
import {addEvt} from '../../event';
import {
defaultsBool, defaultsStr, defaultsFn, defaultsNb,
} from '../../settings';
import {RIGHT} from '../../modules/toolbar';
export default class FiltersVisibility{
/**
* Filters Visibility extension
*/
export default class FiltersVisibility extends Feature {
/**
* Filters Row Visibility extension
* @param {Object} tf TableFilter instance
* @param {Object} f Config
* Creates an instance of FiltersVisibility
* @param {TableFilter} tf TableFilter instance
* @param {Object} Configuration object
*/
constructor(tf, f){
constructor(tf, f) {
super(tf, FiltersVisibility);
this.initialized = false;
/**
* Module name
* @type {String}
*/
this.name = f.name;
this.desc = f.description || 'Filters row visibility manager';
// Path and image filenames
this.stylesheet = f.stylesheet || 'filtersVisibility.css';
this.icnExpand = f.expand_icon_name || 'icn_exp.png';
this.icnCollapse = f.collapse_icon_name || 'icn_clp.png';
/**
* Module description
* @type {String}
*/
this.desc = defaultsStr(f.description,
'Filters row visibility manager');
//expand/collapse filters span element
/**
* Extension's stylesheet filename
* @type {String}
*/
this.stylesheet = defaultsStr(f.stylesheet , 'filtersVisibility.css');
/**
* Expand icon filename
* @type {String}
*/
this.icnExpand = defaultsStr(f.expand_icon_name, 'icn_exp.png');
/**
* Collapse icon filename
* @type {String}
*/
this.icnCollapse = defaultsStr(f.collapse_icon_name, 'icn_clp.png');
/**
* Main container element
* @private
*/
this.contEl = null;
//expand/collapse filters btn element
/**
* Button element
* @private
*/
this.btnEl = null;
this.icnExpandHtml = '<img src="'+ tf.themesPath + this.icnExpand +
/**
* Expand icon HTML
* @private
*/
this.icnExpandHtml = '<img src="' + tf.themesPath + this.icnExpand +
'" alt="Expand filters" >';
this.icnCollapseHtml = '<img src="'+ tf.themesPath + this.icnCollapse +
/**
* Collapse icon HTML
* @private
*/
this.icnCollapseHtml = '<img src="' + tf.themesPath + this.icnCollapse +
'" alt="Collapse filters" >';
/**
* Default text
* @private
*/
this.defaultText = 'Toggle filters';
//id of container element
this.targetId = f.target_id || null;
//enables/disables expand/collapse icon
this.enableIcon = f.enable_icon===false ? false : true;
this.btnText = f.btn_text || '';
/**
* ID of main container element
* @type {String}
*/
this.targetId = f.target_id || null;
//defines expand/collapse filters text
/**
* Enable expand/collapse icon, defaults to true
* @type {Boolean}
*/
this.enableIcon = defaultsBool(f.enable_icon, true);
/**
* Custom text for button
* @type {String}
*/
this.btnText = defaultsStr(f.btn_text, '');
/**
* Collapse button HTML
* @private
*/
this.collapseBtnHtml = this.enableIcon ?
this.icnCollapseHtml + this.btnText :
this.btnText || this.defaultText;
this.expandBtnHtml = this.enableIcon ?
/**
* Expand button HTML
* @private
*/
this.expandBtnHtml = this.enableIcon ?
this.icnExpandHtml + this.btnText :
this.btnText || this.defaultText;
//defines expand/collapse filters button innerHtml
this.btnHtml = f.btn_html || null;
//defines css class for expand/collapse filters button
this.btnCssClass = f.btn_css_class || 'btnExpClpFlt';
//defines css class span containing expand/collapse filters
this.contCssClass = f.cont_css_class || 'expClpFlt';
this.filtersRowIndex = !Types.isUndef(f.filters_row_index) ?
f.filters_row_index : tf.getFiltersRowIndex();
/**
* Button's custom HTML
* @type {String}
*/
this.btnHtml = defaultsStr(f.btn_html, null);
this.visibleAtStart = !Types.isUndef(f.visible_at_start) ?
Boolean(f.visible_at_start) : true;
/**
* Css class for expand/collapse filters button
* @type {String}
*/
this.btnCssClass = defaultsStr(f.btn_css_class, 'btnExpClpFlt');
// Prefix
this.prfx = 'fltsVis_';
/**
* Css class for main container
* @type {String}
*/
this.contCssClass = defaultsStr(f.cont_css_class, 'expClpFlt');
//callback before filters row is shown
this.onBeforeShow = Types.isFn(f.on_before_show) ?
f.on_before_show : null;
//callback after filters row is shown
this.onAfterShow = Types.isFn(f.on_after_show) ?
f.on_after_show : null;
//callback before filters row is hidden
this.onBeforeHide = Types.isFn(f.on_before_hide) ?
f.on_before_hide : null;
//callback after filters row is hidden
this.onAfterHide = Types.isFn(f.on_after_hide) ? f.on_after_hide : null;
/**
* Filters row index
* @type {Number}
*/
this.filtersRowIndex = defaultsNb(f.filters_row_index,
tf.getFiltersRowIndex());
//Loads extension stylesheet
tf.import(f.name+'Style', tf.stylePath + this.stylesheet, null, 'link');
/**
* Make filters visible at initialization, defaults to true
* @type {Boolean}
*/
this.visibleAtStart = defaultsNb(f.visible_at_start, true);
this.tf = tf;
/**
* Default position in toolbar ('left'|'center'|'right')
* @type {String}
*/
this.toolbarPosition = defaultsStr(f.toolbar_position, RIGHT);
/**
* Callback fired before filters row is shown
* @type {Function}
*/
this.onBeforeShow = defaultsFn(f.on_before_show, EMPTY_FN);
/**
* Callback fired after filters row is shown
* @type {Function}
*/
this.onAfterShow = defaultsFn(f.on_after_show, EMPTY_FN);
/**
* Callback fired before filters row is hidden
* @type {Function}
*/
this.onBeforeHide = defaultsFn(f.on_before_hide, EMPTY_FN);
/**
* Callback fired after filters row is hidden
* @type {Function}
*/
this.onAfterHide = defaultsFn(f.on_after_hide, EMPTY_FN);
//Import extension's stylesheet
tf.import(f.name + 'Style', tf.getStylePath() + this.stylesheet, null,
'link');
this.enable();
}
/**
* Initialise extension
*/
init(){
if(this.initialized){
init() {
if (this.initialized) {
return;
}
this.emitter.emit('initializing-extension', this,
!isNull(this.targetId));
this.buildUI();
/** @inherited */
this.initialized = true;
this.emitter.on(['show-filters'], (tf, visible) => this.show(visible));
this.emitter.emit('filters-visibility-initialized', this.tf, this);
this.emitter.emit('extension-initialized', this);
}
/**
* Build UI elements
*/
buildUI(){
buildUI() {
let tf = this.tf;
let span = Dom.create('span',['id', this.prfx+tf.id]);
let span = createElm('span');
span.className = this.contCssClass;
//Container element (rdiv or custom element)
if(!this.targetId){
tf.setToolbar();
}
let targetEl = !this.targetId ? tf.rDiv : Dom.id(this.targetId);
// Container element (rdiv or custom element)
let targetEl = !this.targetId ?
tf.feature('toolbar').container(this.toolbarPosition) :
elm(this.targetId);
if(!this.targetId){
if (!this.targetId) {
let firstChild = targetEl.firstChild;
firstChild.parentNode.insertBefore(span, firstChild);
} else {
@ -112,23 +227,23 @@ export default class FiltersVisibility{
}
let btn;
if(!this.btnHtml){
btn = Dom.create('a', ['href', 'javascript:void(0);']);
if (!this.btnHtml) {
btn = createElm('a', ['href', 'javascript:void(0);']);
btn.className = this.btnCssClass;
btn.title = this.btnText || this.defaultText;
btn.innerHTML = this.collapseBtnHtml;
span.appendChild(btn);
} else { //Custom html
} else { // Custom html
span.innerHTML = this.btnHtml;
btn = span.firstChild;
}
Event.add(btn, 'click', ()=> this.toggle());
addEvt(btn, 'click', () => this.toggle());
this.contEl = span;
this.btnEl = btn;
if(!this.visibleAtStart){
if (!this.visibleAtStart) {
this.toggle();
}
}
@ -136,47 +251,64 @@ export default class FiltersVisibility{
/**
* Toggle filters visibility
*/
toggle(){
toggle() {
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 fltRowDisplay = fltRow.style.display;
let isDisplayed = fltRow.style.display === '';
if(this.onBeforeShow && fltRowDisplay !== ''){
this.onBeforeShow.call(this, this);
this.show(!isDisplayed);
}
/**
* Show or hide filters
*
* @param {boolean} [visible=true] Visibility flag
*/
show(visible = true) {
let tf = this.tf;
let tbl = tf.gridLayout ? tf.feature('gridLayout').headTbl : tf.dom();
let fltRow = tbl.rows[this.filtersRowIndex];
if (visible) {
this.onBeforeShow(this);
}
if(this.onBeforeHide && fltRowDisplay === ''){
this.onBeforeHide.call(null, this);
if (!visible) {
this.onBeforeHide(this);
}
fltRow.style.display = fltRowDisplay==='' ? 'none' : '';
if(this.enableIcon && !this.btnHtml){
this.btnEl.innerHTML = fltRowDisplay === '' ?
this.expandBtnHtml : this.collapseBtnHtml;
fltRow.style.display = visible ? '' : 'none';
if (this.enableIcon && !this.btnHtml) {
this.btnEl.innerHTML = visible ?
this.collapseBtnHtml : this.expandBtnHtml;
}
if(this.onAfterShow && fltRowDisplay !== ''){
this.onAfterShow.call(null, this);
if (visible) {
this.onAfterShow(this);
}
if(this.onAfterHide && fltRowDisplay === ''){
this.onAfterHide.call(null, this);
if (!visible) {
this.onAfterHide(this);
}
this.emitter.emit('filters-toggled', tf, this, visible);
}
/**
* Destroy the UI
*/
destroy(){
if(!this.btnEl && !this.contEl){
destroy() {
if (!this.initialized) {
return;
}
this.emitter.off(['show-filters'], (tf, visible) => this.show(visible));
this.btnEl.innerHTML = '';
Dom.remove(this.btnEl);
removeElm(this.btnEl);
this.btnEl = null;
this.contEl.innerHTML = '';
Dom.remove(this.contEl);
removeElm(this.contEl);
this.contEl = null;
this.initialized = false;
}

View file

@ -1,128 +1,176 @@
import Types from '../../types';
import Dom from '../../dom';
import Event from '../../event';
import DateHelper from '../../date';
import Helpers from '../../helpers';
import {Feature} from '../../feature';
import {isUndef, isObj, EMPTY_FN} from '../../types';
import {createElm, elm, tag} from '../../dom';
import {addEvt, bound} from '../../event';
import {parse as parseNb} from '../../number';
import {
NONE, CELL_TAG, HEADER_TAG, STRING, NUMBER, DATE, FORMATTED_NUMBER,
IP_ADDRESS
} from '../../const';
import {defaultsStr, defaultsFn, defaultsArr} from '../../settings';
export default class AdapterSortableTable{
/**
* SortableTable Adapter module
*/
export default class AdapterSortableTable extends Feature {
/**
* SortableTable Adapter module
* @param {Object} tf TableFilter instance
* Creates an instance of AdapterSortableTable
* @param {TableFilter} tf TableFilter instance
* @param {Object} opts Configuration object
*/
constructor(tf, opts){
this.initialized = false;
this.name = opts.name;
this.desc = opts.description || 'Sortable table';
constructor(tf, opts) {
super(tf, AdapterSortableTable);
//indicates if tables was sorted
/**
* Module name
* @type {String}
*/
this.name = opts.name;
/**
* Module description
* @type {String}
*/
this.desc = defaultsStr(opts.description, 'Sortable table');
/**
* Indicate whether table previously sorted
* @type {Boolean}
* @private
*/
this.sorted = false;
this.sortTypes = Types.isArray(opts.types) ? opts.types : [];
this.sortColAtStart = Types.isArray(opts.sort_col_at_start) ?
opts.sort_col_at_start : null;
/**
* List of sort type per column basis
* @type {Array}
*/
this.sortTypes = defaultsArr(opts.types, tf.colTypes);
/**
* Column to be sorted at initialization, ie:
* sort_col_at_start: [1, true]
* @type {Array}
*/
this.sortColAtStart = defaultsArr(opts.sort_col_at_start, null);
/**
* Enable asynchronous sort, if triggers are external
* @type {Boolean}
*/
this.asyncSort = Boolean(opts.async_sort);
this.triggerIds = Types.isArray(opts.trigger_ids) ?
opts.trigger_ids : [];
/**
* List of element IDs triggering sort on a per column basis
* @type {Array}
*/
this.triggerIds = defaultsArr(opts.trigger_ids, []);
// edit .sort-arrow.descending / .sort-arrow.ascending in
// tablefilter.css to reflect any path change
this.imgPath = opts.images_path || tf.themesPath;
this.imgBlank = opts.image_blank || 'blank.png';
this.imgClassName = opts.image_class_name || 'sort-arrow';
this.imgAscClassName = opts.image_asc_class_name || 'ascending';
this.imgDescClassName = opts.image_desc_class_name ||'descending';
//cell attribute storing custom key
this.customKey = opts.custom_key || 'data-tf-sortKey';
/**
* Path to images
* @type {String}
*/
this.imgPath = defaultsStr(opts.images_path, tf.themesPath);
// callback invoked after sort is loaded and instanciated
this.onSortLoaded = Types.isFn(opts.on_sort_loaded) ?
opts.on_sort_loaded : null;
// callback invoked before table is sorted
this.onBeforeSort = Types.isFn(opts.on_before_sort) ?
opts.on_before_sort : null;
// callback invoked after table is sorted
this.onAfterSort = Types.isFn(opts.on_after_sort) ?
opts.on_after_sort : null;
/**
* Blank image file name
* @type {String}
*/
this.imgBlank = defaultsStr(opts.image_blank, 'blank.png');
this.tf = tf;
/**
* Css class for sort indicator image
* @type {String}
*/
this.imgClassName = defaultsStr(opts.image_class_name, 'sort-arrow');
/**
* Css class for ascending sort indicator image
* @type {String}
*/
this.imgAscClassName = defaultsStr(opts.image_asc_class_name,
'ascending');
/**
* Css class for descending sort indicator image
* @type {String}
*/
this.imgDescClassName = defaultsStr(opts.image_desc_class_name,
'descending');
/**
* Cell attribute key storing custom value used for sorting
* @type {String}
*/
this.customKey = defaultsStr(opts.custom_key, 'data-tf-sortKey');
/**
* Callback fired when sort extension is instanciated
* @type {Function}
*/
this.onSortLoaded = defaultsFn(opts.on_sort_loaded, EMPTY_FN);
/**
* Callback fired before a table column is sorted
* @type {Function}
*/
this.onBeforeSort = defaultsFn(opts.on_before_sort, EMPTY_FN);
/**
* Callback fired after a table column is sorted
* @type {Function}
*/
this.onAfterSort = defaultsFn(opts.on_after_sort, EMPTY_FN);
/**
* SortableTable instance
* @private
*/
this.stt = null;
this.enable();
}
init(){
/**
* Initializes AdapterSortableTable instance
*/
init() {
if (this.initialized) {
return;
}
let tf = this.tf;
let adpt = this;
// SortableTable class sanity check (sortabletable.js)
if(Types.isUndef(SortableTable)){
if (isUndef(SortableTable)) {
throw new Error('SortableTable class not found.');
}
// Add any date format if needed
this.emitter.emit('add-date-type-formats', this.tf, this.sortTypes);
this.overrideSortableTable();
this.setSortTypes();
//Column sort at start
let sortColAtStart = adpt.sortColAtStart;
if(sortColAtStart){
this.stt.sort(sortColAtStart[0], sortColAtStart[1]);
}
if(this.onSortLoaded){
this.onSortLoaded.call(null, tf, this);
}
this.onSortLoaded(tf, this);
/*** SortableTable callbacks ***/
this.stt.onbeforesort = function(){
if(adpt.onBeforeSort){
adpt.onBeforeSort.call(null, tf, adpt.stt.sortColumn);
}
this.stt.onbeforesort = function () {
adpt.onBeforeSort(tf, adpt.stt.sortColumn);
/*** sort behaviour for paging ***/
if(tf.paging){
if (tf.paging) {
tf.feature('paging').disable();
}
};
this.stt.onsort = function(){
this.stt.onsort = function () {
adpt.sorted = true;
//rows alternating bg issue
// TODO: move into AlternateRows component
if(tf.alternateRows){
let rows = tf.tbl.rows, c = 0;
let setClass = function(row, i, removeOnly){
if(Types.isUndef(removeOnly)){
removeOnly = false;
}
let altRows = tf.feature('alternateRows'),
oddCls = altRows.oddCss,
evenCls = altRows.evenCss;
Dom.removeClass(row, oddCls);
Dom.removeClass(row, evenCls);
if(!removeOnly){
Dom.addClass(row, i % 2 ? oddCls : evenCls);
}
};
for (let i = tf.refRow; i < tf.nbRows; i++){
let isRowValid = rows[i].getAttribute('validRow');
if(tf.paging && rows[i].style.display === ''){
setClass(rows[i], c);
c++;
} else {
if((isRowValid==='true' || isRowValid===null) &&
rows[i].style.display === ''){
setClass(rows[i], c);
c++;
} else {
setClass(rows[i], c, true);
}
}
}
}
//sort behaviour for paging
if(tf.paging){
if (tf.paging) {
let paginator = tf.feature('paging');
// recalculate valid rows index as sorting may have change it
tf.getValidRows(true);
@ -130,12 +178,23 @@ export default class AdapterSortableTable{
paginator.setPage(paginator.getPage());
}
if(adpt.onAfterSort){
adpt.onAfterSort.call(null, tf, adpt.stt.sortColumn);
}
adpt.onAfterSort(tf, adpt.stt.sortColumn, adpt.stt.descending);
adpt.emitter.emit('column-sorted', tf, adpt.stt.sortColumn,
adpt.stt.descending);
};
// Column sort at start
let sortColAtStart = adpt.sortColAtStart;
if (sortColAtStart) {
this.stt.sort(sortColAtStart[0], sortColAtStart[1]);
}
this.emitter.on(['sort'], bound(this.sortByColumnIndexHandler, this));
/** @inherited */
this.initialized = true;
this.emitter.emit('sort-initialized', tf, this);
}
/**
@ -143,11 +202,19 @@ export default class AdapterSortableTable{
* @param {Number} colIdx Column index
* @param {Boolean} desc Optional: descending manner
*/
sortByColumnIndex(colIdx, desc){
sortByColumnIndex(colIdx, desc) {
this.stt.sort(colIdx, desc);
}
overrideSortableTable(){
/** @private */
sortByColumnIndexHandler(tf, colIdx, desc) {
this.sortByColumnIndex(colIdx, desc);
}
/**
* Set SortableTable overrides for TableFilter integration
*/
overrideSortableTable() {
let adpt = this,
tf = this.tf;
@ -155,15 +222,15 @@ export default class AdapterSortableTable{
* Overrides headerOnclick method in order to handle th event
* @param {Object} e [description]
*/
SortableTable.prototype.headerOnclick = function(evt){
if(!adpt.initialized){
SortableTable.prototype.headerOnclick = function (evt) {
if (!adpt.initialized) {
return;
}
// find Header element
let el = evt.target || evt.srcElement;
while(el.tagName !== 'TD' && el.tagName !== 'TH'){
while (el.tagName !== CELL_TAG && el.tagName !== HEADER_TAG) {
el = el.parentNode;
}
@ -179,10 +246,10 @@ export default class AdapterSortableTable{
* @param {Object} oTd TD element
* @return {Number} Cell index
*/
SortableTable.getCellIndex = function(oTd){
SortableTable.getCellIndex = function (oTd) {
let cells = oTd.parentNode.cells,
l = cells.length, i;
for (i = 0; cells[i] != oTd && i < l; i++){}
for (i = 0; cells[i] !== oTd && i < l; i++) { }
return i;
};
@ -190,10 +257,10 @@ export default class AdapterSortableTable{
* Overrides initHeader in order to handle filters row position
* @param {Array} oSortTypes
*/
SortableTable.prototype.initHeader = function(oSortTypes){
SortableTable.prototype.initHeader = function (oSortTypes) {
let stt = this;
if (!stt.tHead){
if(tf.gridLayout){
if (!stt.tHead) {
if (tf.gridLayout) {
stt.tHead = tf.feature('gridLayout').headTbl.tHead;
} else {
return;
@ -208,15 +275,15 @@ export default class AdapterSortableTable{
for (let i = 0; i < l; i++) {
c = cells[i];
if (stt.sortTypes[i] !== null && stt.sortTypes[i] !== 'None'){
if (stt.sortTypes[i] !== null && stt.sortTypes[i] !== 'None') {
c.style.cursor = 'pointer';
img = Dom.create('img',
img = createElm('img',
['src', adpt.imgPath + adpt.imgBlank]);
c.appendChild(img);
if (stt.sortTypes[i] !== null){
c.setAttribute( '_sortType', stt.sortTypes[i]);
if (stt.sortTypes[i] !== null) {
c.setAttribute('_sortType', stt.sortTypes[i]);
}
Event.add(c, 'click', stt._headerOnclick);
addEvt(c, 'click', stt._headerOnclick);
} else {
c.setAttribute('_sortType', oSortTypes[i]);
c._sortType = 'None';
@ -228,40 +295,44 @@ export default class AdapterSortableTable{
/**
* Overrides updateHeaderArrows in order to handle arrows indicators
*/
SortableTable.prototype.updateHeaderArrows = function(){
SortableTable.prototype.updateHeaderArrows = function () {
let stt = this;
let cells, l, img;
// external headers
if(adpt.asyncSort && adpt.triggerIds.length > 0){
if (adpt.asyncSort && adpt.triggerIds.length > 0) {
let triggers = adpt.triggerIds;
cells = [];
l = triggers.length;
for(let j=0; j<triggers.length; j++){
cells.push(Dom.id(triggers[j]));
for (let j = 0; j < l; j++) {
cells.push(elm(triggers[j]));
}
} else {
if(!this.tHead){
if (!this.tHead) {
return;
}
cells = stt.tHead.rows[stt.headersRow].cells;
l = cells.length;
}
for(let i = 0; i < l; i++){
let cellAttr = cells[i].getAttribute('_sortType');
if(cellAttr !== null && cellAttr !== 'None'){
img = cells[i].lastChild || cells[i];
if(img.nodeName.toLowerCase() !== 'img'){
img = Dom.create('img',
for (let i = 0; i < l; i++) {
let cell = cells[i];
if (!cell) {
continue;
}
let cellAttr = cell.getAttribute('_sortType');
if (cellAttr !== null && cellAttr !== 'None') {
img = cell.lastChild || cell;
if (img.nodeName.toLowerCase() !== 'img') {
img = createElm('img',
['src', adpt.imgPath + adpt.imgBlank]);
cells[i].appendChild(img);
cell.appendChild(img);
}
if (i === stt.sortColumn){
img.className = adpt.imgClassName +' '+
if (i === stt.sortColumn) {
img.className = adpt.imgClassName + ' ' +
(this.descending ?
adpt.imgDescClassName :
adpt.imgAscClassName);
} else{
} else {
img.className = adpt.imgClassName;
}
}
@ -275,11 +346,11 @@ export default class AdapterSortableTable{
* @param {Number} nColumn
* @return {String}
*/
SortableTable.prototype.getRowValue = function(oRow, sType, nColumn){
SortableTable.prototype.getRowValue = function (oRow, sType, nColumn) {
let stt = this;
// if we have defined a custom getRowValue use that
let sortTypeInfo = stt._sortTypeInfo[sType];
if (sortTypeInfo && sortTypeInfo.getRowValue){
if (sortTypeInfo && sortTypeInfo.getRowValue) {
return sortTypeInfo.getRowValue(oRow, nColumn);
}
let c = oRow.cells[nColumn];
@ -290,82 +361,94 @@ export default class AdapterSortableTable{
/**
* Overrides getInnerText in order to avoid Firefox unexpected sorting
* behaviour with untrimmed text elements
* @param {Object} oNode DOM element
* @param {Object} cell DOM element
* @return {String} DOM element inner text
*/
SortableTable.getInnerText = function(oNode){
if(!oNode){
SortableTable.getInnerText = function (cell) {
if (!cell) {
return;
}
if(oNode.getAttribute(adpt.customKey)){
return oNode.getAttribute(adpt.customKey);
if (cell.getAttribute(adpt.customKey)) {
return cell.getAttribute(adpt.customKey);
} else {
return Dom.getText(oNode);
return tf.getCellValue(cell);
}
};
}
addSortType(){
var args = arguments;
SortableTable.prototype.addSortType(args[0], args[1], args[2], args[3]);
/**
* Adds a sort type
*/
addSortType(...args) {
// Extract the arguments
let [id, caster, sorter, getRowValue] = args;
SortableTable.prototype.addSortType(id, caster, sorter, getRowValue);
}
setSortTypes(){
/**
* Sets the sort types on a column basis
* @private
*/
setSortTypes() {
let tf = this.tf,
sortTypes = this.sortTypes,
_sortTypes = [];
for(let i=0; i<tf.nbCells; i++){
tf.eachCol((i) => {
let colType;
if(sortTypes[i]){
colType = sortTypes[i].toLowerCase();
if(colType === 'none'){
colType = 'None';
}
} else { // resolve column types
if(tf.hasColNbFormat && tf.colNbFormat[i] !== null){
colType = tf.colNbFormat[i].toLowerCase();
} else if(tf.hasColDateType && tf.colDateType[i] !== null){
colType = tf.colDateType[i].toLowerCase()+'date';
if (sortTypes[i]) {
colType = sortTypes[i];
if (isObj(colType)) {
if (colType.type === DATE) {
colType = this._addDateType(i, sortTypes);
}
else if (colType.type === FORMATTED_NUMBER) {
let decimal = colType.decimal || tf.decimalSeparator;
colType = this._addNumberType(i, decimal);
}
} else {
colType = 'String';
colType = colType.toLowerCase();
if (colType === DATE) {
colType = this._addDateType(i, sortTypes);
}
else if (colType === FORMATTED_NUMBER ||
colType === NUMBER) {
colType = this._addNumberType(i, tf.decimalSeparator);
}
else if (colType === NONE) {
// TODO: normalise 'none' vs 'None'
colType = 'None';
}
}
} else {
colType = STRING;
}
_sortTypes.push(colType);
}
});
//Public TF method to add sort type
//Custom sort types
this.addSortType('number', Number);
this.addSortType('caseinsensitivestring', SortableTable.toUpperCase);
this.addSortType('date', SortableTable.toDate);
this.addSortType('string');
this.addSortType('us', usNumberConverter);
this.addSortType('eu', euNumberConverter);
this.addSortType('dmydate', dmyDateConverter );
this.addSortType('ymddate', ymdDateConverter);
this.addSortType('mdydate', mdyDateConverter);
this.addSortType('ddmmmyyyydate', ddmmmyyyyDateConverter);
this.addSortType('ipaddress', ipAddress, sortIP);
this.addSortType(STRING);
this.addSortType(IP_ADDRESS, ipAddress, sortIP);
this.stt = new SortableTable(tf.tbl, _sortTypes);
this.stt = new SortableTable(tf.dom(), _sortTypes);
/*** external table headers adapter ***/
if(this.asyncSort && this.triggerIds.length > 0){
if (this.asyncSort && this.triggerIds.length > 0) {
let triggers = this.triggerIds;
for(let j=0; j<triggers.length; j++){
if(triggers[j] === null){
for (let j = 0; j < triggers.length; j++) {
if (triggers[j] === null) {
continue;
}
let trigger = Dom.id(triggers[j]);
if(trigger){
let trigger = elm(triggers[j]);
if (trigger) {
trigger.style.cursor = 'pointer';
Event.add(trigger, 'click', (evt) => {
addEvt(trigger, 'click', (evt) => {
let elm = evt.target;
if(!this.tf.sort){
if (!this.tf.sort) {
return;
}
this.stt.asyncSort(triggers.indexOf(elm.id));
@ -376,69 +459,77 @@ export default class AdapterSortableTable{
}
}
/**
* Destroy sort
*/
destroy(){
_addDateType(colIndex, types) {
let tf = this.tf;
let dateType = tf.feature('dateType');
let locale = dateType.getOptions(colIndex, types).locale || tf.locale;
let colType = `${DATE}-${locale}`;
this.addSortType(colType, (value) => {
let parsedDate = dateType.parse(value, locale);
// Invalid date defaults to Wed Feb 04 -768 11:00:00
return isNaN(+parsedDate) ? new Date(-86400000000000) : parsedDate;
});
return colType;
}
_addNumberType(colIndex, decimal) {
let colType = `${FORMATTED_NUMBER}${decimal === '.' ? '' : '-custom'}`;
this.addSortType(colType, (value) => {
return parseNb(value, decimal);
});
return colType;
}
/**
* Remove extension
*/
destroy() {
if (!this.initialized) {
return;
}
let tf = this.tf;
this.emitter.off(['sort'], bound(this.sortByColumnIndexHandler, this));
this.sorted = false;
this.initialized = false;
this.stt.destroy();
let ids = tf.getFiltersId();
for (let idx = 0; idx < ids.length; idx++){
for (let idx = 0; idx < ids.length; idx++) {
let header = tf.getHeaderElement(idx);
let img = Dom.tag(header, 'img');
let img = tag(header, 'img');
if(img.length === 1){
if (img.length === 1) {
header.removeChild(img[0]);
}
}
this.initialized = false;
}
}
//Converters
function usNumberConverter(s){
return Helpers.removeNbFormat(s, 'us');
}
function euNumberConverter(s){
return Helpers.removeNbFormat(s, 'eu');
}
function dateConverter(s, format){
return DateHelper.format(s, format);
}
function dmyDateConverter(s){
return dateConverter(s, 'DMY');
}
function mdyDateConverter(s){
return dateConverter(s, 'MDY');
}
function ymdDateConverter(s){
return dateConverter(s, 'YMD');
}
function ddmmmyyyyDateConverter(s){
return dateConverter(s, 'DDMMMYYYY');
}
AdapterSortableTable.meta = {altName: 'sort'};
function ipAddress(value){
//Converters
function ipAddress(value) {
let vals = value.split('.');
// eslint-disable-next-line no-unused-vars
for (let x in vals) {
let val = vals[x];
while (3 > val.length){
val = '0'+val;
while (3 > val.length) {
val = '0' + val;
}
vals[x] = val;
}
return vals.join('.');
}
function sortIP(a,b){
function sortIP(a, b) {
let aa = ipAddress(a.value.toLowerCase());
let bb = ipAddress(b.value.toLowerCase());
if (aa==bb){
if (aa === bb) {
return 0;
} else if (aa<bb){
} else if (aa < bb) {
return -1;
} else {
return 1;

View file

@ -1,8 +1,8 @@
// import 'script!sortabletable';
import AdapterSortableTable from './adapterSortabletable';
import {root} from '../../root';
if(!window.SortableTable){
require('script!sortabletable');
if (!root.SortableTable) {
require('script-loader!sortabletable');
}
export default AdapterSortableTable;

102
src/feature.js Normal file
View file

@ -0,0 +1,102 @@
import {toCamelCase} from './string';
const NOT_IMPLEMENTED = 'Not implemented.';
/**
* Base class defining the interface of a TableFilter feature
*/
export class Feature {
/**
* Creates an instance of Feature
* @param {Object} tf TableFilter instance
* @param {Class} feature Feature class for TableFilter registration
*/
constructor(tf, cls) {
cls.meta = cls.meta || {};
/**
* TableFilter instance
* @type {TableFilter}
*/
this.tf = tf;
/**
* Feature name is the camelised class name as per TableFilter's
* convention
* @type {String}
*/
this.feature = cls.meta.altName || cls.meta.name
|| toCamelCase(cls.name);
/**
* TableFilter feature setting
* @type {Boolean}
*/
this.enabled = tf[this.feature];
/**
* TableFilter configuration
* @type {Object}
*/
this.config = tf.config();
/**
* TableFilter emitter instance
* @type {Emitter}
*/
this.emitter = tf.emitter;
/**
* Field indicating whether Feature is initialized
* @type {Boolean}
*/
this.initialized = false;
/** Subscribe to destroy event */
this.emitter.on(['destroy'], () => this.destroy());
}
/**
* Initialize the feature
*/
init() {
throw new Error(NOT_IMPLEMENTED);
}
/**
* Reset the feature after being disabled
*/
reset() {
this.enable();
this.init();
}
/**
* Destroy the feature
*/
destroy() {
throw new Error(NOT_IMPLEMENTED);
}
/**
* Enable the feature
*/
enable() {
this.enabled = true;
}
/**
* Disable the feature
*/
disable() {
this.enabled = false;
}
/**
* Indicate whether the feature is enabled or not
* @returns {Boolean}
*/
isEnabled() {
return this.enabled === true;
}
}

View file

@ -1,23 +0,0 @@
/**
* Misc helpers
*/
import Str from './string';
export default {
removeNbFormat(data, format){
if(!data){
return;
}
if(!format){
format = 'us';
}
let n = data;
if(Str.lower(format) === 'us'){
n =+ n.replace(/[^\d\.-]/g,'');
} else {
n =+ n.replace(/[^\d\,-]/g,'').replace(',','.');
}
return n;
}
};

View file

@ -1,48 +1,88 @@
import {Feature} from './feature';
import Dom from '../dom';
import {Feature} from '../feature';
import {addClass, removeClass} from '../dom';
import {defaultsStr} from '../settings';
import {bound} from '../event';
/**
* Rows with alternating background color for improved readability
*/
export class AlternateRows extends Feature {
/**
* Alternating rows color
* Creates an instance of AlternateRows.
*
* @param {Object} tf TableFilter instance
*/
constructor(tf) {
super(tf, 'alternateRows');
super(tf, AlternateRows);
var config = this.config;
//defines css class for even rows
this.evenCss = config.even_row_css_class || 'even';
//defines css class for odd rows
this.oddCss = config.odd_row_css_class || 'odd';
let config = this.config;
/**
* Css class for even rows (default: 'even')
* @type {String}
*/
this.evenCss = defaultsStr(config.even_row_css_class, 'even');
/**
* Css class for odd rows (default: 'odd')
* @type {String}
*/
this.oddCss = defaultsStr(config.odd_row_css_class, 'odd');
}
/**
* Sets alternating rows color
*/
init() {
if(this.initialized){
if (this.initialized) {
return;
}
var tf = this.tf;
var validRowsIndex = tf.validRowsIndex;
var noValidRowsIndex = validRowsIndex===null;
//1st index
var beginIndex = noValidRowsIndex ? tf.refRow : 0;
// nb indexes
var indexLen = noValidRowsIndex ?
tf.nbFilterableRows+beginIndex :
validRowsIndex.length;
var idx = 0;
this.processAll();
// Subscribe to events
this.emitter.on(['row-processed', 'row-paged'],
bound(this.processRowHandler, this));
this.emitter.on(['column-sorted', 'rows-changed'],
bound(this.processAll, this));
/** @inherited */
this.initialized = true;
}
/**
* Apply background to all valid rows
*/
processAll() {
if (!this.isEnabled()) {
return;
}
let tf = this.tf;
let validRowsIndex = tf.getValidRows(true);
let indexLen = validRowsIndex.length;
let idx = 0;
//alternates bg color
for(var j=beginIndex; j<indexLen; j++){
var rowIdx = noValidRowsIndex ? j : validRowsIndex[j];
for (let j = 0; j < indexLen; j++) {
let rowIdx = validRowsIndex[j];
this.setRowBg(rowIdx, idx);
idx++;
}
this.initialized = true;
}
/**
* Set/remove row background based on row validation
* @param {Number} rowIdx Row index
* @param {Number} arrIdx Array index
* @param {Boolean} isValid Valid row flag
*/
processRow(rowIdx, arrIdx, isValid) {
if (isValid) {
this.setRowBg(rowIdx, arrIdx);
} else {
this.removeRowBg(rowIdx);
}
}
/**
@ -50,44 +90,55 @@ export class AlternateRows extends Feature {
* @param {Number} rowIdx Row index
* @param {Number} idx Valid rows collection index needed to calculate bg
* color
* @private
*/
setRowBg(rowIdx, idx) {
if(!this.isEnabled() || isNaN(rowIdx)){
if (!this.isEnabled() || isNaN(rowIdx)) {
return;
}
var rows = this.tf.tbl.rows;
var i = isNaN(idx) ? rowIdx : idx;
let rows = this.tf.dom().rows;
let i = isNaN(idx) ? rowIdx : idx;
this.removeRowBg(rowIdx);
Dom.addClass(
rows[rowIdx],
(i%2) ? this.evenCss : this.oddCss
);
addClass(rows[rowIdx], (i % 2) ? this.evenCss : this.oddCss);
}
/**
* Removes row background color
* @param {Number} idx Row index
* @private
*/
removeRowBg(idx) {
if(isNaN(idx)){
if (isNaN(idx)) {
return;
}
var rows = this.tf.tbl.rows;
Dom.removeClass(rows[idx], this.oddCss);
Dom.removeClass(rows[idx], this.evenCss);
let rows = this.tf.dom().rows;
removeClass(rows[idx], this.oddCss);
removeClass(rows[idx], this.evenCss);
}
/** @private */
processRowHandler(tf, rowIndex, arrIndex, isValid) {
this.processRow(rowIndex, arrIndex, isValid);
}
/**
* Removes all alternating backgrounds
*/
destroy() {
if(!this.initialized){
if (!this.initialized) {
return;
}
for(var i=this.tf.refRow; i<this.tf.nbRows; i++){
this.removeRowBg(i);
}
let eachRow = this.tf.eachRow(0);
eachRow((row, i) => this.removeRowBg(i));
// Unsubscribe to events
this.emitter.off(['row-processed', 'row-paged'],
bound(this.processRowHandler, this));
this.emitter.off(['column-sorted', 'rows-changed'],
bound(this.processAll, this));
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,288 +1,326 @@
import Dom from '../dom';
import Arr from '../array';
import Str from '../string';
import Sort from '../sort';
import Event from '../event';
import {BaseDropdown} from './baseDropdown';
import {
addClass, createCheckItem, createText, createElm, elm, removeClass, tag
} from '../dom';
import {has} from '../array';
import {matchCase, trim, rgxEsc} from '../string';
import {addEvt, removeEvt, targetEvt} from '../event';
import {isEmpty} from '../types';
import {CHECKLIST, NONE} from '../const';
import {defaultsStr, defaultsBool} from '../settings';
export class CheckList{
/**
* Checklist filter UI component
* @export
* @class CheckList
* @extends {BaseDropdown}
*/
export class CheckList extends BaseDropdown {
/**
* Checklist UI component
* @param {Object} tf TableFilter instance
* Creates an instance of CheckList
* @param {TableFilter} tf TableFilter instance
*/
constructor(tf){
// Configuration object
var f = tf.config();
constructor(tf) {
super(tf, CheckList);
this.checkListDiv = []; //checklist container div
//defines css class for div containing checklist filter
this.checkListDivCssClass = f.div_checklist_css_class ||
'div_checklist';
//defines css class for checklist filters
this.checkListCssClass = f.checklist_css_class || 'flt_checklist';
//defines css class for checklist item (li)
this.checkListItemCssClass = f.checklist_item_css_class ||
'flt_checklist_item';
//defines css class for selected checklist item (li)
this.checkListSlcItemCssClass = f.checklist_selected_item_css_class ||
'flt_checklist_slc_item';
//Load on demand text
this.activateCheckListTxt = f.activate_checklist_text ||
'Click to load filter data';
//defines css class for checklist filters
this.checkListItemDisabledCssClass =
f.checklist_item_disabled_css_class ||
'flt_checklist_item_disabled';
this.enableCheckListResetFilter =
f.enable_checklist_reset_filter===false ? false : true;
//checklist filter container div
this.prfxCheckListDiv = 'chkdiv_';
let f = this.config;
this.isCustom = null;
this.opts = null;
this.optsTxt = null;
this.excludedOpts = null;
/**
* List of container DOM elements
* @type {Array}
*/
this.containers = [];
this.tf = tf;
}
/**
* Css class for the container of the checklist filter (div)
* @type {String}
*/
this.containerCssClass = defaultsStr(f.div_checklist_css_class,
'div_checklist');
// TODO: move event here
onChange(evt){
let elm = evt.target;
this.tf.activeFilterId = elm.getAttribute('id');
this.tf.activeFlt = Dom.id(this.tf.activeFilterId);
this.tf.Evt.onSlcChange.call(this.tf, evt);
}
/**
* Css class for the checklist filter element (ul)
* @type {String}
*/
this.filterCssClass = defaultsStr(f.checklist_css_class,
'flt_checklist');
optionClick(evt){
this.setCheckListValues(evt.target);
this.onChange(evt);
}
/**
* Css class for the item of a checklist (li)
* @type {String}
*/
this.itemCssClass = defaultsStr(f.checklist_item_css_class,
'flt_checklist_item');
/**
* Build checklist UI asynchronously
* @param {Number} colIndex Column index
* @param {Boolean} isExternal Render in external container
* @param {String} extFltId External container id
*/
build(colIndex, isExternal, extFltId){
var tf = this.tf;
tf.EvtManager(
tf.Evt.name.checklist,
{ slcIndex:colIndex, slcExternal:isExternal, slcId:extFltId }
/**
* Css class for a selected item of a checklist (li)
* @type {String}
*/
this.selectedItemCssClass = defaultsStr(
f.checklist_selected_item_css_class,
'flt_checklist_slc_item'
);
/**
* Text placed in the filter's container when load filter on demand
* feature is enabled
* @type {String}
*/
this.activateText = defaultsStr(
f.activate_checklist_text,
'Click to load filter data'
);
/**
* Css class for a disabled item of a checklist (li)
* @type {String}
*/
this.disabledItemCssClass = defaultsStr(
f.checklist_item_disabled_css_class,
'flt_checklist_item_disabled'
);
/**
* Enable the reset filter option as first item
* @type {Boolean}
*/
this.enableResetOption = defaultsBool(f.enable_checklist_reset_filter,
true);
/**
* Prefix for container element ID
* @type {String}
* @private
*/
this.prfx = 'chkdiv_';
}
/**
* Checklist option click event handler
* @param {Event} evt
* @private
*/
optionClick(evt) {
let elm = targetEvt(evt);
let tf = this.tf;
this.emitter.emit('filter-focus', tf, elm);
this.setItemOption(elm);
tf.filter();
}
/**
* Checklist container click event handler for load-on-demand feature
* @param {Event} evt
* @private
*/
onCheckListClick(evt) {
let elm = targetEvt(evt);
if (this.tf.loadFltOnDemand && elm.getAttribute('filled') === '0') {
let ct = elm.getAttribute('ct');
let div = this.containers[ct];
this.build(ct);
removeEvt(div, 'click', (evt) => this.onCheckListClick(evt));
}
}
/**
* Refresh all checklist filters
*/
refreshAll() {
let colIdxs = this.tf.getFiltersByType(CHECKLIST, true);
this.refreshFilters(colIdxs);
}
/**
* Initialize checklist filter
* @param {Number} colIndex Column index
* @param {Boolean} isExternal External filter flag
* @param {DOMElement} container Dom element containing the filter
*/
init(colIndex, isExternal, container) {
let tf = this.tf;
let externalFltTgtId = isExternal ?
tf.externalFltIds[colIndex] : null;
let divCont = createElm('div',
['id', `${this.prfx}${colIndex}_${tf.id}`],
['ct', colIndex], ['filled', '0']);
divCont.className = this.containerCssClass;
//filter is appended in desired element
if (externalFltTgtId) {
elm(externalFltTgtId).appendChild(divCont);
} else {
container.appendChild(divCont);
}
this.containers[colIndex] = divCont;
tf.fltIds.push(tf.buildFilterId(colIndex));
if (!tf.loadFltOnDemand) {
this.build(colIndex);
} else {
addEvt(divCont, 'click', (evt) => this.onCheckListClick(evt));
divCont.appendChild(createText(this.activateText));
}
this.emitter.on(
['build-checklist-filter'],
(tf, colIndex, isLinked) => this.build(colIndex, isLinked)
);
this.emitter.on(
['select-checklist-options'],
(tf, colIndex, values) => this.selectOptions(colIndex, values)
);
this.emitter.on(['rows-changed'], () => this.refreshAll());
this.emitter.on(['after-filtering'], () => this.linkFilters());
/** @inherited */
this.initialized = true;
}
/**
* Build checklist UI
* @param {Number} colIndex Column index
* @param {Boolean} isExternal Render in external container
* @param {String} extFltId External container id
* @param {Boolean} isLinked Enable linked filters behaviour
*/
_build(colIndex, isExternal=false, extFltId=null){
var tf = this.tf;
colIndex = parseInt(colIndex, 10);
build(colIndex, isLinked = false) {
let tf = this.tf;
colIndex = Number(colIndex);
this.emitter.emit('before-populating-filter', tf, colIndex);
/** @inherited */
this.opts = [];
/** @inherited */
this.optsTxt = [];
var divFltId = this.prfxCheckListDiv+colIndex+'_'+tf.id;
if((!Dom.id(divFltId) && !isExternal) ||
(!Dom.id(extFltId) && isExternal)){
return;
}
let flt = this.containers[colIndex];
let ul = createElm('ul',
['id', tf.fltIds[colIndex]],
['colIndex', colIndex]);
ul.className = this.filterCssClass;
var flt = !isExternal ? this.checkListDiv[colIndex] : Dom.id(extFltId);
var ul = Dom.create(
'ul', ['id', tf.fltIds[colIndex]], ['colIndex', colIndex]);
ul.className = this.checkListCssClass;
Event.add(ul, 'change', (evt) => { this.onChange(evt); });
var rows = tf.tbl.rows;
let caseSensitive = tf.caseSensitive;
/** @inherited */
this.isCustom = tf.isCustomOptions(colIndex);
var activeFlt;
if(tf.linkedFilters && tf.activeFilterId){
activeFlt = tf.activeFilterId.split('_')[0];
activeFlt = activeFlt.split(tf.prfxFlt)[1];
}
var filteredDataCol = [];
if(tf.linkedFilters && tf.disableExcludedOptions){
this.excludedOpts = [];
}
for(var k=tf.refRow; k<tf.nbRows; k++){
// always visible rows don't need to appear on selects as always
// valid
if(tf.hasVisibleRows && tf.visibleRows.indexOf(k) !== -1){
continue;
}
var cells = rows[k].cells;
var ncells = cells.length;
// checks if row has exact cell #
if(ncells !== tf.nbCells || this.isCustom){
continue;
}
// this loop retrieves cell data
for(var j=0; j<ncells; j++){
// WTF: cyclomatic complexity hell :)
if((colIndex===j && (!tf.linkedFilters ||
(tf.linkedFilters && tf.disableExcludedOptions)))||
(colIndex===j && tf.linkedFilters &&
((rows[k].style.display === '' && !tf.paging) ||
(tf.paging && ((!activeFlt || activeFlt===colIndex )||
(activeFlt!=colIndex &&
tf.validRowsIndex.indexOf(k) != -1)) )))){
var cell_data = tf.getCellData(cells[j]);
//Vary Peter's patch
var cell_string = Str.matchCase(cell_data, tf.matchCase);
// checks if celldata is already in array
if(!Arr.has(this.opts, cell_string, tf.matchCase)){
this.opts.push(cell_data);
}
var filteredCol = filteredDataCol[j];
if(tf.linkedFilters && tf.disableExcludedOptions){
if(!filteredCol){
filteredCol = tf.getFilteredDataCol(j);
}
if(!Arr.has(filteredCol, cell_string, tf.matchCase) &&
!Arr.has(this.excludedOpts,
cell_string, tf.matchCase) &&
!tf.isFirstLoad){
this.excludedOpts.push(cell_data);
}
}
}
}
}
//Retrieves custom values
if(this.isCustom){
var customValues = tf.getCustomOptions(colIndex);
if (this.isCustom) {
let customValues = tf.getCustomOptions(colIndex);
this.opts = customValues[0];
this.optsTxt = customValues[1];
}
if(tf.sortSlc && !this.isCustom){
if (!tf.matchCase){
this.opts.sort(Sort.ignoreCase);
if(this.excludedOpts){
this.excludedOpts.sort(Sort.ignoreCase);
let activeIdx;
let activeFilterId = tf.getActiveFilterId();
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);
}
} else {
this.opts.sort();
if(this.excludedOpts){
this.excludedOpts.sort();
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;
}
}
}
//asc sort
if(tf.sortNumAsc && 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) {
this.opts.sort();
if(this.excludedOpts){
this.excludedOpts.sort();
}
if(this.isCustom){
this.optsTxt.sort();
}
}//in case there are alphanumeric values
}
//desc sort
if(tf.sortNumDesc && 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) {
this.opts.sort();
if(this.excludedOpts){
this.excludedOpts.sort(); }
if(this.isCustom){
this.optsTxt.sort();
}
}//in case there are alphanumeric values
);
//sort options
this.opts = this.sortOptions(colIndex, this.opts);
if (this.excludedOpts) {
this.excludedOpts = this.sortOptions(colIndex, this.excludedOpts);
}
this.addChecks(colIndex, ul, tf.separator);
this.addChecks(colIndex, ul);
if(tf.loadFltOnDemand){
if (tf.loadFltOnDemand) {
flt.innerHTML = '';
}
flt.appendChild(ul);
flt.setAttribute('filled', '1');
this.emitter.emit('after-populating-filter', tf, colIndex, flt);
}
/**
* Add checklist options
* @param {Number} colIndex Column index
* @param {Object} ul Ul element
* @private
*/
addChecks(colIndex, ul){
var tf = this.tf;
var chkCt = this.addTChecks(colIndex, ul);
var fltArr = []; //remember grid values
var store = tf.feature('store');
var tmpVal = store ?
store.getFilterValues(tf.fltsValuesCookie)[colIndex] : null;
if(tmpVal && Str.trim(tmpVal).length > 0){
if(tf.hasCustomSlcOptions &&
tf.customSlcOptions.cols.indexOf(colIndex) != -1){
fltArr.push(tmpVal);
} else {
fltArr = tmpVal.split(' '+tf.orOperator+' ');
}
}
addChecks(colIndex, ul) {
let tf = this.tf;
let chkCt = this.addTChecks(colIndex, ul);
for(var y=0; y<this.opts.length; y++){
var val = this.opts[y]; //item value
var lbl = this.isCustom ? this.optsTxt[y] : val; //item text
var li = Dom.createCheckItem(
tf.fltIds[colIndex]+'_'+(y+chkCt), val, lbl);
li.className = this.checkListItemCssClass;
if(tf.linkedFilters && tf.disableExcludedOptions &&
Arr.has(this.excludedOpts,
Str.matchCase(val, tf.matchCase), tf.matchCase)){
Dom.addClass(li, this.checkListItemDisabledCssClass);
li.check.disabled = true;
li.disabled = true;
for (let y = 0; y < this.opts.length; y++) {
let val = this.opts[y]; //item value
let lbl = this.isCustom ? this.optsTxt[y] : val; //item text
let fltId = tf.fltIds[colIndex];
let lblIdx = y + chkCt;
let li = createCheckItem(`${fltId}_${lblIdx}`, val, lbl,
['data-idx', lblIdx]);
li.className = this.itemCssClass;
if (tf.linkedFilters && tf.disableExcludedOptions &&
has(this.excludedOpts, matchCase(val, tf.caseSensitive),
tf.caseSensitive)) {
addClass(li, this.disabledItemCssClass);
li.check.disabled = true;
li.disabled = true;
} else {
Event.add(li.check, 'click',
(evt) => { this.optionClick(evt); });
addEvt(li.check, 'click', evt => this.optionClick(evt));
}
ul.appendChild(li);
if(val===''){
if (val === '') {
//item is hidden
li.style.display = 'none';
}
/*** remember grid values ***/
if(tf.rememberGridValues){
if((tf.hasCustomSlcOptions &&
tf.customSlcOptions.cols.indexOf(colIndex) != -1 &&
fltArr.toString().indexOf(val) != -1) ||
Arr.has(fltArr,
Str.matchCase(val, tf.matchCase), tf.matchCase)){
li.check.checked = true;
this.setCheckListValues(li.check);
}
li.style.display = NONE;
}
}
}
@ -291,129 +329,191 @@ export class CheckList{
* Add checklist header option
* @param {Number} colIndex Column index
* @param {Object} ul Ul element
* @private
*/
addTChecks(colIndex, ul){
var tf = this.tf;
var chkCt = 1;
var li0 = Dom.createCheckItem(
tf.fltIds[colIndex]+'_0', '', tf.displayAllText);
li0.className = this.checkListItemCssClass;
addTChecks(colIndex, ul) {
let tf = this.tf;
let chkCt = 1;
let fltId = tf.fltIds[colIndex];
let li0 = createCheckItem(`${fltId}_0`, '',
tf.getClearFilterText(colIndex), ['data-idx', 0]);
li0.className = this.itemCssClass;
ul.appendChild(li0);
Event.add(li0.check, 'click', (evt) => {
this.optionClick(evt);
});
addEvt(li0.check, 'click', evt => this.optionClick(evt));
if(!this.enableCheckListResetFilter){
li0.style.display = 'none';
if (!this.enableResetOption) {
li0.style.display = NONE;
}
if(tf.enableEmptyOption){
var li1 = Dom.createCheckItem(
tf.fltIds[colIndex]+'_1', tf.emOperator, tf.emptyText);
li1.className = this.checkListItemCssClass;
if (tf.enableEmptyOption) {
let li1 = createCheckItem(`${fltId}_1`, tf.emOperator,
tf.emptyText, ['data-idx', 1]);
li1.className = this.itemCssClass;
ul.appendChild(li1);
Event.add(li1.check, 'click', (evt) => {
this.optionClick(evt);
});
addEvt(li1.check, 'click', evt => this.optionClick(evt));
chkCt++;
}
if(tf.enableNonEmptyOption){
var li2 = Dom.createCheckItem(
tf.fltIds[colIndex]+'_2',
tf.nmOperator,
tf.nonEmptyText
);
li2.className = this.checkListItemCssClass;
if (tf.enableNonEmptyOption) {
let li2 = createCheckItem(`${fltId}_2`, tf.nmOperator,
tf.nonEmptyText, ['data-idx', 2]);
li2.className = this.itemCssClass;
ul.appendChild(li2);
Event.add(li2.check, 'click', (evt) => {
this.optionClick(evt);
});
addEvt(li2.check, 'click', evt => this.optionClick(evt));
chkCt++;
}
return chkCt;
}
/**
* 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
* @private
*/
setCheckListValues(o){
if(!o){
setItemOption(o) {
if (!o) {
return;
}
var tf = this.tf;
var chkValue = o.value; //checked item value
var chkIndex = parseInt(o.id.split('_')[2], 10);
var filterTag = 'ul', itemTag = 'li';
var n = o;
//ul tag search
while(Str.lower(n.nodeName)!==filterTag){
n = n.parentNode;
}
let tf = this.tf;
let chkValue = o.value; //checked item value
let chkIndex = o.dataset.idx;
let colIdx = tf.getColumnIndexFromFilterId(o.id);
let n = tf.getFilterElement(parseInt(colIdx, 10));
let items = n.childNodes;
let li = items[chkIndex];
//selected values (ul tag)
let slcValues = n.getAttribute('value') || '';
//selected items indexes (ul tag)
let slcIndexes = n.getAttribute('indexes') || '';
var li = n.childNodes[chkIndex];
var colIndex = n.getAttribute('colIndex');
var fltValue = n.getAttribute('value'); //filter value (ul tag)
var fltIndexes = n.getAttribute('indexes'); //selected items (ul tag)
if(o.checked){
if (o.checked) {
//show all item
if(chkValue===''){
if((fltIndexes && fltIndexes!=='')){
//items indexes
var indSplit = fltIndexes.split(tf.separator);
//checked items loop
for(var u=0; u<indSplit.length; u++){
//checked item
var cChk = Dom.id(tf.fltIds[colIndex]+'_'+indSplit[u]);
if(cChk){
cChk.checked = false;
Dom.removeClass(
n.childNodes[indSplit[u]],
this.checkListSlcItemCssClass
);
}
if (chkValue === '') {
//items indexes
let indexes = slcIndexes.split(tf.separator);
indexes.forEach(idx => {
idx = Number(idx);
let li = items[idx];
let chx = tag(li, 'input')[0];
if (chx && idx > 0) {
chx.checked = false;
removeClass(li, this.selectedItemCssClass);
}
}
});
n.setAttribute('value', '');
n.setAttribute('indexes', '');
} else {
fltValue = (fltValue) ? fltValue : '';
chkValue = Str.trim(
fltValue+' '+chkValue+' '+tf.orOperator);
chkIndex = fltIndexes + chkIndex + tf.separator;
n.setAttribute('value', chkValue );
n.setAttribute('indexes', chkIndex);
//1st option unchecked
if(Dom.id(tf.fltIds[colIndex]+'_0')){
Dom.id(tf.fltIds[colIndex]+'_0').checked = false;
let indexes = slcIndexes + chkIndex + tf.separator;
let values =
trim(slcValues + ' ' + chkValue + ' ' + tf.orOperator);
n.setAttribute('value', values);
n.setAttribute('indexes', indexes);
//uncheck first option
let chx0 = tag(items[0], 'input')[0];
if (chx0) {
chx0.checked = false;
}
}
if(Str.lower(li.nodeName) === itemTag){
Dom.removeClass(
n.childNodes[0], this.checkListSlcItemCssClass);
Dom.addClass(li, this.checkListSlcItemCssClass);
}
removeClass(items[0], this.selectedItemCssClass);
addClass(li, this.selectedItemCssClass);
} else { //removes values and indexes
if(chkValue!==''){
var replaceValue = new RegExp(
Str.rgxEsc(chkValue+' '+tf.orOperator));
fltValue = fltValue.replace(replaceValue,'');
n.setAttribute('value', Str.trim(fltValue));
let replaceValue =
new RegExp(rgxEsc(chkValue + ' ' + tf.orOperator));
let values = slcValues.replace(replaceValue, '');
let replaceIndex = new RegExp(rgxEsc(chkIndex + tf.separator));
let indexes = slcIndexes.replace(replaceIndex, '');
var replaceIndex = new RegExp(
Str.rgxEsc(chkIndex + tf.separator));
fltIndexes = fltIndexes.replace(replaceIndex, '');
n.setAttribute('indexes', fltIndexes);
}
if(Str.lower(li.nodeName)===itemTag){
Dom.removeClass(li, this.checkListSlcItemCssClass);
}
n.setAttribute('value', trim(values));
n.setAttribute('indexes', indexes);
removeClass(li, this.selectedItemCssClass);
}
}
/**
* Select filter options programmatically
* @param {Number} colIndex Column index
* @param {Array} values Array of option values to select
*/
selectOptions(colIndex, values = []) {
let tf = this.tf;
let flt = tf.getFilterElement(colIndex);
if (!flt || values.length === 0) {
return;
}
let lis = tag(flt, 'li');
flt.setAttribute('value', '');
flt.setAttribute('indexes', '');
[].forEach.call(lis, (li) => {
let chk = tag(li, 'input')[0];
let chkVal = matchCase(chk.value, tf.caseSensitive);
if (chkVal !== '' && has(values, chkVal, tf.caseSensitive)) {
chk.checked = true;
} else {
// Check non-empty-text or empty-text option
if (values.indexOf(tf.nmOperator) !== -1 &&
chkVal === matchCase(tf.nonEmptyText, tf.caseSensitive)) {
chk.checked = true;
}
else if (values.indexOf(tf.emOperator) !== -1 &&
chkVal === matchCase(tf.emptyText, tf.caseSensitive)) {
chk.checked = true;
} else {
chk.checked = false;
}
}
this.setItemOption(chk);
});
}
/**
* Get filter values for a given column index
* @param {Number} colIndex Column index
* @returns {Array} values Collection of selected values
*/
getValues(colIndex) {
let tf = this.tf;
let flt = tf.getFilterElement(colIndex);
if (!flt) {
return [];
}
let fltAttr = flt.getAttribute('value');
let values = isEmpty(fltAttr) ? '' : fltAttr;
//removes last operator ||
values = values.substr(0, values.length - 3);
//turn || separated values into array
values = values.split(' ' + tf.orOperator + ' ');
return values;
}
/**
* Destroy CheckList instance
*/
destroy() {
this.emitter.off(
['build-checklist-filter'],
(tf, colIndex, isLinked) => this.build(colIndex, isLinked)
);
this.emitter.off(
['select-checklist-options'],
(tf, colIndex, values) => this.selectOptions(colIndex, values)
);
this.emitter.off(['rows-changed'], () => this.refreshAll());
this.emitter.off(['after-filtering'], () => this.linkFilters());
this.initialized = false;
}
}

View file

@ -1,94 +1,142 @@
import {Feature} from './feature';
import Dom from '../dom';
import Event from '../event';
import {Feature} from '../feature';
import {createElm, createText, elm, removeElm} from '../dom';
import {addEvt} from '../event';
import {defaultsStr} from '../settings';
import {isNull} from '../types';
import {RIGHT} from './toolbar';
export class ClearButton extends Feature{
/**
* Clear button UI component
*/
export class ClearButton extends Feature {
/**
* Clear button component
* @param {Object} tf TableFilter instance
* Creates an instance of ClearButton
* @param {TableFilter} tf TableFilter instance
*/
constructor(tf){
super(tf, 'btnReset');
constructor(tf) {
super(tf, ClearButton);
// Configuration object
var f = this.config;
let f = this.config.btn_reset || {};
//id of container element
this.btnResetTgtId = f.btn_reset_target_id || null;
//reset button element
this.btnResetEl = null;
//defines reset text
this.btnResetText = f.btn_reset_text || 'Reset';
//defines reset button tooltip
this.btnResetTooltip = f.btn_reset_tooltip || 'Clear filters';
//defines reset button innerHtml
this.btnResetHtml = f.btn_reset_html ||
(!tf.enableIcons ? null :
'<input type="button" value="" class="'+tf.btnResetCssClass+'" ' +
'title="'+this.btnResetTooltip+'" />');
//span containing reset button
this.prfxResetSpan = 'resetspan_';
/**
* Container element ID
* @type {String}
*/
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
* @type {DOMElement}
* @private
*/
this.container = null;
/**
* Clear button element
* @type {DOMElement}
* @private
*/
this.element = null;
}
onClick(){
if(!this.isEnabled()){
/**
* Click event handler for clear button
* @private
*/
onClick() {
if (!this.isEnabled()) {
return;
}
this.tf.clearFilters();
}
/**
* Build DOM elements
* Initialize clear button component
*/
init(){
var tf = this.tf;
init() {
let tf = this.tf;
if(this.initialized){
if (this.initialized) {
return;
}
var resetspan = Dom.create('span', ['id', this.prfxResetSpan+tf.id]);
this.emitter.emit('initializing-feature', this, !isNull(this.targetId));
// reset button is added to defined element
if(!this.btnResetTgtId){
tf.setToolbar();
}
var targetEl = !this.btnResetTgtId ?
tf.rDiv : Dom.id(this.btnResetTgtId);
targetEl.appendChild(resetspan);
let cont = createElm('span');
if(!this.btnResetHtml){
var fltreset = Dom.create('a', ['href', 'javascript:void(0);']);
fltreset.className = tf.btnResetCssClass;
fltreset.appendChild(Dom.text(this.btnResetText));
resetspan.appendChild(fltreset);
Event.add(fltreset, 'click', ()=> { this.onClick(); });
let targetEl = !this.targetId ?
tf.feature('toolbar').container(this.toolbarPosition) :
elm(this.targetId);
targetEl.appendChild(cont);
if (!this.html) {
let fltReset = createElm('a', ['href', 'javascript:void(0);']);
fltReset.className = this.cssClass;
fltReset.appendChild(createText(this.text));
cont.appendChild(fltReset);
addEvt(fltReset, 'click', () => this.onClick());
} else {
resetspan.innerHTML = this.btnResetHtml;
var resetEl = resetspan.firstChild;
Event.add(resetEl, 'click', ()=> { this.onClick(); });
cont.innerHTML = this.html;
let resetEl = cont.firstChild;
addEvt(resetEl, 'click', () => this.onClick());
}
this.btnResetEl = resetspan.firstChild;
this.element = cont.firstChild;
this.container = cont;
/** @inherited */
this.initialized = true;
this.emitter.emit('feature-initialized', this);
}
/**
* Remove clear button UI
* Destroy ClearButton instance
*/
destroy(){
var tf = this.tf;
if(!this.initialized){
destroy() {
if (!this.initialized) {
return;
}
var resetspan = Dom.id(this.prfxResetSpan+tf.id);
if(resetspan){
Dom.remove(resetspan);
}
this.btnResetEl = null;
removeElm(this.element);
removeElm(this.container);
this.element = null;
this.container = null;
this.initialized = false;
}
}
// TODO: remove as soon as feature name is fixed
ClearButton.meta = {altName: 'btnReset'};

157
src/modules/dateType.js Normal file
View file

@ -0,0 +1,157 @@
import {Date as SugarDate} from 'sugar-date';
import 'sugar-date/locales';
import {Feature} from '../feature';
import {isObj, isArray} from '../types';
import {DATE} from '../const';
import {root} from '../root';
/**
* Wrapper for Sugar Date module providing datetime helpers and locales
* @export
* @class DateType
*/
export class DateType extends Feature {
/**
* Creates an instance of DateType
* @param {TableFilter} tf TableFilter instance
*/
constructor(tf) {
super(tf, DateType);
/**
* Global locale
* @type {String}
*/
this.locale = tf.locale;
/**
* Sugar Date instance
* @type {Object}
*/
this.datetime = SugarDate;
this.enable();
}
/**
* Initialize DateType instance
*/
init() {
if (this.initialized) {
return;
}
// Set global locale
this.datetime.setLocale(this.locale);
// Add formats from column types configuration if any
this.addConfigFormats(this.tf.colTypes);
this.emitter.on(
['add-date-type-formats'],
(tf, types) => this.addConfigFormats(types)
);
// Broadcast date-type initialization
this.emitter.emit('date-type-initialized', this.tf, this);
/** @inherited */
this.initialized = true;
}
/**
* Parse a string representation of a date for a specified locale and return
* a date object
* @param {String} dateStr String representation of a date
* @param {String} localeCode Locale code (ie 'en-us')
* @returns {Date}
*/
parse(dateStr, localeCode) {
return this.datetime.create(dateStr, localeCode);
}
/**
* Check string representation of a date for a specified locale is valid
* @param {any} dateStr String representation of a date
* @param {any} localeCode Locale code (ie 'en-us')
* @returns {Boolean}
*/
isValid(dateStr, localeCode) {
return this.datetime.isValid(this.parse(dateStr, localeCode));
}
/**
* Return the type object of a specified column as per configuration or
* passed collection
* @param {Number} colIndex Column index
* @param {Array} types Collection of column types, optional
* @returns {Object}
*/
getOptions(colIndex, types) {
types = types || this.tf.colTypes;
let colType = types[colIndex];
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
* collection of column types, ie:
* [
* 'string',
* 'number',
* { type: 'date', locale: 'en', format: ['{dd}/{MM}/{yyyy}']}
* ]
*
* @param {Array} [types=[]] Collection of column types
*/
addConfigFormats(types=[]) {
types.forEach((type, idx) => {
let options = this.getOptions(idx, types);
if (options.type === DATE && options.hasOwnProperty('format')) {
let locale = this.datetime.getLocale(
options.locale || this.locale
);
let formats = isArray(options.format) ?
options.format : [options.format];
// Sugar date module throws exceptions with locale.addFormat
try {
formats.forEach((format) => {
locale.addFormat(format);
});
} catch (ex) {
root.console.error(ex);
}
}
});
}
/**
* Remove DateType instance
*/
destroy() {
if (!this.initialized) {
return;
}
// TODO: remove added formats
this.emitter.off(
['add-date-type-formats'],
(tf, types) => this.addConfigFormats(types)
);
this.initialized = false;
}
}

View file

@ -1,231 +1,242 @@
import Dom from '../dom';
import Arr from '../array';
import Str from '../string';
import Sort from '../sort';
import {BaseDropdown} from './baseDropdown';
import {createElm, createOpt, elm} from '../dom';
import {has} from '../array';
import {matchCase} from '../string';
import {addEvt, targetEvt} from '../event';
import {SELECT, MULTIPLE, NONE} from '../const';
import {defaultsStr, defaultsBool} from '../settings';
export class Dropdown{
/**
* Dropdown filter UI component
* @export
* @class Dropdown
* @extends {BaseDropdown}
*/
export class Dropdown extends BaseDropdown {
/**
* Dropdown UI component
* @param {Object} tf TableFilter instance
* Creates an instance of Dropdown
* @param {TableFilter} tf TableFilter instance
*/
constructor(tf){
constructor(tf) {
super(tf, Dropdown);
// Configuration object
var f = tf.config();
let f = this.config;
this.enableSlcResetFilter = f.enable_slc_reset_filter===false ?
false : true;
//defines empty option text
this.nonEmptyText = f.non_empty_text || '(Non empty)';
//sets select filling method: 'innerHTML' or 'createElement'
this.slcFillingMethod = f.slc_filling_method || 'createElement';
//IE only, tooltip text appearing on select before it is populated
this.activateSlcTooltip = f.activate_slc_tooltip ||
'Click to activate';
//tooltip text appearing on multiple select
this.multipleSlcTooltip = f.multiple_slc_tooltip ||
'Use Ctrl key for multiple selections';
/**
* Enable the reset filter option as first item
* @type {Boolean}
*/
this.enableSlcResetFilter =
defaultsBool(f.enable_slc_reset_filter, true);
this.isCustom = null;
this.opts = null;
this.optsTxt = null;
this.slcInnerHtml = null;
/**
* Non empty option text
* @type {String}
*/
this.nonEmptyText = defaultsStr(f.non_empty_text, '(Non empty)');
this.tf = tf;
/**
* Tooltip text appearing on multiple select
* @type {String}
*/
this.multipleSlcTooltip = defaultsStr(f.multiple_slc_tooltip,
'Use Ctrl/Cmd key for multiple selections');
}
/**
* Drop-down filter focus event handler
* @param {Event} e DOM Event
* @private
*/
onSlcFocus(e) {
let elm = targetEvt(e);
let tf = this.tf;
// select is populated when element has focus
if (tf.loadFltOnDemand && elm.getAttribute('filled') === '0') {
let ct = elm.getAttribute('ct');
this.build(ct);
}
this.emitter.emit('filter-focus', tf, elm);
}
/**
* Build drop-down filter UI asynchronously
* @param {Number} colIndex Column index
* @param {Boolean} isLinked Enable linked refresh behaviour
* @param {Boolean} isExternal Render in external container
* @param {String} extSlcId External container id
* Drop-down filter change event handler
* @private
*/
build(colIndex, isLinked, isExternal, extSlcId){
var tf = this.tf;
tf.EvtManager(
tf.Evt.name.dropdown,
{
slcIndex: colIndex,
slcRefreshed: isLinked,
slcExternal: isExternal,
slcId: extSlcId
}
onSlcChange() {
if (this.tf.onSlcChange) {
this.tf.filter();
}
}
/**
* Refresh all drop-down filters
*/
refreshAll() {
let selectFlts = this.tf.getFiltersByType(SELECT, true);
let multipleFlts = this.tf.getFiltersByType(MULTIPLE, true);
let colIdxs = selectFlts.concat(multipleFlts);
this.refreshFilters(colIdxs);
}
/**
* Initialize drop-down filter
* @param {Number} colIndex Column index
* @param {Boolean} isExternal External filter flag
* @param {DOMElement} container Dom element containing the filter
*/
init(colIndex, isExternal, container) {
let tf = this.tf;
let col = tf.getFilterType(colIndex);
let externalFltTgtId = isExternal ?
tf.externalFltIds[colIndex] : null;
let slc = createElm(SELECT,
['id', tf.buildFilterId(colIndex)],
['ct', colIndex], ['filled', '0']
);
if (col === MULTIPLE) {
slc.multiple = MULTIPLE;
slc.title = this.multipleSlcTooltip;
}
slc.className = col.toLowerCase() === SELECT ?
tf.fltCssClass : tf.fltMultiCssClass;
//filter is appended in container element
if (externalFltTgtId) {
elm(externalFltTgtId).appendChild(slc);
} else {
container.appendChild(slc);
}
tf.fltIds.push(slc.id);
if (!tf.loadFltOnDemand) {
this.build(colIndex);
} else {
//1st option is created here since build isn't invoked
let opt0 = createOpt(tf.getClearFilterText(colIndex), '');
slc.appendChild(opt0);
}
addEvt(slc, 'change', () => this.onSlcChange());
addEvt(slc, 'focus', (e) => this.onSlcFocus(e));
this.emitter.on(
['build-select-filter'],
(tf, colIndex, isLinked, isExternal) =>
this.build(colIndex, isLinked, isExternal)
);
this.emitter.on(
['select-options'],
(tf, colIndex, values) => this.selectOptions(colIndex, values)
);
this.emitter.on(['rows-changed'], () => this.refreshAll());
this.emitter.on(['after-filtering'], () => this.linkFilters());
/** @inherited */
this.initialized = true;
}
/**
* Build drop-down filter UI
* @param {Number} colIndex Column index
* @param {Boolean} isLinked Enable linked refresh behaviour
* @param {Boolean} isExternal Render in external container
* @param {String} extSlcId External container id
* @param {Boolean} isLinked Enable linked filters behaviour
*/
_build(colIndex, isLinked=false, isExternal=false, extSlcId=null){
var tf = this.tf;
colIndex = parseInt(colIndex, 10);
build(colIndex, isLinked = false) {
let tf = this.tf;
colIndex = Number(colIndex);
this.emitter.emit('before-populating-filter', tf, colIndex);
/** @inherited */
this.opts = [];
/** @inherited */
this.optsTxt = [];
this.slcInnerHtml = '';
var slcId = tf.fltIds[colIndex];
if((!Dom.id(slcId) && !isExternal) ||
(!Dom.id(extSlcId) && isExternal)){
return;
}
var slc = !isExternal ? Dom.id(slcId) : Dom.id(extSlcId),
rows = tf.tbl.rows,
matchCase = tf.matchCase;
let slc = tf.getFilterElement(colIndex);
//custom select test
/** @inherited */
this.isCustom = tf.isCustomOptions(colIndex);
//custom selects text
var activeFlt;
if(isLinked && tf.activeFilterId){
activeFlt = tf.activeFilterId.split('_')[0];
activeFlt = activeFlt.split(tf.prfxFlt)[1];
}
/*** remember grid values ***/
var fltsValues = [], fltArr = [];
if(tf.rememberGridValues){
fltsValues =
tf.feature('store').getFilterValues(tf.fltsValuesCookie);
if(fltsValues && !Str.isEmpty(fltsValues.toString())){
if(this.isCustom){
fltArr.push(fltsValues[colIndex]);
} else {
fltArr = fltsValues[colIndex].split(' '+tf.orOperator+' ');
}
}
}
var excludedOpts = null,
filteredDataCol = null;
if(isLinked && tf.disableExcludedOptions){
excludedOpts = [];
filteredDataCol = [];
}
for(var k=tf.refRow; k<tf.nbRows; k++){
// always visible rows don't need to appear on selects as always
// valid
if(tf.hasVisibleRows && tf.visibleRows.indexOf(k) !== -1){
continue;
}
var 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(var j=0; j<nchilds; j++){
// WTF: cyclomatic complexity hell
if((colIndex===j &&
(!isLinked ||
(isLinked && tf.disableExcludedOptions))) ||
(colIndex==j && isLinked &&
((rows[k].style.display === '' && !tf.paging) ||
(tf.paging && (!tf.validRowsIndex ||
(tf.validRowsIndex &&
tf.validRowsIndex.indexOf(k) != -1)) &&
((activeFlt===undefined || activeFlt==colIndex) ||
(activeFlt!=colIndex &&
tf.validRowsIndex.indexOf(k) != -1 ))) ))){
var cell_data = tf.getCellData(cell[j]),
//Vary Peter's patch
cell_string = Str.matchCase(cell_data, matchCase);
// checks if celldata is already in array
if(!Arr.has(this.opts, cell_string, matchCase)){
this.opts.push(cell_data);
}
if(isLinked && tf.disableExcludedOptions){
var filteredCol = filteredDataCol[j];
if(!filteredCol){
filteredCol = tf.getFilteredDataCol(j);
}
if(!Arr.has(filteredCol, cell_string, matchCase) &&
!Arr.has(
excludedOpts, cell_string, matchCase) &&
!this.isFirstLoad){
excludedOpts.push(cell_data);
}
}
}//if colIndex==j
}//for j
}//for k
//Retrieves custom values
if(this.isCustom){
var customValues = tf.getCustomOptions(colIndex);
if (this.isCustom) {
let customValues = tf.getCustomOptions(colIndex);
this.opts = customValues[0];
this.optsTxt = customValues[1];
}
if(tf.sortSlc && !this.isCustom){
if (!matchCase){
this.opts.sort(Sort.ignoreCase);
if(excludedOpts){
excludedOpts.sort(Sort.ignoreCase);
}
} else {
this.opts.sort();
if(excludedOpts){ excludedOpts.sort(); }
}
//custom selects text
let activeIdx;
let activeFilterId = tf.getActiveFilterId();
if (isLinked && activeFilterId) {
activeIdx = tf.getColumnIndexFromFilterId(activeFilterId);
}
//asc sort
if(tf.sortNumAsc && tf.sortNumAsc.indexOf(colIndex) != -1){
try{
this.opts.sort( numSortAsc );
if(excludedOpts){
excludedOpts.sort(numSortAsc);
}
if(this.isCustom){
this.optsTxt.sort(numSortAsc);
}
} catch(e) {
this.opts.sort();
if(excludedOpts){
excludedOpts.sort();
}
if(this.isCustom){
this.optsTxt.sort();
}
}//in case there are alphanumeric values
let excludedOpts = null,
filteredDataCol = null;
if (isLinked && tf.disableExcludedOptions) {
excludedOpts = [];
filteredDataCol = [];
}
//desc sort
if(tf.sortNumDesc && tf.sortNumDesc.indexOf(colIndex) != -1){
try{
this.opts.sort(numSortDesc);
if(excludedOpts){
excludedOpts.sort(numSortDesc);
let eachRow = tf.eachRow();
eachRow(
(row) => {
let cellValue = tf.getCellValue(row.cells[colIndex]);
//Vary Peter's patch
let cellString = matchCase(cellValue, tf.caseSensitive);
// checks if celldata is already in array
if (!has(this.opts, cellString, tf.caseSensitive)) {
this.opts.push(cellValue);
}
if(this.isCustom){
this.optsTxt.sort(numSortDesc);
if (isLinked && tf.disableExcludedOptions) {
let filteredCol = filteredDataCol[colIndex];
if (!filteredCol) {
filteredCol = tf.getVisibleColumnValues(colIndex);
}
if (!has(filteredCol, cellString, tf.caseSensitive) &&
!has(excludedOpts, cellString, tf.caseSensitive)) {
excludedOpts.push(cellValue);
}
}
} catch(e) {
this.opts.sort();
if(excludedOpts){
excludedOpts.sort();
},
// 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;
}
if(this.isCustom){
this.optsTxt.sort();
// checks if row has expected number of cells
if (row.cells.length !== tf.nbCells || this.isCustom) {
return true;
}
}//in case there are alphanumeric values
if (isLinked && !this.isValidLinkedValue(k, activeIdx)) {
return true;
}
}
);
//sort options
this.opts = this.sortOptions(colIndex, this.opts);
if (excludedOpts) {
excludedOpts = this.sortOptions(colIndex, excludedOpts);
}
//populates drop-down
this.addOptions(
colIndex, slc, isLinked, excludedOpts, fltsValues, fltArr);
this.addOptions(colIndex, slc, isLinked, excludedOpts);
this.emitter.emit('after-populating-filter', tf, colIndex, slc);
}
/**
@ -234,77 +245,41 @@ export class Dropdown{
* @param {Object} slc Select Dom element
* @param {Boolean} isLinked Enable linked refresh behaviour
* @param {Array} excludedOpts Array of excluded options
* @param {Array} fltsValues Collection of persisted filter values
* @param {Array} fltArr Collection of persisted filter values
*/
addOptions(colIndex, slc, isLinked, excludedOpts, fltsValues, fltArr){
var tf = this.tf,
fillMethod = Str.lower(this.slcFillingMethod),
addOptions(colIndex, slc, isLinked, excludedOpts) {
let tf = this.tf,
slcValue = slc.value;
slc.innerHTML = '';
slc = this.addFirstOption(slc);
for(var y=0; y<this.opts.length; y++){
if(this.opts[y]===''){
for (let y = 0; y < this.opts.length; y++) {
if (this.opts[y] === '') {
continue;
}
var val = this.opts[y]; //option value
var lbl = this.isCustom ? this.optsTxt[y] : val; //option text
var isDisabled = false;
if(isLinked && tf.disableExcludedOptions &&
Arr.has(
excludedOpts,
Str.matchCase(val, tf.matchCase),
tf.matchCase
)){
let val = this.opts[y]; //option value
let lbl = this.isCustom ? this.optsTxt[y] : val; //option text
let isDisabled = false;
if (isLinked && tf.disableExcludedOptions &&
has(excludedOpts, matchCase(val, tf.caseSensitive),
tf.caseSensitive)) {
isDisabled = true;
}
if(fillMethod === 'innerhtml'){
var slcAttr = '';
if(tf.loadFltOnDemand && slcValue===this.opts[y]){
slcAttr = 'selected="selected"';
}
this.slcInnerHtml += '<option value="'+val+'" ' + slcAttr +
(isDisabled ? 'disabled="disabled"' : '')+ '>' +
lbl+'</option>';
let opt;
//fill select on demand
if (tf.loadFltOnDemand && slcValue === this.opts[y] &&
tf.getFilterType(colIndex) === SELECT) {
opt = createOpt(lbl, val, true);
} else {
var opt;
//fill select on demand
if(tf.loadFltOnDemand && slcValue===this.opts[y] &&
tf.getFilterType(colIndex) === tf.fltTypeSlc){
opt = Dom.createOpt(lbl, val, true);
} else {
if(tf.getFilterType(colIndex) !== tf.fltTypeMulti){
opt = Dom.createOpt(
lbl,
val,
(fltsValues[colIndex]!==' ' &&
val===fltsValues[colIndex]) ? true : false
);
} else {
opt = Dom.createOpt(
lbl,
val,
(Arr.has(fltArr,
Str.matchCase(this.opts[y], tf.matchCase),
tf.matchCase) ||
fltArr.toString().indexOf(val)!== -1) ?
true : false
);
}
}
if(isDisabled){
opt.disabled = true;
}
slc.appendChild(opt);
opt = createOpt(lbl, val, false);
}
if (isDisabled) {
opt.disabled = true;
}
slc.appendChild(opt);
}// for y
if(fillMethod === 'innerhtml'){
slc.innerHTML += this.slcInnerHtml;
}
slc.setAttribute('filled', '1');
}
@ -312,31 +287,90 @@ export class Dropdown{
* Add drop-down header option
* @param {Object} slc Select DOM element
*/
addFirstOption(slc){
var tf = this.tf,
fillMethod = Str.lower(this.slcFillingMethod);
if(fillMethod === 'innerhtml'){
this.slcInnerHtml += '<option value="">'+ tf.displayAllText +
'</option>';
addFirstOption(slc) {
let tf = this.tf;
let colIdx = tf.getColumnIndexFromFilterId(slc.id);
let opt0 = createOpt((!this.enableSlcResetFilter ?
'' : tf.getClearFilterText(colIdx)), '');
if (!this.enableSlcResetFilter) {
opt0.style.display = NONE;
}
else {
var opt0 = Dom.createOpt(
(!this.enableSlcResetFilter ? '' : tf.displayAllText),'');
if(!this.enableSlcResetFilter){
opt0.style.display = 'none';
}
slc.appendChild(opt0);
if(tf.enableEmptyOption){
var opt1 = Dom.createOpt(tf.emptyText, tf.emOperator);
slc.appendChild(opt1);
}
if(tf.enableNonEmptyOption){
var opt2 = Dom.createOpt(tf.nonEmptyText, tf.nmOperator);
slc.appendChild(opt2);
}
slc.appendChild(opt0);
if (tf.enableEmptyOption) {
let opt1 = createOpt(tf.emptyText, tf.emOperator);
slc.appendChild(opt1);
}
if (tf.enableNonEmptyOption) {
let opt2 = createOpt(tf.nonEmptyText, tf.nmOperator);
slc.appendChild(opt2);
}
return slc;
}
/**
* Select filter options programmatically
* @param {Number} colIndex Column index
* @param {Array} values Array of option values to select
*/
selectOptions(colIndex, values = []) {
let tf = this.tf;
if (values.length === 0) {
return;
}
let slc = tf.getFilterElement(colIndex);
[].forEach.call(slc.options, (option) => {
// Empty value means clear all selections and first option is the
// clear all option
if (values[0] === '' || option.value === '') {
option.selected = false;
}
if (option.value !== '' && has(values, option.value, true)) {
option.selected = true;
}//if
});
}
/**
* Get filter values for a given column index
* @param {Number} colIndex Column index
* @returns {Array} values Array of selected values
*/
getValues(colIndex) {
let tf = this.tf;
let slc = tf.getFilterElement(colIndex);
let values = [];
// IE >= 9 does not support the selectedOptions property :(
if (slc.selectedOptions) {
[].forEach.call(slc.selectedOptions,
option => values.push(option.value));
} else {
[].forEach.call(slc.options, (option) => {
if (option.selected) {
values.push(option.value);
}
});
}
return values;
}
/**
* Destroy Dropdown instance
*/
destroy() {
this.emitter.off(
['build-select-filter'],
(colIndex, isLinked, isExternal) =>
this.build(colIndex, isLinked, isExternal)
);
this.emitter.off(
['select-options'],
(tf, colIndex, values) => this.selectOptions(colIndex, values)
);
this.emitter.off(['rows-changed'], () => this.refreshAll());
this.emitter.off(['after-filtering'], () => this.linkFilters());
this.initialized = false;
}
}

View file

@ -1,37 +0,0 @@
const NOTIMPLEMENTED = 'Not implemented.';
export class Feature {
constructor(tf, feature) {
this.tf = tf;
this.feature = feature;
this.enabled = tf[feature];
this.config = tf.config();
this.initialized = false;
}
init() {
throw new Error(NOTIMPLEMENTED);
}
reset() {
this.enable();
this.init();
}
destroy() {
throw new Error(NOTIMPLEMENTED);
}
enable() {
this.enabled = true;
}
disable() {
this.enabled = false;
}
isEnabled() {
return this.enabled;
}
}

View file

@ -1,188 +1,224 @@
import {Feature} from './feature';
import Dom from '../dom';
import Types from '../types';
import Event from '../event';
import Str from '../string';
import {Feature} from '../feature';
import {createElm, removeElm, elm, tag} from '../dom';
import {addEvt, targetEvt} from '../event';
import {contains} from '../string';
import {NONE} from '../const';
import {
defaultsBool, defaultsStr, defaultsNb, defaultsArr
} from '../settings';
export class GridLayout extends Feature{
/**
* Grid layout, table with fixed headers
*/
export class GridLayout extends Feature {
/**
* Grid layout, table with fixed headers
* @param {Object} tf TableFilter instance
* Creates an instance of GridLayout
* @param {TableFilter} tf TableFilter instance
*/
constructor(tf){
super(tf, 'gridLayout');
constructor(tf) {
super(tf, GridLayout);
var f = this.config;
let f = this.config.grid_layout || {};
//defines grid width
this.gridWidth = f.grid_width || null;
//defines grid height
this.gridHeight = f.grid_height || null;
//defines css class for main container
this.gridMainContCssClass = f.grid_cont_css_class || 'grd_Cont';
//defines css class for div containing table
this.gridContCssClass = f.grid_tbl_cont_css_class || 'grd_tblCont';
//defines css class for div containing headers' table
this.gridHeadContCssClass = f.grid_tblHead_cont_css_class ||
'grd_headTblCont';
//defines css class for div containing rows counter, paging etc.
this.gridInfDivCssClass = f.grid_inf_grid_css_class || 'grd_inf';
//defines which row contains column headers
this.gridHeadRowIndex = f.grid_headers_row_index || 0;
//array of headers row indexes to be placed in header table
this.gridHeadRows = f.grid_headers_rows || [0];
//generate filters in table headers
this.gridEnableFilters = f.grid_enable_default_filters!==undefined ?
f.grid_enable_default_filters : true;
//default col width
this.gridDefaultColWidth = f.grid_default_col_width || '100px';
/**
* Grid-layout container width as CSS string
* @type {String}
*/
this.width = defaultsStr(f.width, null);
this.gridColElms = [];
/**
* Grid-layout container height as CSS string
* @type {String}
*/
this.height = defaultsStr(f.height, null);
//div containing grid elements if grid_layout true
this.prfxMainTblCont = 'gridCont_';
//div containing table if grid_layout true
this.prfxTblCont = 'tblCont_';
//div containing headers table if grid_layout true
this.prfxHeadTblCont = 'tblHeadCont_';
//headers' table if grid_layout true
this.prfxHeadTbl = 'tblHead_';
//id of td containing the filter if grid_layout true
/**
* Css class for main container element
* @type {String}
*/
this.mainContCssClass = defaultsStr(f.cont_css_class, 'grd_Cont');
/**
* Css class for body table container element
* @type {String}
*/
this.contCssClass = defaultsStr(f.tbl_cont_css_class, 'grd_tblCont');
/**
* Css class for headers table container element
* @type {String}
*/
this.headContCssClass = defaultsStr(f.tbl_head_css_class,
'grd_headTblCont');
/**
* Css class for toolbar container element (rows counter, paging etc.)
* @type {String}
*/
this.infDivCssClass = defaultsStr(f.inf_grid_css_class, 'grd_inf');
/**
* Index of the headers row, default: 0
* @type {Number}
*/
this.headRowIndex = defaultsNb(f.headers_row_index, 0);
/**
* Collection of the header row indexes to be moved into headers table
* @type {Array}
*/
this.headRows = defaultsArr(f.headers_rows, [0]);
/**
* Enable or disable column filters generation, default: true
* @type {Boolean}
*/
this.filters = defaultsBool(f.filters, true);
/**
* Enable or disable column headers, default: false
* @type {Boolean}
*/
this.noHeaders = Boolean(f.no_headers);
/**
* Grid-layout default column widht as CSS string
* @type {String}
*/
this.defaultColWidth = defaultsStr(f.default_col_width, '100px');
/**
* List of column elements
* @type {Array}
* @private
*/
this.colElms = [];
/**
* Prefix for grid-layout filter's cell ID
* @type {String}
* @private
*/
this.prfxGridFltTd = '_td_';
//id of th containing column header if grid_layout true
/**
* Prefix for grid-layout header's cell ID
* @type {String}
* @private
*/
this.prfxGridTh = 'tblHeadTh_';
this.sourceTblHtml = tf.tbl.outerHTML;
/**
* Mark-up of original HTML table
* @type {String}
* @private
*/
this.sourceTblHtml = tf.dom().outerHTML;
/**
* Indicates if working table has column elements
* @type {Boolean}
* @private
*/
this.tblHasColTag = tag(tf.dom(), 'col').length > 0 ? true : false;
/**
* Main container element
* @private
*/
this.tblMainCont = null;
/**
* Table container element
* @private
*/
this.tblCont = null;
/**
* Headers' table container element
* @private
*/
this.headTblCont = null;
/**
* Headers' table element
* @private
*/
this.headTbl = null;
// filters flag at TF level
tf.fltGrid = this.filters;
}
/**
* Generates a grid with fixed headers
* TODO: reduce size of init by extracting single purposed methods
*/
init(){
var tf = this.tf;
var f = this.config;
var tbl = tf.tbl;
init() {
let tf = this.tf;
let tbl = tf.dom();
if(this.initialized){
if (this.initialized) {
return;
}
tf.isExternalFlt = true;
// Override relevant TableFilter properties
this.setOverrides();
// default width of 100px if column widths not set
if(!tf.hasColWidths){
tf.colWidths = [];
for(var k=0; k<tf.nbCells; k++){
var colW,
cell = tbl.rows[this.gridHeadRowIndex].cells[k];
if(cell.width !== ''){
colW = cell.width;
} else if(cell.style.width !== ''){
colW = parseInt(cell.style.width, 10);
} else {
colW = this.gridDefaultColWidth;
}
tf.colWidths[k] = colW;
}
tf.hasColWidths = true;
}
tf.setColWidths(this.gridHeadRowIndex);
var tblW;//initial table width
if(tbl.width !== ''){
tblW = tbl.width;
}
else if(tbl.style.width !== ''){
tblW = parseInt(tbl.style.width, 10);
} else {
tblW = tbl.clientWidth;
}
// Assign default column widths
this.setDefaultColWidths();
//Main container: it will contain all the elements
this.tblMainCont = Dom.create('div',
['id', this.prfxMainTblCont + tf.id]);
this.tblMainCont.className = this.gridMainContCssClass;
if(this.gridWidth){
this.tblMainCont.style.width = this.gridWidth;
this.tblMainCont = this.createContainer(
'div', this.mainContCssClass);
if (this.width) {
this.tblMainCont.style.width = this.width;
}
tbl.parentNode.insertBefore(this.tblMainCont, tbl);
//Table container: div wrapping content table
this.tblCont = Dom.create('div',['id', this.prfxTblCont + tf.id]);
this.tblCont.className = this.gridContCssClass;
if(this.gridWidth){
if(this.gridWidth.indexOf('%') != -1){
this.tblCont.style.width = '100%';
} else {
this.tblCont.style.width = this.gridWidth;
}
}
if(this.gridHeight){
this.tblCont.style.height = this.gridHeight;
this.tblCont = this.createContainer('div', this.contCssClass);
this.setConfigWidth(this.tblCont);
if (this.height) {
this.tblCont.style.height = this.height;
}
tbl.parentNode.insertBefore(this.tblCont, tbl);
var t = Dom.remove(tbl);
let t = removeElm(tbl);
this.tblCont.appendChild(t);
//In case table width is expressed in %
if(tbl.style.width === ''){
tbl.style.width = (Str.contains('%', tblW) ?
if (tbl.style.width === '') {
let tblW = this.initialTableWidth();
tbl.style.width = (contains('%', tblW) ?
tbl.clientWidth : tblW) + 'px';
}
var d = Dom.remove(this.tblCont);
let d = removeElm(this.tblCont);
this.tblMainCont.appendChild(d);
//Headers table container: div wrapping headers table
this.headTblCont = Dom.create(
'div',['id', this.prfxHeadTblCont + tf.id]);
this.headTblCont.className = this.gridHeadContCssClass;
if(this.gridWidth){
if(this.gridWidth.indexOf('%') != -1){
this.headTblCont.style.width = '100%';
} else {
this.headTblCont.style.width = this.gridWidth;
}
}
this.headTblCont = this.createContainer(
'div', this.headContCssClass);
//Headers table
this.headTbl = Dom.create('table', ['id', this.prfxHeadTbl + tf.id]);
var tH = Dom.create('tHead');
this.headTbl = createElm('table');
let tH = createElm('tHead');
//1st row should be headers row, ids are added if not set
//Those ids are used by the sort feature
var hRow = tbl.rows[this.gridHeadRowIndex];
var sortTriggers = [];
for(var n=0; n<tf.nbCells; n++){
var c = hRow.cells[n];
var thId = c.getAttribute('id');
if(!thId || thId===''){
thId = this.prfxGridTh+n+'_'+tf.id;
c.setAttribute('id', thId);
}
sortTriggers.push(thId);
}
let hRow = tbl.rows[this.headRowIndex];
let sortTriggers = this.getSortTriggerIds(hRow);
//Filters row is created
var filtersRow = Dom.create('tr');
if(this.gridEnableFilters && tf.fltGrid){
tf.externalFltTgtIds = [];
for(var j=0; j<tf.nbCells; j++){
var fltTdId = tf.prfxFlt+j+ this.prfxGridFltTd +tf.id;
var cl = Dom.create(tf.fltCellTag, ['id', fltTdId]);
filtersRow.appendChild(cl);
tf.externalFltTgtIds[j] = fltTdId;
}
}
let filtersRow = this.createFiltersRow();
//Headers row are moved from content table to headers table
for(var i=0; i<this.gridHeadRows.length; i++){
var headRow = tbl.rows[this.gridHeadRows[0]];
tH.appendChild(headRow);
}
this.setHeadersRow(tH);
this.headTbl.appendChild(tH);
if(tf.filtersRowIndex === 0){
tH.insertBefore(filtersRow,hRow);
if (tf.filtersRowIndex === 0) {
tH.insertBefore(filtersRow, hRow);
} else {
tH.appendChild(filtersRow);
}
@ -191,40 +227,34 @@ export class GridLayout extends Feature{
this.tblCont.parentNode.insertBefore(this.headTblCont, this.tblCont);
//THead needs to be removed in content table for sort feature
var thead = Dom.tag(tbl, 'thead');
if(thead.length>0){
let thead = tag(tbl, 'thead');
if (thead.length > 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';
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
tf.setColWidths(0, this.headTbl);
tf.setColWidths(this.headTbl);
//Headers container width
// this.headTblCont.style.width = this.tblCont.clientWidth+'px';
tbl.style.width = '';
//
this.headTbl.style.width = tbl.clientWidth + 'px';
this.headTbl.style.width = tbl.style.width;
//
//scroll synchronisation
Event.add(this.tblCont, 'scroll', (evt)=> {
var elm = Event.target(evt);
var scrollLeft = elm.scrollLeft;
addEvt(this.tblCont, 'scroll', (evt) => {
let elm = targetEvt(evt);
let scrollLeft = elm.scrollLeft;
this.headTblCont.scrollLeft = scrollLeft;
//New pointerX calc taking into account scrollLeft
// if(!o.isPointerXOverwritten){
// try{
// o.Evt.pointerX = function(evt){
// var e = evt || global.event;
// var bdScrollLeft = tf_StandardBody().scrollLeft +
// let e = evt || global.event;
// let bdScrollLeft = tf_StandardBody().scrollLeft +
// scrollLeft;
// return (e.pageX + scrollLeft) ||
// (e.clientX + bdScrollLeft);
@ -236,87 +266,208 @@ export class GridLayout extends Feature{
// }
});
//Configure sort extension if any
var sort = (f.extensions || []).filter(function(itm){
return itm.name === 'sort';
});
if(sort.length === 1){
sort[0].async_sort = true;
sort[0].trigger_ids = sortTriggers;
// TODO: Trigger a custom event handled by sort extension
let sort = tf.extension('sort');
if (sort) {
sort.asyncSort = true;
sort.triggerIds = sortTriggers;
}
//Cols generation for all browsers excepted IE<=7
this.tblHasColTag = Dom.tag(tbl, 'col').length > 0 ? true : false;
//Col elements are enough to keep column widths after sorting and
//filtering
var createColTags = function(){
for(var k=(tf.nbCells-1); k>=0; k--){
var col = Dom.create('col', ['id', tf.id+'_col_'+k]);
tbl.insertBefore(col, tbl.firstChild);
col.style.width = tf.colWidths[k];
this.gridColElms[k] = col;
}
this.tblHasColTag = true;
};
this.setColumnElements();
if(!this.tblHasColTag){
createColTags.call(this);
} else {
var cols = Dom.tag(tbl, 'col');
for(var ii=0; ii<tf.nbCells; ii++){
cols[ii].setAttribute('id', tf.id+'_col_'+ii);
cols[ii].style.width = tf.colWidths[ii];
this.gridColElms.push(cols[ii]);
}
}
var afterColResizedFn = Types.isFn(f.on_after_col_resized) ?
f.on_after_col_resized : null;
f.on_after_col_resized = function(o, colIndex){
if(!colIndex){
return;
}
var w = o.crWColsRow.cells[colIndex].style.width;
var col = o.gridColElms[colIndex];
col.style.width = w;
var thCW = o.crWColsRow.cells[colIndex].clientWidth;
var tdCW = o.crWRowDataTbl.cells[colIndex].clientWidth;
if(thCW != tdCW){
o.headTbl.style.width = tbl.clientWidth+'px';
}
if(afterColResizedFn){
afterColResizedFn.call(null, o, colIndex);
}
};
if(tf.popupFilters){
filtersRow.style.display = 'none';
}
if(tbl.clientWidth !== this.headTbl.clientWidth){
tbl.style.width = this.headTbl.clientWidth+'px';
if (tf.popupFilters) {
filtersRow.style.display = NONE;
}
/** @inherited */
this.initialized = true;
}
/**
* Overrides TableFilter instance properties to adjust to grid layout mode
* @private
*/
setOverrides() {
let tf = this.tf;
tf.refRow = 0;
tf.headersRow = 0;
tf.filtersRowIndex = 1;
}
/**
* Set grid-layout default column widths if column widths are not defined
* @private
*/
setDefaultColWidths() {
let tf = this.tf;
if (tf.colWidths.length > 0) {
return;
}
tf.eachCol((k) => {
let colW;
let cell = tf.dom().rows[tf.getHeadersRowIndex()].cells[k];
if (cell.width !== '') {
colW = cell.width;
} else if (cell.style.width !== '') {
colW = parseInt(cell.style.width, 10);
} else {
colW = this.defaultColWidth;
}
tf.colWidths[k] = colW;
});
tf.setColWidths();
}
/**
* Initial table width
* @returns {Number}
* @private
*/
initialTableWidth() {
let tbl = this.tf.dom();
let width; //initial table width
if (tbl.width !== '') {
width = tbl.width;
}
else if (tbl.style.width !== '') {
width = tbl.style.width;
} else {
width = tbl.clientWidth;
}
return parseInt(width, 10);
}
/**
* Creates container element
* @param {String} tag Tag name
* @param {String} className Css class to assign to element
* @returns {DOMElement}
* @private
*/
createContainer(tag, className) {
let element = createElm(tag);
element.className = className;
return element;
}
/**
* Creates filters row with cells
* @returns {HTMLTableRowElement}
* @private
*/
createFiltersRow() {
let tf = this.tf;
let filtersRow = createElm('tr');
if (this.filters && tf.fltGrid) {
tf.externalFltIds = [];
tf.eachCol((j) => {
let fltTdId = `${tf.prfxFlt + j + this.prfxGridFltTd + tf.id}`;
let cl = createElm(tf.fltCellTag, ['id', fltTdId]);
filtersRow.appendChild(cl);
tf.externalFltIds[j] = fltTdId;
});
}
return filtersRow;
}
/**
* Generates column elements if necessary and assigns their widths
* @private
*/
setColumnElements() {
let tf = this.tf;
let cols = tag(tf.dom(), 'col');
this.tblHasColTag = cols.length > 0;
for (let k = (tf.getCellsNb() - 1); k >= 0; k--) {
let col;
if (!this.tblHasColTag) {
col = createElm('col');
tf.dom().insertBefore(col, tf.dom().firstChild);
} else {
col = cols[k];
}
col.style.width = tf.colWidths[k];
this.colElms[k] = col;
}
this.tblHasColTag = true;
}
/**
* Sets headers row in headers table
* @param {HTMLHeadElement} tableHead Table head element
* @private
*/
setHeadersRow(tableHead) {
if (this.noHeaders) {
// Handle table with no headers, assuming here headers do not
// exist
tableHead.appendChild(createElm('tr'));
} else {
// Headers row are moved from content table to headers table
for (let i = 0; i < this.headRows.length; i++) {
let row = this.tf.dom().rows[this.headRows[i]];
tableHead.appendChild(row);
}
}
}
/**
* Sets width defined in configuration to passed element
* @param {DOMElement} element DOM element
* @private
*/
setConfigWidth(element) {
if (!this.width) {
return;
}
if (this.width.indexOf('%') !== -1) {
element.style.width = '100%';
} else {
element.style.width = this.width;
}
}
/**
* Returns a list of header IDs used for specifing external sort triggers
* @param {HTMLTableRowElement} row DOM row element
* @returns {Array} List of IDs
* @private
*/
getSortTriggerIds(row) {
let tf = this.tf;
let sortTriggers = [];
tf.eachCol((n) => {
let c = row.cells[n];
let thId = c.getAttribute('id');
if (!thId || thId === '') {
thId = `${this.prfxGridTh + n}_${tf.id}`;
c.setAttribute('id', thId);
}
sortTriggers.push(thId);
});
return sortTriggers;
}
/**
* Removes the grid layout
*/
destroy(){
var tf = this.tf;
var tbl = tf.tbl;
destroy() {
let tf = this.tf;
let tbl = tf.dom();
if(!this.initialized){
if (!this.initialized) {
return;
}
var t = Dom.remove(tbl);
let t = removeElm(tbl);
this.tblMainCont.parentNode.insertBefore(t, this.tblMainCont);
Dom.remove(this.tblMainCont);
removeElm(this.tblMainCont);
this.tblMainCont = null;
this.headTblCont = null;
@ -325,7 +476,7 @@ export class GridLayout extends Feature{
tbl.outerHTML = this.sourceTblHtml;
//needed to keep reference of table element for future usage
this.tf.tbl = t;
this.tf.tbl = elm(tf.id);
this.initialized = false;
}

126
src/modules/hash.js Normal file
View file

@ -0,0 +1,126 @@
import {addEvt, removeEvt} from '../event';
import {root} from '../root';
const JSON = root.JSON;
const location = root.location;
const decodeURIComponent = root.decodeURIComponent;
const encodeURIComponent = root.encodeURIComponent;
/**
* Checks if browser has onhashchange event
*/
export const hasHashChange = () => {
let docMode = root.documentMode;
return ('onhashchange' in root) && (docMode === undefined || docMode > 7);
};
/**
* Manages state via URL hash changes
*
* @export
* @class Hash
*/
export class Hash {
/**
* Creates an instance of Hash
*
* @param {State} state Instance of State
*/
constructor(state) {
/**
* State object
* @type {State}
*/
this.state = state;
/**
* Cached URL hash
* @type {String} Hash string
* @private
*/
this.lastHash = null;
/**
* Application event emitter instance
* @type {Emitter}
*/
this.emitter = state.emitter;
/**
* Bound sync wrapper for future use
* @private
*/
this.boundSync = null;
}
/**
* Initializes the Hash object
*/
init() {
if (!hasHashChange()) {
return;
}
this.lastHash = location.hash;
//Store a bound sync wrapper
this.boundSync = this.sync.bind(this);
this.emitter.on(['state-changed'], (tf, state) => this.update(state));
this.emitter.on(['initialized'], this.boundSync);
addEvt(root, 'hashchange', this.boundSync);
}
/**
* Updates the URL hash based on a state change
*
* @param {State} state Instance of State
*/
update(state) {
let hash = `#${encodeURIComponent(JSON.stringify(state))}`;
if (this.lastHash === hash) {
return;
}
location.hash = hash;
this.lastHash = hash;
}
/**
* Converts a URL hash into a JSON object
*
* @param {String} hash URL hash fragment
* @returns {Object} JSON object
*/
parse(hash) {
if (hash.indexOf('#') === -1) {
return null;
}
hash = hash.substr(1);
return JSON.parse(decodeURIComponent(hash));
}
/**
* Applies current hash state to features
*/
sync() {
let state = this.parse(location.hash);
if (!state) {
return;
}
// override current state with persisted one and sync features
this.state.overrideAndSync(state);
}
/**
* Release Hash event subscriptions and clear fields
*/
destroy() {
this.emitter.off(['state-changed'], (tf, state) => this.update(state));
this.emitter.off(['initialized'], this.boundSync);
removeEvt(root, 'hashchange', this.boundSync);
this.state = null;
this.lastHash = null;
this.emitter = null;
}
}

View file

@ -1,153 +1,264 @@
import {Feature} from './feature';
import Dom from '../dom';
import Event from '../event';
import {Feature} from '../feature';
import {createElm, createText, elm, removeElm} from '../dom';
import {addEvt, targetEvt, removeEvt} from '../event';
import {NONE} from '../const';
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/' +
'4.-Filter-operators';
const WEBSITE_URL = 'http://koalyptus.github.io/TableFilter/';
'4.-Filter-operators';
const WEBSITE_URL = 'https://www.tablefilter.com/';
export class Help extends Feature{
/**
* Help UI component
*/
export class Help extends Feature {
/**
* Help UI component
* @param {Object} tf TableFilter instance
* Creates an instance of Help
* @param {TableFilter} tf TableFilter instance
*/
constructor(tf){
super(tf, 'help');
constructor(tf) {
super(tf, Help);
var f = this.config;
let f = this.config.help_instructions || {};
//id of custom container element for instructions
this.tgtId = f.help_instructions_target_id || null;
//id of custom container element for instructions
this.contTgtId = f.help_instructions_container_target_id ||
null;
//defines help text
this.instrText = f.help_instructions_text ?
f.help_instructions_text :
/**
* ID of main custom container element
* @type {String}
*/
this.tgtId = defaultsStr(f.target_id, null);
/**
* ID of custom container element for instructions
* @type {String}
*/
this.contTgtId = defaultsStr(f.container_target_id, null);
/**
* Instructions text (accepts HTML)
* @type {String}
*/
this.instrText = !isEmpty(f.text) ? f.text :
'Use the filters above each column to filter and limit table ' +
'data. Advanced searches can be performed by using the following ' +
'operators: <br /><b>&lt;</b>, <b>&lt;=</b>, <b>&gt;</b>, ' +
'<b>&gt;=</b>, <b>=</b>, <b>*</b>, <b>!</b>, <b>{</b>, <b>}</b>, ' +
'<b>||</b>,<b>&amp;&amp;</b>, <b>[empty]</b>, <b>[nonempty]</b>, ' +
'<b>rgx:</b><br/><a href="'+ WIKI_URL +'" target="_blank">' +
'<b>rgx:</b><br/><a href="' + WIKI_URL + '" target="_blank">' +
'Learn more</a><hr/>';
//defines help innerHtml
this.instrHtml = f.help_instructions_html || null;
//defines reset button text
this.btnText = f.help_instructions_btn_text || '?';
//defines reset button innerHtml
this.btnHtml = f.help_instructions_btn_html || null;
//defines css class for help button
this.btnCssClass = f.help_instructions_btn_css_class || 'helpBtn';
//defines css class for help container
this.contCssClass = f.help_instructions_container_css_class ||
'helpCont';
//help button element
/**
* Instructions HTML
* @type {String}
*/
this.instrHtml = defaultsStr(f.html, null);
/**
* Help button text ('?')
* @type {String}
*/
this.btnText = defaultsStr(f.btn_text, '?');
/**
* Custom help button HTML
* @type {String}
*/
this.btnHtml = defaultsStr(f.btn_html, null);
/**
* Css class for help button
* @type {String}
*/
this.btnCssClass = defaultsStr(f.btn_css_class, 'helpBtn');
/**
* Css class for help container element
* @type {String}
*/
this.contCssClass = defaultsStr(f.container_css_class, 'helpCont');
/**
* Button DOM element
* @type {DOMElement}
*/
this.btn = null;
//help content div
/**
* Help container DOM element
* @type {DOMElement}
*/
this.cont = null;
/**
* Adjust container left position when table's horizontal scroll is
* on, typically when `responsive` option is enabled.
* @type {Number}
* @defaultValue 25
*/
this.contAdjustLeftPosition =
defaultsNb(f.container_adjust_left_position, 25);
/**
* Bound mouseup wrapper
* @private
*/
this.boundMouseup = null;
/**
* Default HTML appended to instructions text
* @type {String}
*/
this.defaultHtml = '<div class="helpFooter"><h4>TableFilter ' +
'v'+ tf.version +'</h4>' +
'<a href="'+ WEBSITE_URL +'" target="_blank">'+ WEBSITE_URL +'</a>'+
'<br/><span>&copy;2015-'+ tf.year +' {AUTHOR}</span>' +
'v' + tf.version + '</h4>' + '<a href="' + WEBSITE_URL +
'" target="_blank">' + WEBSITE_URL + '</a>' +
'<br/><span>&copy;2015-' + tf.year + ' {AUTHOR}</span>' +
'<div align="center" style="margin-top:8px;">' +
'<a href="javascript:void(0);" class="close">Close</a></div></div>';
//id prefix for help elements
this.prfxHelpSpan = 'helpSpan_';
//id prefix for help elements
this.prfxHelpDiv = 'helpDiv_';
/**
* Default position in toolbar ('left'|'center'|'right')
* @type {String}
*/
this.toolbarPosition = defaultsStr(f.toolbar_position, RIGHT);
this.emitter.on(['init-help'], () => this.init());
}
init(){
if(this.initialized){
/**
* Mouse-up event handler handling popup auto-close behaviour
* @private
*/
onMouseup(evt) {
let targetElm = targetEvt(evt);
while (targetElm && targetElm !== this.cont && targetElm !== this.btn) {
targetElm = targetElm.parentNode;
}
if (targetElm !== this.cont && targetElm !== this.btn) {
this.toggle();
}
return;
}
/**
* Initialise Help instance
*/
init() {
if (this.initialized) {
return;
}
var tf = this.tf;
this.emitter.emit('initializing-feature', this, !isNull(this.tgtId));
var helpspan = Dom.create('span', ['id', this.prfxHelpSpan+tf.id]);
var helpdiv = Dom.create('div', ['id', this.prfxHelpDiv+tf.id]);
let tf = this.tf;
let btn = createElm('span');
let cont = createElm('div');
this.boundMouseup = this.onMouseup.bind(this);
//help button is added to defined element
if(!this.tgtId){
tf.setToolbar();
}
var targetEl = !this.tgtId ? tf.rDiv : Dom.id(this.tgtId);
targetEl.appendChild(helpspan);
let targetEl = !this.tgtId ?
tf.feature('toolbar').container(this.toolbarPosition) :
elm(this.tgtId);
targetEl.appendChild(btn);
var divContainer = !this.contTgtId ? helpspan : Dom.id(this.contTgtId);
let divContainer = !this.contTgtId ? btn : elm(this.contTgtId);
if(!this.btnHtml){
divContainer.appendChild(helpdiv);
var helplink = Dom.create('a', ['href', 'javascript:void(0);']);
if (!this.btnHtml) {
divContainer.appendChild(cont);
let helplink = createElm('a', ['href', 'javascript:void(0);']);
helplink.className = this.btnCssClass;
helplink.appendChild(Dom.text(this.btnText));
helpspan.appendChild(helplink);
Event.add(helplink, 'click', () => { this.toggle(); });
helplink.appendChild(createText(this.btnText));
btn.appendChild(helplink);
addEvt(helplink, 'click', () => this.toggle());
} else {
helpspan.innerHTML = this.btnHtml;
var helpEl = helpspan.firstChild;
Event.add(helpEl, 'click', () => { this.toggle(); });
divContainer.appendChild(helpdiv);
btn.innerHTML = this.btnHtml;
let helpEl = btn.firstChild;
addEvt(helpEl, 'click', () => this.toggle());
divContainer.appendChild(cont);
}
if(!this.instrHtml){
helpdiv.innerHTML = this.instrText;
helpdiv.className = this.contCssClass;
Event.add(helpdiv, 'dblclick', () => { this.toggle(); });
if (!this.instrHtml) {
cont.innerHTML = this.instrText;
cont.className = this.contCssClass;
} else {
if(this.contTgtId){
divContainer.appendChild(helpdiv);
if (this.contTgtId) {
divContainer.appendChild(cont);
}
helpdiv.innerHTML = this.instrHtml;
if(!this.contTgtId){
helpdiv.className = this.contCssClass;
Event.add(helpdiv, 'dblclick', () => { this.toggle(); });
cont.innerHTML = this.instrHtml;
if (!this.contTgtId) {
cont.className = this.contCssClass;
}
}
helpdiv.innerHTML += this.defaultHtml;
Event.add(helpdiv, 'click', () => { this.toggle(); });
cont.innerHTML += this.defaultHtml;
addEvt(cont, 'click', () => this.toggle());
this.cont = helpdiv;
this.btn = helpspan;
this.cont = cont;
this.btn = btn;
/** @inherited */
this.initialized = true;
this.emitter.emit('feature-initialized', this);
}
/**
* Toggle help pop-up
*/
toggle(){
// check only if explicitily set to false as in this case undefined
toggle() {
// check only if explicitily disabled as in this case undefined
// signifies the help feature is enabled by default
if(this.enabled === false){
if (!this.isEnabled()) {
return;
}
var divDisplay = this.cont.style.display;
if(divDisplay === '' || divDisplay === 'none'){
// ensure mouseup event handler is removed
removeEvt(root, 'mouseup', this.boundMouseup);
let divDisplay = this.cont.style.display;
if (divDisplay === '' || divDisplay === NONE) {
this.cont.style.display = 'inline';
// if table element has an horizontal scrollbar adjust container
// left position accordingly
if (this.tf.dom().scrollLeft > 0) {
this.cont.style.left = `${
this.btn.offsetLeft
- this.tf.dom().scrollLeft
+ this.contAdjustLeftPosition
}px`;
}
addEvt(root, 'mouseup', this.boundMouseup);
} else {
this.cont.style.display = 'none';
this.cont.style.display = NONE;
this.cont.style.left = '';
}
}
/**
* Remove help UI
*/
destroy(){
if(!this.initialized){
destroy() {
if (!this.initialized) {
return;
}
Dom.remove(this.btn);
removeElm(this.btn);
this.btn = null;
if(!this.cont){
return;
}
Dom.remove(this.cont);
removeElm(this.cont);
this.cont = null;
this.boundMouseup = null;
this.initialized = false;
}
}
// TODO: remove as soon as feature name is fixed
Help.meta = {alwaysInstantiate: true};

View file

@ -1,58 +1,94 @@
import Dom from '../dom';
import Str from '../string';
import {createText, createElm, getText} from '../dom';
import {isNull} from '../types';
import {rgxEsc} from '../string';
import {defaultsStr} from '../settings';
export class HighlightKeyword{
/**
* Highlight matched keywords upon filtering
*
* @export
* @class HighlightKeyword
*/
export class HighlightKeyword {
/**
* HighlightKeyword, highlight matched keyword
* @param {Object} tf TableFilter instance
* Creates an instance of HighlightKeyword
* @param {TableFilter} tf TableFilter instance
*/
constructor(tf) {
var f = tf.config();
//defines css class for highlighting
this.highlightCssClass = f.highlight_css_class || 'keyword';
this.highlightedNodes = [];
let f = tf.config();
/**
* Css class for highlighted term
* @type {String}
*/
this.highlightCssClass = defaultsStr(f.highlight_css_class, 'keyword');
/**
* TableFilter instance
* @type {TableFilter}
*/
this.tf = tf;
/**
* TableFilter's emitter instance
* @type {Emitter}
*/
this.emitter = tf.emitter;
}
/**
* highlight occurences of searched term in passed node
* @param {Node} node
* @param {String} word Searched term
* @param {String} cssClass Css class name
* Initializes HighlightKeyword instance
*/
highlight(node, word, cssClass){
init() {
this.emitter.on(
['before-filtering', 'destroy'],
() => this.unhighlightAll()
);
this.emitter.on(
['highlight-keyword'],
(tf, cell, term) => this._processTerm(cell, term)
);
}
/**
* Highlight occurences of searched term in passed node
* @param {Node} node
* @param {String} term Searched term
* @param {String} cssClass Css class name
*
* TODO: refactor this method
*/
highlight(node, term, cssClass) {
// Iterate into this nodes childNodes
if(node.hasChildNodes){
var children = node.childNodes;
for(var i=0; i<children.length; i++){
this.highlight(children[i], word, cssClass);
if (node.hasChildNodes) {
let children = node.childNodes;
for (let i = 0; i < children.length; i++) {
this.highlight(children[i], term, cssClass);
}
}
if(node.nodeType === 3){
var tempNodeVal = Str.lower(node.nodeValue);
var tempWordVal = Str.lower(word);
if(tempNodeVal.indexOf(tempWordVal) != -1){
var pn = node.parentNode;
if(pn && pn.className != cssClass){
// word not highlighted yet
var nv = node.nodeValue,
ni = tempNodeVal.indexOf(tempWordVal),
if (node.nodeType === 3) {
let nodeVal = node.nodeValue.toLowerCase();
let termIdx = nodeVal.indexOf(term.toLowerCase());
if (termIdx !== -1) {
let pn = node.parentNode;
if (pn && pn.className !== cssClass) {
// term not highlighted yet
let nv = node.nodeValue,
// Create a load of replacement nodes
before = Dom.text(nv.substr(0, ni)),
docWordVal = nv.substr(ni,word.length),
after = Dom.text(nv.substr(ni+word.length)),
hiwordtext = Dom.text(docWordVal),
hiword = Dom.create('span');
hiword.className = cssClass;
hiword.appendChild(hiwordtext);
pn.insertBefore(before,node);
pn.insertBefore(hiword,node);
pn.insertBefore(after,node);
before = createText(nv.substr(0, termIdx)),
value = nv.substr(termIdx, term.length),
after = createText(nv.substr(termIdx + term.length)),
text = createText(value),
container = createElm('span');
container.className = cssClass;
container.appendChild(text);
pn.insertBefore(before, node);
pn.insertBefore(container, node);
pn.insertBefore(after, node);
pn.removeChild(node);
this.highlightedNodes.push(hiword.firstChild);
}
}
}
@ -60,49 +96,85 @@ export class HighlightKeyword{
/**
* Removes highlight to nodes matching passed string
* @param {String} word
* @param {String} term
* @param {String} cssClass Css class to remove
*/
unhighlight(word, cssClass){
var arrRemove = [];
var highlightedNodes = this.highlightedNodes;
for(var i=0; i<highlightedNodes.length; i++){
var n = highlightedNodes[i];
if(!n){
continue;
unhighlight(term, cssClass) {
let highlightedNodes = this.tf.dom().querySelectorAll(`.${cssClass}`);
for (let i = 0; i < highlightedNodes.length; i++) {
let n = highlightedNodes[i];
let nodeVal = getText(n);
if (isNull(term) ||
nodeVal.toLowerCase().indexOf(term.toLowerCase()) !== -1) {
let parentNode = n.parentNode;
parentNode.replaceChild(createText(nodeVal), n);
parentNode.normalize();
}
var tempNodeVal = Str.lower(n.nodeValue),
tempWordVal = Str.lower(word);
if(tempNodeVal.indexOf(tempWordVal) !== -1){
var pn = n.parentNode;
if(pn && pn.className === cssClass){
var prevSib = pn.previousSibling,
nextSib = pn.nextSibling;
if(!prevSib || !nextSib){ continue; }
nextSib.nodeValue = prevSib.nodeValue + n.nodeValue +
nextSib.nodeValue;
prevSib.nodeValue = '';
n.nodeValue = '';
arrRemove.push(i);
}
}
}
for(var k=0; k<arrRemove.length; k++){
highlightedNodes.splice(arrRemove[k], 1);
}
}
/**
* Clear all occurrences of highlighted nodes
*/
unhighlightAll(){
if(!this.tf.highlightKeywords || !this.tf.searchArgs){
unhighlightAll() {
if (!this.tf.highlightKeywords) {
return;
}
for(var y=0; y<this.tf.searchArgs.length; y++){
this.unhighlight(
this.tf.searchArgs[y], this.highlightCssClass);
}
this.highlightedNodes = [];
this.unhighlight(null, this.highlightCssClass);
}
}
/** Remove feature */
destroy() {
this.emitter.off(
['before-filtering', 'destroy'],
() => this.unhighlightAll()
);
this.emitter.off(
['highlight-keyword'],
(tf, cell, term) => this._processTerm(cell, term)
);
}
/**
* Ensure filtering operators are handled before highlighting any match
* @param {any} Table cell to look searched term into
* @param {any} Searched termIdx
*/
_processTerm(cell, term) {
let tf = this.tf;
let reLk = new RegExp(rgxEsc(tf.lkOperator));
let reEq = new RegExp(tf.eqOperator);
let reSt = new RegExp(tf.stOperator);
let reEn = new RegExp(tf.enOperator);
let reLe = new RegExp(tf.leOperator);
let reGe = new RegExp(tf.geOperator);
let reL = new RegExp(tf.lwOperator);
let reG = new RegExp(tf.grOperator);
let reD = new RegExp(tf.dfOperator);
term = term
.replace(reLk, '')
.replace(reEq, '')
.replace(reSt, '')
.replace(reEn, '');
if (reLe.test(term) || reGe.test(term) || reL.test(term) ||
reG.test(term) || reD.test(term)) {
term = getText(cell);
}
if (term === '') {
return;
}
this.highlight(cell, term, this.highlightCssClass);
}
}
// TODO: remove as soon as feature name is fixed
HighlightKeyword.meta = {
name: 'highlightKeyword',
altName: 'highlightKeywords'
};

View file

@ -1,100 +1,183 @@
import {Feature} from './feature';
import Dom from '../dom';
import Types from '../types';
import {Feature} from '../feature';
import {createElm, createText, elm, removeElm} from '../dom';
import {EMPTY_FN} from '../types';
import {root} from '../root';
import {NONE} from '../const';
import {defaultsStr, defaultsFn} from '../settings';
var global = window;
const BEFORE_ACTION_EVENTS = [
'before-filtering',
'before-populating-filter',
'before-page-change',
'before-clearing-filters',
'before-page-length-change',
'before-reset-page',
'before-reset-page-length',
'before-loading-extensions',
'before-loading-themes'
];
export class Loader extends Feature{
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
*
* @export
* @class Loader
* @extends {Feature}
*/
export class Loader extends Feature {
/**
* Loading message/spinner
* @param {Object} tf TableFilter instance
* Creates an instance of Loader.
*
* @param {TableFilter} tf TableFilter instance
*/
constructor(tf){
super(tf, 'loader');
constructor(tf) {
super(tf, Loader);
// TableFilter configuration
var f = this.config;
let f = this.config.loader || {};
//id of container element
this.loaderTgtId = f.loader_target_id || null;
//div containing loader
this.loaderDiv = null;
//defines loader text
this.loaderText = f.loader_text || 'Loading...';
//defines loader innerHtml
this.loaderHtml = f.loader_html || null;
//defines css class for loader div
this.loaderCssClass = f.loader_css_class || 'loader';
//delay for hiding loader
this.loaderCloseDelay = 200;
//callback function before loader is displayed
this.onShowLoader = Types.isFn(f.on_show_loader) ?
f.on_show_loader : null;
//callback function after loader is closed
this.onHideLoader = Types.isFn(f.on_hide_loader) ?
f.on_hide_loader : null;
//loader div
this.prfxLoader = 'load_';
/**
* ID of custom container element
* @type {String}
*/
this.targetId = defaultsStr(f.target_id, null);
/**
* Loader container DOM element
* @type {DOMElement}
*/
this.cont = null;
/**
* Text displayed when indicator is visible
* @type {String}
*/
this.text = defaultsStr(f.text, 'Loading...');
/**
* Custom HTML injected in Loader's container element
* @type {String}
*/
this.html = defaultsStr(f.html, null);
/**
* Css class for Loader's container element
* @type {String}
*/
this.cssClass = defaultsStr(f.css_class, 'loader');
/**
* Close delay in milliseconds
* @type {Number}
*/
this.closeDelay = 250;
/**
* Callback fired when loader is displayed
* @type {Function}
*/
this.onShow = defaultsFn(f.on_show_loader, EMPTY_FN);
/**
* Callback fired when loader is closed
* @type {Function}
*/
this.onHide = defaultsFn(f.on_hide_loader, EMPTY_FN);
}
/**
* Initializes Loader instance
*/
init() {
if(this.initialized){
if (this.initialized) {
return;
}
var tf = this.tf;
let tf = this.tf;
let emitter = this.emitter;
var containerDiv = Dom.create('div', ['id', this.prfxLoader+tf.id]);
containerDiv.className = this.loaderCssClass;
let containerDiv = createElm('div');
containerDiv.className = this.cssClass;
var targetEl = !this.loaderTgtId ?
tf.tbl.parentNode : Dom.id(this.loaderTgtId);
if(!this.loaderTgtId){
targetEl.insertBefore(containerDiv, tf.tbl);
let targetEl = !this.targetId ?
tf.dom().parentNode : elm(this.targetId);
if (!this.targetId) {
targetEl.insertBefore(containerDiv, tf.dom());
} else {
targetEl.appendChild(containerDiv);
}
this.loaderDiv = containerDiv;
if(!this.loaderHtml){
this.loaderDiv.appendChild(Dom.text(this.loaderText));
this.cont = containerDiv;
if (!this.html) {
this.cont.appendChild(createText(this.text));
} else {
this.loaderDiv.innerHTML = this.loaderHtml;
this.cont.innerHTML = this.html;
}
this.show('none');
this.show(NONE);
// Subscribe to events
emitter.on(BEFORE_ACTION_EVENTS, () => this.show(''));
emitter.on(AFTER_ACTION_EVENTS, () => this.show(NONE));
/** @inherited */
this.initialized = true;
}
/**
* Shows or hides activity indicator
* @param {String} Two possible values: '' or 'none'
*/
show(p) {
if(!this.isEnabled() || this.loaderDiv.style.display === p){
if (!this.isEnabled()) {
return;
}
var displayLoader = () => {
if(!this.loaderDiv){
function displayLoader() {
if (!this.cont) {
return;
}
if(this.onShowLoader && p !== 'none'){
this.onShowLoader.call(null, this);
if (p !== NONE) {
this.onShow(this);
}
this.loaderDiv.style.display = p;
if(this.onHideLoader && p === 'none'){
this.onHideLoader.call(null, this);
this.cont.style.display = p;
if (p === NONE) {
this.onHide(this);
}
};
var t = p === 'none' ? this.loaderCloseDelay : 1;
global.setTimeout(displayLoader, t);
let t = p === NONE ? this.closeDelay : 1;
root.setTimeout(displayLoader.bind(this), t);
}
destroy(){
if(!this.initialized){
/**
* Removes feature
*/
destroy() {
if (!this.initialized) {
return;
}
Dom.remove(this.loaderDiv);
this.loaderDiv = null;
let emitter = this.emitter;
removeElm(this.cont);
this.cont = null;
// Unsubscribe to events
emitter.off(BEFORE_ACTION_EVENTS, () => this.show(''));
emitter.off(AFTER_ACTION_EVENTS, () => this.show(NONE));
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,120 +1,193 @@
import {Feature} from './feature';
import Dom from '../dom';
import Types from '../types';
import {Feature} from '../feature';
import {createElm, elm, removeElm} from '../dom';
import {isEmpty, EMPTY_FN} from '../types';
import {NONE} from '../const';
import {defaultsStr, defaultsFn} from '../settings';
export class NoResults extends Feature{
/**
* UI when filtering yields no matches
* @export
* @class NoResults
* @extends {Feature}
*/
export class NoResults extends Feature {
/**
* No results message UI component
* @param {Object} tf TableFilter instance
* Creates an instance of NoResults
* @param {TableFilter} tf TableFilter instance
*/
constructor(tf){
super(tf, 'noResults');
constructor(tf) {
super(tf, NoResults);
//configuration object
let f = this.config.no_results_message;
let f = this.config.no_results_message || {};
this.content = f.content || 'No results';
this.customContainer = f.custom_container || null;
this.customContainerId = f.custom_container_id || null;
this.isExternal = !Types.isEmpty(this.customContainer) ||
!Types.isEmpty(this.customContainerId);
this.cssClass = f.css_class || 'no-results';
/**
* Text (accepts HTML)
* @type {String}
*/
this.content = defaultsStr(f.content, 'No results');
/**
* Custom container DOM element
* @type {DOMElement}
*/
this.customContainer = defaultsStr(f.custom_container, null);
/**
* ID of custom container element
* @type {String}
*/
this.customContainerId = defaultsStr(f.custom_container_id, null);
/**
* Indicates if UI is contained in a external element
* @type {Boolean}
* @private
*/
this.isExternal = !isEmpty(this.customContainer) ||
!isEmpty(this.customContainerId);
/**
* Css class assigned to container element
* @type {String}
*/
this.cssClass = defaultsStr(f.css_class, 'no-results');
/**
* Stores container DOM element
* @type {DOMElement}
*/
this.cont = null;
//callback before message is displayed
this.onBeforeShowMsg = Types.isFn(f.on_before_show_msg) ?
f.on_before_show_msg : null;
//callback after message is displayed
this.onAfterShowMsg = Types.isFn(f.on_after_show_msg) ?
f.on_after_show_msg : null;
//callback before message is hidden
this.onBeforeHideMsg = Types.isFn(f.on_before_hide_msg) ?
f.on_before_hide_msg : null;
//callback after message is hidden
this.onAfterHideMsg = Types.isFn(f.on_after_hide_msg) ?
f.on_after_hide_msg : null;
/**
* Callback fired before the message is displayed
* @type {Function}
*/
this.onBeforeShow = defaultsFn(f.on_before_show_msg, EMPTY_FN);
this.prfxNoResults = 'nores_';
/**
* Callback fired after the message is displayed
* @type {Function}
*/
this.onAfterShow = defaultsFn(f.on_after_show_msg, EMPTY_FN);
/**
* Callback fired before the message is hidden
* @type {Function}
*/
this.onBeforeHide = defaultsFn(f.on_before_hide_msg, EMPTY_FN);
/**
* Callback fired after the message is hidden
* @type {Function}
*/
this.onAfterHide = defaultsFn(f.on_after_hide_msg, EMPTY_FN);
}
init(){
if(this.initialized){
/**
* Initializes NoResults instance
*/
init() {
if (this.initialized) {
return;
}
let tf = this.tf;
let target = this.customContainer || Dom.id(this.customContainerId) ||
tf.tbl;
let target = this.customContainer || elm(this.customContainerId) ||
tf.dom();
//container
let cont = Dom.create('div', ['id', this.prfxNoResults+tf.id]);
let cont = createElm('div');
cont.className = this.cssClass;
cont.innerHTML = this.content;
if(this.isExternal){
if (this.isExternal) {
target.appendChild(cont);
} else {
target.parentNode.insertBefore(cont, target.nextSibling);
}
this.cont = cont;
// subscribe to after-filtering event
this.emitter.on(
['initialized', 'after-filtering'],
() => this.toggle()
);
/** @inherited */
this.initialized = true;
this.hide();
}
show(){
if(!this.initialized || !this.isEnabled()){
/**
* Toggle no results message
*/
toggle() {
if (this.tf.getValidRowsNb() > 0) {
this.hide();
} else {
this.show();
}
}
/**
* Show no results message
*/
show() {
if (!this.initialized || !this.isEnabled()) {
return;
}
if(this.onBeforeShowMsg){
this.onBeforeShowMsg.call(null, this.tf, this);
}
this.onBeforeShow(this.tf, this);
this.setWidth();
this.cont.style.display = 'block';
if(this.onAfterShowMsg){
this.onAfterShowMsg.call(null, this.tf, this);
}
this.onAfterShow(this.tf, this);
}
hide(){
if(!this.initialized || !this.isEnabled()){
/**
* Hide no results message
*/
hide() {
if (!this.initialized || !this.isEnabled()) {
return;
}
this.onBeforeHide(this.tf, this);
if(this.onBeforeHideMsg){
this.onBeforeHideMsg.call(null, this.tf, this);
}
this.cont.style.display = NONE;
this.cont.style.display = 'none';
if(this.onBeforeHideMsg){
this.onBeforeHideMsg.call(null, this.tf, this);
}
this.onAfterHide(this.tf, this);
}
setWidth(){
if(!this.initialized || this.isExternal || !this.isEnabled()){
/**
* Sets no results container width
* @private
*/
setWidth() {
if (!this.initialized || this.isExternal || !this.isEnabled()) {
return;
}
if(this.tf.gridLayout){
let gridLayout = this.tf.feature('gridLayout');
this.cont.style.width = gridLayout.tblCont.clientWidth + 'px';
let tf = this.tf;
if (tf.gridLayout) {
let gridLayout = tf.feature('gridLayout');
this.cont.style.width = gridLayout.headTbl.clientWidth + 'px';
} else {
this.cont.style.width = this.tf.tbl.clientWidth + 'px';
this.cont.style.width = (tf.dom().tHead ?
tf.dom().tHead.clientWidth :
tf.dom().tBodies[0].clientWidth) + 'px';
}
}
destroy(){
if(!this.initialized){
/** Remove feature */
destroy() {
if (!this.initialized) {
return;
}
Dom.remove(this.cont);
removeElm(this.cont);
this.cont = null;
// unsubscribe to after-filtering event
this.emitter.off(['after-filtering'], () => this.toggle());
this.initialized = false;
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,124 +1,276 @@
import {Feature} from './feature';
import Types from '../types';
import Dom from '../dom';
import Event from '../event';
import {Feature} from '../feature';
import {isUndef, EMPTY_FN} from '../types';
import {createElm, removeElm} from '../dom';
import {addEvt, cancelEvt, stopEvt, targetEvt, removeEvt} from '../event';
import {INPUT, NONE, CHECKLIST, MULTIPLE} from '../const';
import {root} from '../root';
import {defaultsStr, defaultsBool, defaultsArr, defaultsFn} from '../settings';
export class PopupFilter extends Feature{
/**
* Pop-up filter component
* @export
* @class PopupFilter
* @extends {Feature}
*/
export class PopupFilter extends Feature {
/**
* Pop-up filter component
* @param {Object} tf TableFilter instance
* Creates an instance of PopupFilter
* @param {TableFilter} tf TableFilter instance
*/
constructor(tf){
super(tf, 'popupFilters');
constructor(tf) {
super(tf, PopupFilter);
// Configuration object
var f = this.config;
let f = this.config.popup_filters || {};
// Enable external filters behaviour
tf.isExternalFlt = true;
tf.externalFltTgtIds = [];
/**
* Close active popup filter upon filtering, enabled by default
* @type {Boolean}
*/
this.closeOnFiltering = defaultsBool(f.close_on_filtering, true);
//filter icon path
this.popUpImgFlt = f.popup_filters_image ||
tf.themesPath+'icn_filter.gif';
//active filter icon path
this.popUpImgFltActive = f.popup_filters_image_active ||
tf.themesPath+'icn_filterActive.gif';
this.popUpImgFltHtml = f.popup_filters_image_html ||
'<img src="'+ this.popUpImgFlt +'" alt="Column filter" />';
//defines css class for popup div containing filter
this.popUpDivCssClass = f.popup_div_css_class || 'popUpFilter';
//callback function before popup filtes is opened
this.onBeforePopUpOpen = Types.isFn(f.on_before_popup_filter_open) ?
f.on_before_popup_filter_open : null;
//callback function after popup filtes is opened
this.onAfterPopUpOpen = Types.isFn(f.on_after_popup_filter_open) ?
f.on_after_popup_filter_open : null;
//callback function before popup filtes is closed
this.onBeforePopUpClose =
Types.isFn(f.on_before_popup_filter_close) ?
f.on_before_popup_filter_close : null;
//callback function after popup filtes is closed
this.onAfterPopUpClose = Types.isFn(f.on_after_popup_filter_close) ?
f.on_after_popup_filter_close : null;
/**
* Filter icon path
* @type {String}
*/
this.iconPath = defaultsStr(f.image, tf.themesPath + 'icn_filter.gif');
//stores filters spans
this.popUpFltSpans = [];
//stores filters icons
this.popUpFltImgs = [];
//stores filters containers
this.popUpFltElms = this.popUpFltElmCache || [];
this.popUpFltAdjustToContainer = true;
/**
* Active filter icon path
* @type {string}
*/
this.activeIconPath = defaultsStr(f.image_active,
tf.themesPath + 'icn_filterActive.gif');
//id prefix for pop-up filter span
this.prfxPopUpSpan = 'popUpSpan_';
//id prefix for pop-up div containing filter
this.prfxPopUpDiv = 'popUpDiv_';
/**
* HTML for the filter icon
* @type {string}
*/
this.iconHtml = defaultsStr(f.image_html,
'<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
* @type {String}
*/
this.containerCssClass = defaultsStr(f.div_css_class, 'popUpFilter');
/**
* Ensure filter's container element width matches column width, enabled
* by default
* @type {Boolean}
*/
this.adjustToContainer = defaultsBool(f.adjust_to_container, true);
/**
* Callback fired before a popup filter is opened
* @type {Function}
*/
this.onBeforeOpen = defaultsFn(f.on_before_popup_filter_open, EMPTY_FN);
/**
* Callback fired after a popup filter is opened
* @type {Function}
*/
this.onAfterOpen = defaultsFn(f.on_after_popup_filter_open, EMPTY_FN);
/**
* Callback fired before a popup filter is closed
* @type {Function}
*/
this.onBeforeClose = defaultsFn(f.on_before_popup_filter_close,
EMPTY_FN);
/**
* Callback fired after a popup filter is closed
* @type {Function}
*/
this.onAfterClose = defaultsFn(f.on_after_popup_filter_close, EMPTY_FN);
/**
* Collection of filters spans
* @type {Array}
* @private
*/
this.fltSpans = [];
/**
* Collection of filters icons
* @type {Array}
* @private
*/
this.fltIcons = [];
/**
* Collection of filters icons cached after pop-up filters are removed
* @type {Array}
* @private
*/
this.filtersCache = null;
/**
* Collection of filters containers
* @type {Array}
* @private
*/
this.fltElms = defaultsArr(this.filtersCache, []);
/**
* Prefix for pop-up filter container ID
* @type {String}
* @private
*/
this.prfxDiv = 'popup_';
/**
* Column index of popup filter currently active
* @type {Number}
* @private
*/
this.activeFilterIdx = -1;
}
onClick(e){
var evt = e || global.event,
elm = evt.target.parentNode,
colIndex = parseInt(elm.getAttribute('ci'), 10);
/**
* Click event handler for pop-up filter icon
* @private
*/
onClick(evt) {
let elm = targetEvt(evt).parentNode;
let colIndex = parseInt(elm.getAttribute('ci'), 10);
this.closeAll(colIndex);
this.toggle(colIndex);
if(this.popUpFltAdjustToContainer){
var popUpDiv = this.popUpFltElms[colIndex],
if (this.adjustToContainer) {
let cont = this.fltElms[colIndex],
header = this.tf.getHeaderElement(colIndex),
headerWidth = header.clientWidth * 0.95;
popUpDiv.style.width = parseInt(headerWidth, 10) + 'px';
cont.style.width = parseInt(headerWidth, 10) + 'px';
}
Event.cancel(evt);
Event.stop(evt);
cancelEvt(evt);
stopEvt(evt);
}
/**
* Mouse-up event handler handling popup filter auto-close behaviour
* @private
*/
onMouseup(evt) {
if (this.activeFilterIdx === -1) {
return;
}
let targetElm = targetEvt(evt);
let activeFlt = this.fltElms[this.activeFilterIdx];
let icon = this.fltIcons[this.activeFilterIdx];
if (icon === targetElm) {
return;
}
while (targetElm && targetElm !== activeFlt) {
targetElm = targetElm.parentNode;
}
if (targetElm !== activeFlt) {
this.close(this.activeFilterIdx);
}
return;
}
/**
* Initialize DOM elements
*/
init(){
if(this.initialized){
init() {
if (this.initialized) {
return;
}
var tf = this.tf;
for(var i=0; i<tf.nbCells; i++){
if(tf.getFilterType(i) === tf.fltTypeNone){
continue;
}
var popUpSpan = Dom.create(
'span',
['id', this.prfxPopUpSpan+tf.id+'_'+i],
['ci', i]
);
popUpSpan.innerHTML = this.popUpImgFltHtml;
var header = tf.getHeaderElement(i);
header.appendChild(popUpSpan);
Event.add(popUpSpan, 'click', (evt) => { this.onClick(evt); });
this.popUpFltSpans[i] = popUpSpan;
this.popUpFltImgs[i] = popUpSpan.firstChild;
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
// TODO: Because of the filters row generation, headers row index needs
// adjusting: prevent useless row generation
if (tf.headersRow <= 1 && isNaN(tf.config().headers_row_index)) {
tf.headersRow = 0;
}
// Adjust headers row index for grid-layout mode
// TODO: Because of the filters row generation, headers row index needs
// adjusting: prevent useless row generation
if (tf.gridLayout) {
tf.headersRow--;
this.buildIcons();
}
// subscribe to events
this.emitter.on(['before-filtering'], () => this.setIconsState());
this.emitter.on(['after-filtering'], () => this.closeAll());
this.emitter.on(['cell-processed'],
(tf, cellIndex) => this.changeState(cellIndex, true));
this.emitter.on(['filters-row-inserted'], () => this.buildIcons());
this.emitter.on(['before-filter-init'],
(tf, colIndex) => this.build(colIndex));
/** @inherited */
this.initialized = true;
}
/**
* Reset previously destroyed feature
*/
reset(){
reset() {
this.enable();
this.init();
this.buildIcons();
this.buildAll();
}
/**
* Build all filters icons
*/
buildIcons() {
let tf = this.tf;
// TODO: Because of the filters row generation, headers row index needs
// adjusting: prevent useless row generation
tf.headersRow++;
tf.eachCol(
(i) => {
let icon = createElm('span', ['ci', i]);
icon.innerHTML = this.iconHtml;
let header = tf.getHeaderElement(i);
header.appendChild(icon);
addEvt(icon, 'click', (evt) => this.onClick(evt));
this.fltSpans[i] = icon;
this.fltIcons[i] = icon.firstChild;
},
// continue condition function
(i) => tf.getFilterType(i) === NONE
);
}
/**
* Build all pop-up filters elements
*/
buildAll(){
for(var i=0; i<this.popUpFltElmCache.length; i++){
this.build(i, this.popUpFltElmCache[i]);
buildAll() {
for (let i = 0; i < this.filtersCache.length; i++) {
this.build(i, this.filtersCache[i]);
}
}
@ -127,69 +279,106 @@ export class PopupFilter extends Feature{
* @param {Number} colIndex Column index
* @param {Object} div Optional container DOM element
*/
build(colIndex, div){
var tf = this.tf;
var popUpDiv = !div ?
Dom.create('div', ['id', this.prfxPopUpDiv+tf.id+'_'+colIndex]) :
div;
popUpDiv.className = this.popUpDivCssClass;
tf.externalFltTgtIds.push(popUpDiv.id);
var header = tf.getHeaderElement(colIndex);
header.insertBefore(popUpDiv, header.firstChild);
Event.add(popUpDiv, 'click', (evt) => { Event.stop(evt); });
this.popUpFltElms[colIndex] = popUpDiv;
build(colIndex, div) {
let tf = this.tf;
let contId = `${this.prfxDiv}${tf.id}_${colIndex}`;
let placeholder = createElm('div', ['class', this.placeholderCssClass]);
let cont = div ||
createElm('div', ['id', contId], ['class', this.containerCssClass]);
tf.externalFltIds[colIndex] = cont.id;
placeholder.appendChild(cont);
let header = tf.getHeaderElement(colIndex);
header.insertBefore(placeholder, header.firstChild);
addEvt(cont, 'click', (evt) => stopEvt(evt));
this.fltElms[colIndex] = cont;
}
/**
* Toogle visibility of specified filter
* Toggle visibility of specified filter
* @param {Number} colIndex Column index
*/
toggle(colIndex){
var tf = this.tf,
popUpFltElm = this.popUpFltElms[colIndex];
if(popUpFltElm.style.display === 'none' ||
popUpFltElm.style.display === ''){
if(this.onBeforePopUpOpen){
this.onBeforePopUpOpen.call(
null, this, this.popUpFltElms[colIndex], colIndex);
}
popUpFltElm.style.display = 'block';
if(tf.getFilterType(colIndex) === tf.fltTypeInp){
var flt = tf.getFilterElement(colIndex);
if(flt){
flt.focus();
}
}
if(this.onAfterPopUpOpen){
this.onAfterPopUpOpen.call(
null, this, this.popUpFltElms[colIndex], colIndex);
}
toggle(colIndex) {
if (!this.isOpen(colIndex)) {
this.open(colIndex);
} else {
if(this.onBeforePopUpClose){
this.onBeforePopUpClose.call(
null, this, this.popUpFltElms[colIndex], colIndex);
}
popUpFltElm.style.display = 'none';
if(this.onAfterPopUpClose){
this.onAfterPopUpClose.call(
null, this, this.popUpFltElms[colIndex], colIndex);
this.close(colIndex);
}
}
/**
* Open popup filter of specified column
* @param {Number} colIndex Column index
*/
open(colIndex) {
let tf = this.tf,
container = this.fltElms[colIndex];
this.onBeforeOpen(this, container, colIndex);
container.style.display = 'block';
this.activeFilterIdx = colIndex;
addEvt(root, 'mouseup', (evt) => this.onMouseup(evt));
if (tf.getFilterType(colIndex) === INPUT) {
let flt = tf.getFilterElement(colIndex);
if (flt) {
flt.focus();
}
}
this.onAfterOpen(this, container, colIndex);
}
/**
* Close popup filter of specified column
* @param {Number} colIndex Column index
*/
close(colIndex) {
let container = this.fltElms[colIndex];
this.onBeforeClose(this, container, colIndex);
container.style.display = NONE;
if (this.activeFilterIdx === colIndex) {
this.activeFilterIdx = -1;
}
removeEvt(root, 'mouseup', (evt) => this.onMouseup(evt));
this.onAfterClose(this, container, colIndex);
}
/**
* Check if popup filter for specified column is open
* @param {Number} colIndex Column index
* @returns {Boolean}
*/
isOpen(colIndex) {
return this.fltElms[colIndex].style.display === 'block';
}
/**
* Close all filters excepted for the specified one if any
* @param {Number} exceptIdx Column index of the filter to not close
*/
closeAll(exceptIdx){
for(var i=0; i<this.popUpFltElms.length; i++){
if(i === exceptIdx){
closeAll(exceptIdx) {
// Do not close filters only if argument is undefined and close on
// filtering option is disabled
if (isUndef(exceptIdx) && !this.closeOnFiltering) {
return;
}
for (let i = 0; i < this.fltElms.length; i++) {
if (i === exceptIdx) {
continue;
}
var popUpFltElm = this.popUpFltElms[i];
if(popUpFltElm){
popUpFltElm.style.display = 'none';
let fltType = this.tf.getFilterType(i);
let isMultipleFilter =
(fltType === CHECKLIST || fltType === MULTIPLE);
// Always hide all single selection filter types but hide multiple
// selection filter types only if index set
if (!isMultipleFilter || !isUndef(exceptIdx)) {
this.close(i);
}
}
}
@ -197,55 +386,76 @@ export class PopupFilter extends Feature{
/**
* Build all the icons representing the pop-up filters
*/
buildIcons(){
for(var i=0; i<this.popUpFltImgs.length; i++){
this.buildIcon(i, false);
setIconsState() {
for (let i = 0; i < this.fltIcons.length; i++) {
this.changeState(i, false);
}
}
/**
* Build specified icon
* Apply specified icon state
* @param {Number} colIndex Column index
* @param {Boolean} active Apply active state
*/
buildIcon(colIndex, active){
if(this.popUpFltImgs[colIndex]){
this.popUpFltImgs[colIndex].src = active ?
this.popUpImgFltActive : this.popUpImgFlt;
changeState(colIndex, active) {
let icon = this.fltIcons[colIndex];
if (icon) {
icon.src = active ? this.activeIconPath : this.iconPath;
}
}
/**
* Remove pop-up filters
*/
destroy(){
if(!this.initialized){
destroy() {
if (!this.initialized) {
return;
}
this.popUpFltElmCache = [];
for(var i=0; i<this.popUpFltElms.length; i++){
var popUpFltElm = this.popUpFltElms[i],
popUpFltSpan = this.popUpFltSpans[i],
popUpFltImg = this.popUpFltImgs[i];
if(popUpFltElm){
Dom.remove(popUpFltElm);
this.popUpFltElmCache[i] = popUpFltElm;
this.filtersCache = [];
for (let i = 0; i < this.fltElms.length; i++) {
let container = this.fltElms[i],
placeholder = container.parentNode,
icon = this.fltSpans[i],
iconImg = this.fltIcons[i];
if (container) {
removeElm(container);
this.filtersCache[i] = container;
}
popUpFltElm = null;
if(popUpFltSpan){
Dom.remove(popUpFltSpan);
container = null;
if (placeholder) {
removeElm(placeholder);
}
popUpFltSpan = null;
if(popUpFltImg){
Dom.remove(popUpFltImg);
placeholder = null;
if (icon) {
removeElm(icon);
}
popUpFltImg = null;
icon = null;
if (iconImg) {
removeElm(iconImg);
}
iconImg = null;
}
this.popUpFltElms = [];
this.popUpFltSpans = [];
this.popUpFltImgs = [];
this.fltElms = [];
this.fltSpans = [];
this.fltIcons = [];
// TODO: expose an API to handle external filter IDs
this.tf.externalFltIds = [];
// unsubscribe to events
this.emitter.off(['before-filtering'], () => this.setIconsState());
this.emitter.off(['after-filtering'], () => this.closeAll());
this.emitter.off(['cell-processed'],
(tf, cellIndex) => this.changeState(cellIndex, true));
this.emitter.off(['filters-row-inserted'], () => this.buildIcons());
this.emitter.off(['before-filter-init'],
(tf, colIndex) => this.build(colIndex));
this.initialized = false;
}
}
// TODO: remove as soon as feature name is fixed
PopupFilter.meta = {altName: 'popupFilters'};

View file

@ -1,137 +1,207 @@
import {Feature} from './feature';
import Dom from '../dom';
import Types from '../types';
import {Feature} from '../feature';
import {createElm, createText, elm, removeElm} from '../dom';
import {EMPTY_FN, isNull} from '../types';
import {defaultsStr, defaultsFn} from '../settings';
import {LEFT} from './toolbar';
export class RowsCounter extends Feature{
/**
* Rows counter UI component
* @export
* @class RowsCounter
* @extends {Feature}
*/
export class RowsCounter extends Feature {
/**
* Rows counter
* @param {Object} tf TableFilter instance
* Creates an instance of RowsCounter
* @param {TableFilter} tf TableFilter instance
*/
constructor(tf){
super(tf, 'rowsCounter');
constructor(tf) {
super(tf, RowsCounter);
// TableFilter configuration
var f = this.config;
let f = this.config.rows_counter || {};
//id of custom container element
this.rowsCounterTgtId = f.rows_counter_target_id || null;
//element containing tot nb rows
this.rowsCounterDiv = null;
//element containing tot nb rows label
this.rowsCounterSpan = null;
//defines rows counter text
this.rowsCounterText = f.rows_counter_text || 'Rows: ';
this.fromToTextSeparator = f.from_to_text_separator || '-';
this.overText = f.over_text || ' / ';
//defines css class rows counter
this.totRowsCssClass = f.tot_rows_css_class || 'tot';
//rows counter div
this.prfxCounter = 'counter_';
//nb displayed rows label
this.prfxTotRows = 'totrows_span_';
//label preceding nb rows label
this.prfxTotRowsTxt = 'totRowsTextSpan_';
//callback raised before counter is refreshed
this.onBeforeRefreshCounter = Types.isFn(f.on_before_refresh_counter) ?
f.on_before_refresh_counter : null;
//callback raised after counter is refreshed
this.onAfterRefreshCounter = Types.isFn(f.on_after_refresh_counter) ?
f.on_after_refresh_counter : null;
/**
* ID of custom container element
* @type {String}
*/
this.targetId = defaultsStr(f.target_id, null);
/**
* Container DOM element
* @type {DOMElement}
* @private
*/
this.container = null;
/**
* Container DOM element for label displaying the total number of rows
* @type {DOMElement}
* @private
*/
this.label = null;
/**
* Text preceding the total number of rows
* @type {String}
*/
this.text = defaultsStr(f.text, 'Rows: ');
/**
* Separator symbol appearing between the first and last visible rows of
* current page when paging is enabled. ie: Rows: 31-40 / 70
* @type {String}
*/
this.fromToTextSeparator = defaultsStr(f.separator, '-');
/**
* Separator symbol appearing between the first and last visible rows of
* current page and the total number of filterable rows when paging is
* enabled. ie: Rows: 31-40 / 70
* @type {String}
*/
this.overText = defaultsStr(f.over_text, ' / ');
/**
* Css class for container element
* @type {String}
*/
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
* @type {Function}
*/
this.onBeforeRefreshCounter = defaultsFn(f.on_before_refresh_counter,
EMPTY_FN);
/**
* Callback fired after the counter is refreshed
* @type {Function}
*/
this.onAfterRefreshCounter = defaultsFn(f.on_after_refresh_counter,
EMPTY_FN);
}
init(){
if(this.initialized){
/**
* Initializes RowsCounter instance
*/
init() {
if (this.initialized) {
return;
}
var tf = this.tf;
this.emitter.emit('initializing-feature', this, !isNull(this.targetId));
let tf = this.tf;
//rows counter container
var countDiv = Dom.create('div', ['id', this.prfxCounter+tf.id]);
countDiv.className = this.totRowsCssClass;
let countDiv = createElm('div');
countDiv.className = this.cssClass;
//rows counter label
var countSpan = Dom.create('span', ['id', this.prfxTotRows+tf.id]);
var countText = Dom.create('span', ['id', this.prfxTotRowsTxt+tf.id]);
countText.appendChild(Dom.text(this.rowsCounterText));
let countSpan = createElm('span');
let countText = createElm('span');
countText.appendChild(createText(this.text));
// counter is added to defined element
if(!this.rowsCounterTgtId){
tf.setToolbar();
}
var targetEl = !this.rowsCounterTgtId ?
tf.lDiv : Dom.id( this.rowsCounterTgtId );
let targetEl = !this.targetId ?
tf.feature('toolbar').container(this.toolbarPosition) :
elm(this.targetId);
//default container: 'lDiv'
if(!this.rowsCounterTgtId){
if (!this.targetId) {
countDiv.appendChild(countText);
countDiv.appendChild(countSpan);
targetEl.appendChild(countDiv);
}
else{
} else {
//custom container, no need to append statusDiv
targetEl.appendChild(countText);
targetEl.appendChild(countSpan);
}
this.rowsCounterDiv = countDiv;
this.rowsCounterSpan = countSpan;
this.container = countDiv;
this.label = countSpan;
// subscribe to events
this.emitter.on(['after-filtering', 'grouped-by-page'],
() => this.refresh(tf.getValidRowsNb()));
this.emitter.on(['rows-changed'], () => this.refresh());
/** @inherited */
this.initialized = true;
this.refresh();
this.emitter.emit('feature-initialized', this);
}
refresh(p){
if(!this.initialized || !this.isEnabled()){
/**
* Refreshes the rows counter
* @param {Number} p Optional parameter the total number of rows to display
*/
refresh(p) {
if (!this.initialized || !this.isEnabled()) {
return;
}
var tf = this.tf;
let tf = this.tf;
if(this.onBeforeRefreshCounter){
this.onBeforeRefreshCounter.call(null, tf, this.rowsCounterSpan);
}
this.onBeforeRefreshCounter(tf, this.label);
var totTxt;
if(!tf.paging){
if(p && p !== ''){
let totTxt;
if (!tf.paging) {
if (p && p !== '') {
totTxt = p;
} else{
totTxt = tf.nbFilterableRows - tf.nbHiddenRows;
} else {
totTxt = tf.getFilterableRowsNb() - tf.nbHiddenRows;
}
} else {
var paging = tf.feature('paging');
if(paging){
let paging = tf.feature('paging');
if (paging) {
let nbValidRows = tf.getValidRowsNb();
//paging start row
var paging_start_row = parseInt(paging.startPagingRow, 10) +
((tf.nbVisibleRows>0) ? 1 : 0);
var paging_end_row = (paging_start_row+paging.pagingLength)-1 <=
tf.nbVisibleRows ?
paging_start_row+paging.pagingLength-1 :
tf.nbVisibleRows;
totTxt = paging_start_row + this.fromToTextSeparator +
paging_end_row + this.overText + tf.nbVisibleRows;
let pagingStartRow = parseInt(paging.startPagingRow, 10) +
((nbValidRows > 0) ? 1 : 0);
let pagingEndRow =
(pagingStartRow + paging.pageLength) - 1 <=
nbValidRows ?
pagingStartRow + paging.pageLength - 1 :
nbValidRows;
totTxt = pagingStartRow + this.fromToTextSeparator +
pagingEndRow + this.overText + nbValidRows;
}
}
this.rowsCounterSpan.innerHTML = totTxt;
if(this.onAfterRefreshCounter){
this.onAfterRefreshCounter.call(
null, tf, this.rowsCounterSpan, totTxt);
}
this.label.innerHTML = totTxt;
this.onAfterRefreshCounter(tf, this.label, totTxt);
}
destroy(){
if(!this.initialized){
/**
* Remove feature
*/
destroy() {
if (!this.initialized) {
return;
}
if(!this.rowsCounterTgtId && this.rowsCounterDiv){
Dom.remove(this.rowsCounterDiv);
if (!this.targetId && this.container) {
removeElm(this.container);
} else {
Dom.id(this.rowsCounterTgtId).innerHTML = '';
elm(this.targetId).innerHTML = '';
}
this.rowsCounterSpan = null;
this.rowsCounterDiv = null;
this.label = null;
this.container = null;
// unsubscribe to events
this.emitter.off(['after-filtering', 'grouped-by-page'],
() => this.refresh(tf.getValidRowsNb()));
this.emitter.off(['rows-changed'], () => this.refresh());
this.initialized = false;
}
}

545
src/modules/state.js Normal file
View file

@ -0,0 +1,545 @@
import {Feature} from '../feature';
import {Hash} from './hash';
import {Storage} from './storage';
import {isEmpty} from '../string';
import {isArray, isNull, isString, isUndef} from '../types';
import {defaultsBool, defaultsNb} from '../settings';
/**
* Features state object persistable with localStorage, cookie or URL hash
*
* @export
* @class State
* @extends {Feature}
*/
export class State extends Feature {
/**
* Creates an instance of State
* @param {TableFilter} tf TableFilter instance
*/
constructor(tf) {
super(tf, State);
let cfg = this.config.state || {};
/**
* Determines whether state is persisted with URL hash
* @type {Boolean}
*/
this.enableHash = cfg === true ||
(isArray(cfg.types) && cfg.types.indexOf('hash') !== -1);
/**
* Determines whether state is persisted with localStorage
* @type {Boolean}
*/
this.enableLocalStorage = isArray(cfg.types) &&
cfg.types.indexOf('local_storage') !== -1;
/**
* Determines whether state is persisted with localStorage
* @type {Boolean}
*/
this.enableCookie = isArray(cfg.types) &&
cfg.types.indexOf('cookie') !== -1;
/**
* Persist filters values, enabled by default
* @type {Boolean}
*/
this.persistFilters = defaultsBool(cfg.filters, true);
/**
* Persist current page number when paging is enabled
* @type {Boolean}
*/
this.persistPageNumber = Boolean(cfg.page_number);
/**
* Persist page length when paging is enabled
* @type {Boolean}
*/
this.persistPageLength = Boolean(cfg.page_length);
/**
* Persist column sorting
* @type {Boolean}
*/
this.persistSort = Boolean(cfg.sort);
/**
* Persist columns visibility
* @type {Boolean}
*/
this.persistColsVisibility = Boolean(cfg.columns_visibility);
/**
* Persist filters row visibility
* @type {Boolean}
*/
this.persistFiltersVisibility = Boolean(cfg.filters_visibility);
/**
* Cookie duration in hours
* @type {Boolean}
*/
this.cookieDuration = defaultsNb(parseInt(cfg.cookie_duration, 10),
87600);
/**
* Enable Storage if localStorage or cookie is required
* @type {Boolean}
* @private
*/
this.enableStorage = this.enableLocalStorage || this.enableCookie;
/**
* Storage instance if storage is required
* @type {Storage}
* @private
*/
this.storage = null;
/**
* Hash instance if URL hash is required
* @type {Boolean}
* @private
*/
this.hash = null;
/**
* Current page number
* @type {Number}
* @private
*/
this.pageNb = null;
/**
* Current page length
* @type {Number}
* @private
*/
this.pageLength = null;
/**
* Current column sorting
* @type {Object}
* @private
*/
this.sort = null;
/**
* Current hidden columns
* @type {Object}
* @private
*/
this.hiddenCols = null;
/**
* Filters row visibility
* @type {Boolean}
* @private
*/
this.filtersVisibility = null;
/**
* State object
* @type {Object}
* @private
*/
this.state = {};
/**
* Prefix for column ID
* @type {String}
* @private
*/
this.prfxCol = 'col_';
/**
* Prefix for page number ID
* @type {String}
* @private
*/
this.pageNbKey = 'page';
/**
* Prefix for page length ID
* @type {String}
* @private
*/
this.pageLengthKey = 'page_length';
/**
* Prefix for filters visibility ID
* @type {String}
* @private
*/
this.filtersVisKey = 'filters_visibility';
}
/**
* Initializes State instance
*/
init() {
if (this.initialized) {
return;
}
this.emitter.on(['after-filtering'], () => this.update());
this.emitter.on(['after-page-change', 'after-clearing-filters'],
(tf, pageNb) => this.updatePage(pageNb));
this.emitter.on(['after-page-length-change'],
(tf, pageLength) => this.updatePageLength(pageLength));
this.emitter.on(['column-sorted'],
(tf, index, descending) => this.updateSort(index, descending));
this.emitter.on(['sort-initialized'], () => this._syncSort());
this.emitter.on(['columns-visibility-initialized'],
() => this._syncColsVisibility());
this.emitter.on(['column-shown', 'column-hidden'], (tf, feature,
colIndex, hiddenCols) => this.updateColsVisibility(hiddenCols));
this.emitter.on(['filters-visibility-initialized'],
() => this._syncFiltersVisibility());
this.emitter.on(['filters-toggled'],
(tf, extension, visible) => this.updateFiltersVisibility(visible));
if (this.enableHash) {
this.hash = new Hash(this);
this.hash.init();
}
if (this.enableStorage) {
this.storage = new Storage(this);
this.storage.init();
}
/** @inherited */
this.initialized = true;
}
/**
* Update state object based on current features state
*/
update() {
if (!this.isEnabled()) {
return;
}
let state = this.state;
let tf = this.tf;
if (this.persistFilters) {
let filterValues = tf.getFiltersValue();
filterValues.forEach((val, idx) => {
let key = `${this.prfxCol}${idx}`;
if (isString(val) && isEmpty(val)) {
if (state.hasOwnProperty(key)) {
state[key].flt = undefined;
}
} else {
state[key] = state[key] || {};
state[key].flt = val;
}
});
}
if (this.persistPageNumber) {
if (isNull(this.pageNb)) {
state[this.pageNbKey] = undefined;
} else {
state[this.pageNbKey] = this.pageNb;
}
}
if (this.persistPageLength) {
if (isNull(this.pageLength)) {
state[this.pageLengthKey] = undefined;
} else {
state[this.pageLengthKey] = this.pageLength;
}
}
if (this.persistSort) {
if (!isNull(this.sort)) {
// Remove previuosly sorted column
Object.keys(state).forEach((key) => {
if (key.indexOf(this.prfxCol) !== -1 && state[key]) {
state[key].sort = undefined;
}
});
let key = `${this.prfxCol}${this.sort.column}`;
state[key] = state[key] || {};
state[key].sort = { descending: this.sort.descending };
}
}
if (this.persistColsVisibility) {
if (!isNull(this.hiddenCols)) {
// Clear previuosly hidden columns
Object.keys(state).forEach((key) => {
if (key.indexOf(this.prfxCol) !== -1 && state[key]) {
state[key].hidden = undefined;
}
});
this.hiddenCols.forEach((colIdx) => {
let key = `${this.prfxCol}${colIdx}`;
state[key] = state[key] || {};
state[key].hidden = true;
});
}
}
if (this.persistFiltersVisibility) {
if (isNull(this.filtersVisibility)) {
state[this.filtersVisKey] = undefined;
} else {
state[this.filtersVisKey] = this.filtersVisibility;
}
}
this.emitter.emit('state-changed', tf, state);
}
/**
* Refresh page number field on page number changes
*
* @param {Number} pageNb Current page number
*/
updatePage(pageNb) {
this.pageNb = pageNb;
this.update();
}
/**
* Refresh page length field on page length changes
*
* @param {Number} pageLength Current page length value
*/
updatePageLength(pageLength) {
this.pageLength = pageLength;
this.update();
}
/**
* Refresh column sorting information on sort changes
*
* @param index {Number} Column index
* @param {Boolean} descending Descending manner
*/
updateSort(index, descending) {
this.sort = {
column: index,
descending: descending
};
this.update();
}
/**
* Refresh hidden columns information on columns visibility changes
*
* @param {Array} hiddenCols Columns indexes
*/
updateColsVisibility(hiddenCols) {
this.hiddenCols = hiddenCols;
this.update();
}
/**
* Refresh filters visibility on filters visibility change
*
* @param {Boolean} visible Visibility flad
*/
updateFiltersVisibility(visible) {
this.filtersVisibility = visible;
this.update();
}
/**
* Override state field
*
* @param state State object
*/
override(state) {
this.state = state;
this.emitter.emit('state-changed', this.tf, state);
}
/**
* Sync stored features state
*/
sync() {
let state = this.state;
let tf = this.tf;
this._syncFilters();
if (this.persistPageNumber) {
let pageNumber = state[this.pageNbKey];
this.emitter.emit('change-page', tf, pageNumber);
}
if (this.persistPageLength) {
let pageLength = state[this.pageLengthKey];
this.emitter.emit('change-page-results', tf, pageLength);
}
this._syncSort();
this._syncColsVisibility();
this._syncFiltersVisibility();
}
/**
* Override current state with passed one and sync features
*
* @param {Object} state State object
*/
overrideAndSync(state) {
// To prevent state to react to features changes, state is temporarily
// disabled
this.disable();
// State is overriden with passed state object
this.override(state);
// New hash state is applied to features
this.sync();
// State is re-enabled
this.enable();
}
/**
* Sync filters with stored values and filter table
*
* @private
*/
_syncFilters() {
if (!this.persistFilters) {
return;
}
let state = this.state;
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) => {
if (key.indexOf(this.prfxCol) !== -1) {
let colIdx = parseInt(key.replace(this.prfxCol, ''), 10);
let val = state[key].flt;
tf.setFilterValue(colIdx, val);
}
});
tf.filter();
}
/**
* Sync sorted column with stored sorting information and sort table
*
* @private
*/
_syncSort() {
if (!this.persistSort) {
return;
}
let state = this.state;
let tf = this.tf;
Object.keys(state).forEach((key) => {
if (key.indexOf(this.prfxCol) !== -1) {
let colIdx = parseInt(key.replace(this.prfxCol, ''), 10);
if (!isUndef(state[key].sort)) {
let sort = state[key].sort;
this.emitter.emit('sort', tf, colIdx, sort.descending);
}
}
});
}
/**
* Sync hidden columns with stored information
*
* @private
*/
_syncColsVisibility() {
if (!this.persistColsVisibility) {
return;
}
let state = this.state;
let tf = this.tf;
let hiddenCols = [];
Object.keys(state).forEach((key) => {
if (key.indexOf(this.prfxCol) !== -1) {
let colIdx = parseInt(key.replace(this.prfxCol, ''), 10);
if (!isUndef(state[key].hidden)) {
hiddenCols.push(colIdx);
}
}
});
hiddenCols.forEach((colIdx) => {
this.emitter.emit('hide-column', tf, colIdx);
});
}
/**
* Sync filters visibility with stored information
*
* @private
*/
_syncFiltersVisibility() {
if (!this.persistFiltersVisibility) {
return;
}
let state = this.state;
let tf = this.tf;
let filtersVisibility = state[this.filtersVisKey];
this.filtersVisibility = filtersVisibility;
this.emitter.emit('show-filters', tf, filtersVisibility);
}
/**
* Destroy State instance
*/
destroy() {
if (!this.initialized) {
return;
}
this.state = {};
this.emitter.off(['after-filtering'], () => this.update());
this.emitter.off(['after-page-change', 'after-clearing-filters'],
(tf, pageNb) => this.updatePage(pageNb));
this.emitter.off(['after-page-length-change'],
(tf, index) => this.updatePageLength(index));
this.emitter.off(['column-sorted'],
(tf, index, descending) => this.updateSort(index, descending));
this.emitter.off(['sort-initialized'], () => this._syncSort());
this.emitter.off(['columns-visibility-initialized'],
() => this._syncColsVisibility());
this.emitter.off(['column-shown', 'column-hidden'], (tf, feature,
colIndex, hiddenCols) => this.updateColsVisibility(hiddenCols));
this.emitter.off(['filters-visibility-initialized'],
() => this._syncFiltersVisibility());
this.emitter.off(['filters-toggled'],
(tf, extension, visible) => this.updateFiltersVisibility(visible));
if (this.enableHash) {
this.hash.destroy();
this.hash = null;
}
if (this.enableStorage) {
this.storage.destroy();
this.storage = null;
}
this.initialized = false;
}
}

View file

@ -1,78 +1,207 @@
import {Feature} from './feature';
import Dom from '../dom';
import Types from '../types';
import {Feature} from '../feature';
import {root} from '../root';
import {createElm, createText, elm, removeElm} from '../dom';
import {EMPTY_FN, isNull} from '../types';
import {defaultsStr, defaultsFn} from '../settings';
import {LEFT} from './toolbar';
var global = window;
const 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'
];
export class StatusBar extends Feature{
/**
* Status bar UI component
* @export
* @class StatusBar
* @extends {Feature}
*/
export class StatusBar extends Feature {
/**
* Status bar UI component
* @param {Object} tf TableFilter instance
* Creates an instance of StatusBar
* @param {TableFilter} tf TableFilter instance
*/
constructor(tf){
super(tf, 'statusBar');
constructor(tf) {
super(tf, StatusBar);
// Configuration object
var f = this.config;
let f = this.config.status_bar || {};
//id of custom container element
this.statusBarTgtId = f.status_bar_target_id || null;
//element containing status bar label
this.statusBarDiv = null;
//status bar
this.statusBarSpan = null;
//status bar label
this.statusBarSpanText = null;
//defines status bar text
this.statusBarText = f.status_bar_text || '';
//defines css class status bar
this.statusBarCssClass = f.status_bar_css_class || 'status';
//delay for status bar clearing
this.statusBarCloseDelay = 250;
/**
* ID of custom container element
* @type {String}
*/
this.targetId = defaultsStr(f.target_id, null);
//calls function before message is displayed
this.onBeforeShowMsg = Types.isFn(f.on_before_show_msg) ?
f.on_before_show_msg : null;
//calls function after message is displayed
this.onAfterShowMsg = Types.isFn(f.on_after_show_msg) ?
f.on_after_show_msg : null;
/**
* Container DOM element
* @type {DOMElement}
* @private
*/
this.container = null;
// status bar div
this.prfxStatus = 'status_';
// status bar label
this.prfxStatusSpan = 'statusSpan_';
// text preceding status bar label
this.prfxStatusTxt = 'statusText_';
/**
* Message container DOM element
* @type {DOMElement}
* @private
*/
this.msgContainer = null;
/**
* Label container DOM element
* @type {DOMElement}
* @private
*/
this.labelContainer = null;
/**
* Text preceding status message
* @type {String}
*/
this.text = defaultsStr(f.text, '');
/**
* Css class for container element
* @type {String}
*/
this.cssClass = defaultsStr(f.css_class, 'status');
/**
* Message visibility duration in milliseconds
* @type {Number}
* @private
*/
this.delay = 250;
/**
* Callback fired before the message is displayed
* @type {Function}
*/
this.onBeforeShowMsg = defaultsFn(f.on_before_show_msg, EMPTY_FN);
/**
* Callback fired after the message is displayed
* @type {Function}
*/
this.onAfterShowMsg = defaultsFn(f.on_after_show_msg, EMPTY_FN);
/**
* Message appearing upon filtering
* @type {String}
*/
this.msgFilter = defaultsStr(f.msg_filter, 'Filtering data...');
/**
* Message appearing when a drop-down filter is populated
* @type {String}
*/
this.msgPopulate = defaultsStr(f.msg_populate, 'Populating filter...');
/**
* Message appearing when a checklist filter is populated
* @type {String}
*/
this.msgPopulateCheckList = defaultsStr(f.msg_populate_checklist,
'Populating list...');
/**
* Message appearing when a pagination page is changed
* @type {String}
*/
this.msgChangePage = defaultsStr(f.msg_change_page,
'Collecting paging data...');
/**
* Message appearing when filters are cleared
* @type {String}
*/
this.msgClear = defaultsStr(f.msg_clear, 'Clearing filters...');
/**
* Message appearing when the page length is changed
* @type {String}
*/
this.msgChangeResults = defaultsStr(f.msg_change_results,
'Changing results per page...');
/**
* Message appearing when the page is re-set
* @type {String}
*/
this.msgResetPage = defaultsStr(f.msg_reset_page, 'Re-setting page...');
/**
* Message appearing when the page length is re-set
* @type {String}
*/
this.msgResetPageLength = defaultsStr(f.msg_reset_page_length,
'Re-setting page length...');
/**
* Message appearing upon column sorting
* @type {String}
*/
this.msgSort = defaultsStr(f.msg_sort, 'Sorting data...');
/**
* Message appearing when extensions are loading
* @type {String}
*/
this.msgLoadExtensions = defaultsStr(f.msg_load_extensions,
'Loading extensions...');
/**
* Message appearing when themes are loading
* @type {String}
*/
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);
}
init(){
if(this.initialized){
/**
* Initializes StatusBar instance
*/
init() {
if (this.initialized) {
return;
}
var tf = this.tf;
let tf = this.tf;
let emitter = this.emitter;
//status bar container
var statusDiv = Dom.create('div', ['id', this.prfxStatus+tf.id]);
statusDiv.className = this.statusBarCssClass;
emitter.emit('initializing-feature', this, !isNull(this.targetId));
//status bar label
var statusSpan = Dom.create('span', ['id', this.prfxStatusSpan+tf.id]);
//preceding text
var statusSpanText = Dom.create('span',
['id', this.prfxStatusTxt+tf.id]);
statusSpanText.appendChild(Dom.text(this.statusBarText));
// status bar container
let statusDiv = createElm('div');
statusDiv.className = this.cssClass;
// status bar label
let statusSpan = createElm('span');
// preceding text
let statusSpanText = createElm('span');
statusSpanText.appendChild(createText(this.text));
// target element container
if(!this.statusBarTgtId){
tf.setToolbar();
}
var targetEl = (!this.statusBarTgtId) ?
tf.lDiv : Dom.id(this.statusBarTgtId);
let targetEl = (!this.targetId) ?
tf.feature('toolbar').container(this.toolbarPosition) :
elm(this.targetId);
//default container: 'lDiv'
if(!this.statusBarTgtId){
// default container
if (!this.targetId) {
statusDiv.appendChild(statusSpanText);
statusDiv.appendChild(statusSpan);
targetEl.appendChild(statusDiv);
@ -82,42 +211,98 @@ export class StatusBar extends Feature{
targetEl.appendChild(statusSpan);
}
this.statusBarDiv = statusDiv;
this.statusBarSpan = statusSpan;
this.statusBarSpanText = statusSpanText;
this.container = statusDiv;
this.msgContainer = statusSpan;
this.labelContainer = statusSpanText;
// subscribe to events
emitter.on(['before-filtering'], () => this.message(this.msgFilter));
emitter.on(['before-populating-filter'],
() => this.message(this.msgPopulate));
emitter.on(['before-page-change'],
() => this.message(this.msgChangePage));
emitter.on(['before-clearing-filters'], () =>
this.message(this.msgClear));
emitter.on(['before-page-length-change'],
() => this.message(this.msgChangeResults));
emitter.on(['before-reset-page'],
() => this.message(this.msgResetPage));
emitter.on(['before-reset-page-length'],
() => this.message(this.msgResetPageLength));
emitter.on(['before-loading-extensions'],
() => this.message(this.msgLoadExtensions));
emitter.on(['before-loading-themes'],
() => this.message(this.msgLoadThemes));
emitter.on(EVENTS, () => this.message(''));
/** @inherited */
this.initialized = true;
emitter.emit('feature-initialized', this);
}
message(t=''){
if(!this.isEnabled()){
/**
* Display status message
* @param {String} [t=''] Message to be displayed
*/
message(t = '') {
if (!this.isEnabled()) {
return;
}
if(this.onBeforeShowMsg){
this.onBeforeShowMsg.call(null, this.tf, t);
}
this.onBeforeShowMsg(this.tf, t);
var d = t==='' ? this.statusBarCloseDelay : 1;
global.setTimeout(() => {
this.statusBarSpan.innerHTML = t;
if(this.onAfterShowMsg){
this.onAfterShowMsg.call(null, this.tf, t);
let d = t === '' ? this.delay : 1;
root.setTimeout(() => {
if (!this.initialized) {
return;
}
this.msgContainer.innerHTML = t;
this.onAfterShowMsg(this.tf, t);
}, d);
}
destroy(){
if(!this.initialized){
/**
* Destroy StatusBar instance
*/
destroy() {
if (!this.initialized) {
return;
}
this.statusBarDiv.innerHTML = '';
Dom.remove(this.statusBarDiv);
this.statusBarSpan = null;
this.statusBarSpanText = null;
this.statusBarDiv = null;
let emitter = this.emitter;
this.container.innerHTML = '';
if (!this.targetId) {
removeElm(this.container);
}
this.labelContainer = null;
this.msgContainer = null;
this.container = null;
// Unsubscribe to events
emitter.off(['before-filtering'], () => this.message(this.msgFilter));
emitter.off(['before-populating-filter'],
() => this.message(this.msgPopulate));
emitter.off(['before-page-change'],
() => this.message(this.msgChangePage));
emitter.off(['before-clearing-filters'],
() => this.message(this.msgClear));
emitter.off(['before-page-length-change'],
() => this.message(this.msgChangeResults));
emitter.off(['before-reset-page'], () =>
this.message(this.msgResetPage));
emitter.off(['before-reset-page-length'],
() => this.message(this.msgResetPageLength));
emitter.off(['before-loading-extensions'],
() => this.message(this.msgLoadExtensions));
emitter.off(['before-loading-themes'],
() => this.message(this.msgLoadThemes));
emitter.off(EVENTS, () => this.message(''));
this.initialized = false;
}
}

161
src/modules/storage.js Normal file
View file

@ -0,0 +1,161 @@
import Cookie from '../cookie';
import {root} from '../root';
const JSON = root.JSON;
const localStorage = root.localStorage;
const location = root.location;
/**
* Checks if browser has Storage feature
*/
export const hasStorage = () => {
return 'Storage' in root;
};
/**
* Stores the features state in browser's local storage or cookie
*
* @export
* @class Storage
*/
export class Storage {
/**
* Creates an instance of Storage
*
* @param {State} state Instance of State
*/
constructor(state) {
/**
* State object
* @type {State}
* @private
*/
this.state = state;
/**
* TableFilter object
* @type {TableFilter}
* @private
*/
this.tf = state.tf;
/**
* Persist with local storage
* @type {Boolean}
* @private
*/
this.enableLocalStorage = state.enableLocalStorage && hasStorage();
/**
* Persist with cookie
* @type {Boolean}
* @private
*/
this.enableCookie = state.enableCookie && !this.enableLocalStorage;
/**
* Emitter object
* @type {Emitter}
* @private
*/
this.emitter = state.emitter;
/**
* Cookie duration in hours from state object
* @type {Number}
* @private
*/
this.duration = state.cookieDuration;
}
/**
* Initializes the Storage object
*/
init() {
this.emitter.on(['state-changed'], (tf, state) => this.save(state));
this.emitter.on(['initialized'], () => this.sync());
}
/**
* Persists the features state on state changes
*
* @param {State} state Instance of State
*/
save(state) {
if (this.enableLocalStorage) {
localStorage[this.getKey()] = JSON.stringify(state);
} else {
Cookie.write(this.getKey(), JSON.stringify(state), this.duration);
}
}
/**
* Turns stored string into a State JSON object
*
* @returns {Object} JSON object
*/
retrieve() {
let state = null;
if (this.enableLocalStorage) {
state = localStorage[this.getKey()];
} else {
state = Cookie.read(this.getKey());
}
if (!state) {
return null;
}
return JSON.parse(state);
}
/**
* Removes persisted state from storage
*/
remove() {
if (this.enableLocalStorage) {
localStorage.removeItem(this.getKey());
} else {
Cookie.remove(this.getKey());
}
}
/**
* Applies persisted state to features
*/
sync() {
let state = this.retrieve();
if (!state) {
return;
}
// override current state with persisted one and sync features
this.state.overrideAndSync(state);
}
/**
* Returns the storage key
*
* @returns {String} Key
*/
getKey() {
return JSON.stringify({
key: `${this.tf.prfxTf}_${this.tf.id}`,
path: location.pathname
});
}
/**
* Release Storage event subscriptions and clear fields
*/
destroy() {
this.emitter.off(['state-changed'], (tf, state) => this.save(state));
this.emitter.off(['initialized'], () => this.sync());
this.remove();
this.state = null;
this.emitter = null;
}
}

View file

@ -1,100 +0,0 @@
import Cookie from '../cookie';
export class Store{
/**
* Store, persistence manager
* @param {Object} tf TableFilter instance
*
* TODO: use localStorage and fallback to cookie persistence
*/
constructor(tf) {
var f = tf.config();
this.duration = !isNaN(f.set_cookie_duration) ?
parseInt(f.set_cookie_duration, 10) : 100000;
this.tf = tf;
}
/**
* Store filters' values in cookie
* @param {String} cookie name
*/
saveFilterValues(name){
var tf = this.tf;
var fltValues = [];
//store filters' values
for(var i=0; i<tf.fltIds.length; i++){
var value = tf.getFilterValue(i);
if (value === ''){
value = ' ';
}
fltValues.push(value);
}
//adds array size
fltValues.push(tf.fltIds.length);
//writes cookie
Cookie.write(
name,
fltValues.join(tf.separator),
this.duration
);
}
/**
* Retrieve filters' values from cookie
* @param {String} cookie name
* @return {Array}
*/
getFilterValues(name){
var flts = Cookie.read(name);
var rgx = new RegExp(this.tf.separator, 'g');
// filters' values array
return flts.split(rgx);
}
/**
* Store page number in cookie
* @param {String} cookie name
*/
savePageNb(name){
Cookie.write(
name,
this.tf.feature('paging').currentPageNb,
this.duration
);
}
/**
* Retrieve page number from cookie
* @param {String} cookie name
* @return {String}
*/
getPageNb(name){
return Cookie.read(name);
}
/**
* Store page length in cookie
* @param {String} cookie name
*/
savePageLength(name){
Cookie.write(
name,
this.tf.feature('paging').resultsPerPageSlc.selectedIndex,
this.duration
);
}
/**
* Retrieve page length from cookie
* @param {String} cookie name
* @return {String}
*/
getPageLength(name){
return Cookie.read(name);
}
}

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};

32
src/number.js Normal file
View file

@ -0,0 +1,32 @@
import {isNumber} from './types';
/**
* Takes a string, removes all formatting/cruft and returns the raw float value
* @param {String} Formatted number
* @param {String} Decimal type '.' or ','
* @return {Number} Unformatted number
*
* https://github.com/openexchangerates/accounting.js/blob/master/accounting.js
*/
export const parse = (value, decimal = '.') => {
// Return the value as-is if it's already a number
if (isNumber(value)) {
return value;
}
// Build regex to strip out everything except digits, decimal point and
// minus sign
let regex = new RegExp('[^0-9-' + decimal + ']', ['g']);
let unformatted = parseFloat(
('' + value)
// replace bracketed values with negatives
.replace(/\((.*)\)/, '-$1')
// strip out any cruft
.replace(regex, '')
// make sure decimal point is standard
.replace(decimal, '.')
);
// This will fail silently
return !isNaN(unformatted) ? unformatted : 0;
};

6
src/root.js Normal file
View file

@ -0,0 +1,6 @@
/**
* Export window or global object depending on the environment
*/
export const root = (typeof self === 'object' && self.self === self && self) ||
(typeof global === 'object' && global.global === global && global) ||
this;

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,9 +1,82 @@
import Str from './string';
import {parse as parseNb} from './number';
import {Date as SugarDate} from 'sugar-date';
export default {
ignoreCase(a, b){
let x = Str.lower(a);
let y = Str.lower(b);
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
}
/** Sorting utilities */
/**
* Case insensitive compare function for passed strings
* @param {String} First string
* @param {String} Second string
* @return {Number} -1 if first string lower than second one
* 0 if first string same order as second one
* 1 if first string greater than second one
*/
export const ignoreCase = (a, b) => {
let x = a.toLowerCase();
let y = b.toLowerCase();
return x < y ? -1 : (x > y ? 1 : 0);
};
/**
* Compare function for sorting passed numbers in ascending manner
* @param {Number} First number
* @param {Number} Second number
* @return {Number} Negative, zero or positive number
*/
export const numSortAsc = (a, b) => (a - b);
/**
* Compare function for sorting passed numbers in descending manner
* @param {Number} First number
* @param {Number} Second number
* @return {Number} Negative, zero or positive number
*/
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

@ -1,61 +1,112 @@
import {remove as removeDiacritics} from 'diacritics';
/**
* String utilities
*/
export default {
lower(text){
return text.toLowerCase();
},
upper(text){
return text.toUpperCase();
},
trim(text){
if (text.trim){
return text.trim();
}
return text.replace(/^\s*|\s*$/g, '');
},
isEmpty(text){
return this.trim(text) === '';
},
rgxEsc(text){
let chars = /[-\/\\^$*+?.()|[\]{}]/g;
let escMatch = '\\$&';
return String(text).replace(chars, escMatch);
},
matchCase(text, caseSensitive){
if(!caseSensitive){
return this.lower(text);
}
return text;
},
/**
* Checks if passed data contains the searched term
* @param {String} term Searched term
* @param {String} data Data string
* @param {Boolean} exactMatch Exact match
* @param {Boolean} caseSensitive Case sensitive
* @return {Boolean}
*/
contains(term, data, exactMatch=false, caseSensitive=false){
// Improved by Cedric Wartel (cwl) automatic exact match for selects and
// special characters are now filtered
let regexp,
modifier = caseSensitive ? 'g' : 'gi';
if(exactMatch){
regexp = new RegExp(
'(^\\s*)'+ this.rgxEsc(term) +'(\\s*$)', modifier);
} else {
regexp = new RegExp(this.rgxEsc(term), modifier);
}
return regexp.test(data);
/**
* Removes whitespace from both sides of passed string
* @param {String} text
* @return {String}
*/
export const trim = (text) => {
if (text.trim) {
return text.trim();
}
return text.replace(/^\s*|\s*$/g, '');
};
/**
* Checks if passed string is empty
* @param {String} text
* @return {Boolean}
*/
export const isEmpty = (text) => trim(text) === '';
/**
* Makes regex safe string by escaping special characters from passed string
* @param {String} text
* @return {String} escaped string
*/
export const rgxEsc = (text) => {
let chars = /[-\/\\^$*+?.()|[\]{}]/g;
let escMatch = '\\$&';
return String(text).replace(chars, escMatch);
};
/**
* Returns passed string as lowercase if caseSensitive flag set false. By
* default it returns the string with no casing changes.
* @param {String} text
* @return {String} string
*/
export const matchCase = (text, caseSensitive = false) => {
if (!caseSensitive) {
return text.toLowerCase();
}
return text;
};
/**
* Checks if passed data contains the searched term
* @param {String} term Searched term
* @param {String} data Data string
* @param {Boolean} exactMatch Exact match
* @param {Boolean} caseSensitive Case sensitive
* @param {Boolean} ignoreDiacritics Ignore diacritics
* @return {Boolean}
*/
export const contains = (term, data, exactMatch = false, caseSensitive = false,
ignoreDiacritics = false) => {
// Improved by Cedric Wartel (cwl) automatic exact match for selects and
// special characters are now filtered
let regexp;
let modifier = caseSensitive ? 'g' : 'gi';
if (ignoreDiacritics) {
term = removeDiacritics(term);
data = removeDiacritics(data);
}
if (exactMatch) {
regexp = new RegExp('(^\\s*)' + rgxEsc(term) + '(\\s*$)',
modifier);
} else {
regexp = new RegExp(rgxEsc(term), modifier);
}
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

@ -1,71 +1,81 @@
/**
* Types utilities
*/
const UNDEFINED = void 0;
export default {
/**
* Check if argument is an object or a global object
* @param {String or Object} v
* @return {Boolean}
*/
isObj(v){
let isO = false;
if(typeof v === 'string'){
if(window[v] && typeof window[v] === 'object'){
isO = true;
}
} else {
if(v && typeof v === 'object'){
isO = true;
}
}
return isO;
},
/**
* Return an empty function
* @return {Function}
*/
export const EMPTY_FN = function() {};
/**
* Check if argument is a function
* @param {Function} fn
* @return {Boolean}
*/
isFn(fn){
return (fn && fn.constructor == Function);
},
/**
* Check passed argument is an object
* @param {Object} obj
* @return {Boolean}
*/
export const isObj =
(obj) => Object.prototype.toString.call(obj) === '[object Object]';
/**
* Check if argument is an array
* @param {Array} obj
* @return {Boolean}
*/
isArray(obj){
return (obj && obj.constructor == Array);
},
/**
* Check passed argument is a function
* @param {Function} obj
* @return {Boolean}
*/
export const isFn =
(obj) => Object.prototype.toString.call(obj) === '[object Function]';
/**
* Determine if argument is undefined
* @param {Any} o
* @return {Boolean}
*/
isUndef(o){
return o === UNDEFINED;
},
/**
* Check passed argument is an array
* @param {Array} obj
* @return {Boolean}
*/
export const isArray =
(obj) => Object.prototype.toString.call(obj) === '[object Array]';
/**
* Determine if argument is null
* @param {Any} o
* @return {Boolean}
*/
isNull(o){
return o === null;
},
/**
* Check passed argument is a string
* @param {String} obj obj
* @returns {Boolean}
*/
export const isString =
(obj) => Object.prototype.toString.call(obj) === '[object String]';
/**
* Determine if argument is empty (undefined, null or empty string)
* @param {Any} o
* @return {Boolean}
*/
isEmpty(o){
return this.isUndef(o) || this.isNull(o) || o.length===0;
}
};
/**
* Check passed argument is a number
* @param {Number} obj
* @returns {Boolean}
*/
export const isNumber =
(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
* @param {Any} obj
* @return {Boolean}
*/
export const isUndef = (obj) => obj === UNDEFINED;
/**
* Check passed argument is null
* @param {Any} obj
* @return {Boolean}
*/
export const isNull = (obj) => obj === null;
/**
* Check passed argument is empty (undefined, null or empty string)
* @param {Any} obj
* @return {Boolean}
*/
export const isEmpty = (obj) => isUndef(obj) || isNull(obj) || obj.length === 0;

View file

@ -350,4 +350,4 @@
<td>88.233.19.89</td>
</tr>
</tbody>
</table>
</table>

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

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

View file

@ -11,7 +11,6 @@ div.grd_Cont
width 800px
height auto
overflow hidden
padding 3px 3px 3px 3px
background-color $grid-layout-bg-color
border 1px solid $grid-layout-border-color
@ -37,6 +36,9 @@ div.grd_Cont
.no-results
background-color transparent
.sort-arrow
position initial
// content table container
div.grd_tblCont
height 400px
@ -47,8 +49,9 @@ div.grd_tblCont
// headers' table container
div.grd_headTblCont
display block
margin-right 20px
height auto
width 800px
overflow hidden
border-bottom 1px solid $grid-layout-border-color
background-color $grid-layout-bg-color
@ -60,10 +63,6 @@ div.grd_headTblCont table
table-layout fixed
box-sizing initial
div.grd_tblCont table
border-right 1px solid $grid-layout-border-color
box-sizing initial
// headers
div.grd_tblCont table th
div.grd_headTblCont table th

View file

@ -32,6 +32,7 @@ div.helpCont
color #333
background #fff
text-align left
z-index 1000
a
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
background-color $toolbar-hover-color
a.reset
font-weight normal !important
line-height $min-height
padding 5px 5px

View file

@ -3,14 +3,18 @@
*/
.sort-arrow
position absolute
display none
width 11px
height 11px
margin 0 2px
margin 0
background-position center center;
background-repeat no-repeat
&.descending
background-image url("themes/downsimple.png")
display inline
background-image url("themes/downsimple.png")
&.ascending
background-image url("themes/upsimple.png")
display inline
background-image url("themes/upsimple.png")

View file

@ -26,3 +26,19 @@ table.TF
margin 0
padding $padding
border-bottom 1px solid $td-border-color
text-overflow ellipsis
// responsive
&.resp
display block
overflow-x auto
overflow-y hidden
.sort-arrow
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

@ -4,22 +4,22 @@
// table
table.TF
border-left 1px solid #ccc !important
border-top none !important
border-right none !important
border-bottom none !important
border-left 1px solid #ccc
border-top none
border-right none
border-bottom none
th
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
color #333 !important
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
td
border-bottom 1px dotted #999 !important
padding 5px !important
border-bottom 1px dotted #999
padding 5px
// filters
.fltrow
@ -120,7 +120,7 @@ div.grd_tblCont table td
height 32px
background transparent url(images/img_loading.gif) 0 0 no-repeat !important
// alternating background rowa
// alternating background rows
.even
background-color #fff
.odd
@ -131,3 +131,7 @@ span.expClpFlt
a.btnExpClpFlt
&:hover
background-color transparent !important
// active header
.activeHeader
background: #999 !important

View file

@ -4,23 +4,23 @@
// table
table.TF
border-left 1px dotted #81963B !important
border-top none !important
border-right 0 !important
border-bottom none !important
border-left 1px dotted #81963B
border-top none
border-right 0
border-bottom none
th
background #39424B url(images/bg_headers.jpg) left top repeat-x !important
border-bottom 0 !important
border-right 1px dotted #D0D0D0 !important
border-left 0 !important
border-top 0 !important
color #fff !important
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
td
border-bottom 1px dotted #81963B
border-right 1px dotted #81963B
padding 5px !important
padding 5px
// filters
.fltrow
@ -146,3 +146,7 @@ span.expClpFlt
a.btnExpClpFlt
&:hover
background-color transparent !important
// active header
.activeHeader
background: #81963b !important

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 847 B

View file

@ -0,0 +1,205 @@
/**
* transparent theme overrides
*/
@import '../../mixins/box-shadow'
// table
table.TF
padding 0
color inherit
border-right 1px solid transparent
border-top 1px solid transparent
border-left 1px solid transparent
border-bottom 0
th
margin 0
color inherit
background-color transparent
border-color transparent
border-width 1px
border-style solid
&:last-child
border-right 1px solid transparent
td
margin 0
padding 5px
color inherit
border-bottom 1px solid transparent
border-left 0
border-top 0
border-right 0
// filters
.fltrow
background-color transparent
th, td
padding 1px 3px 1px 3px
border-bottom 1px solid transparent !important
&: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
// toolbar
.inf
background-color transparent
border 1px solid transparent
height $min-height
color inherit
div.tot,
div.status
border-right 0 !important
// help
.helpBtn
&:hover
background-color transparent
// reset button
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
&: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
&: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
&: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
&:hover
background #F7F7F7 url(images/btn_last_page.gif) center center no-repeat !important
border 1px solid #F7F7F7 !important
// active header
.activeHeader
background #F7F7F7 !important
border 1px solid transparent
color inherit !important
// grid-layout
// main container
div.grd_Cont
box-shadow(0 0 0 0 rgba(50, 50, 50, 0.75))
background-color transparent
border 1px solid transparent
padding 0 !important
// alternating background colors
.even
background-color transparent
.odd
background-color #F7F7F7
// headers' table container
div.grd_headTblCont
background-color transparent
border-bottom none !important
div.grd_tblCont table
border-right none !important
// headers
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
// toolbar containing left, middle and right divs
.grd_inf
background-color transparent
color inherit
border-top 1px solid transparent
a
text-decoration none
font-weight bold
// loader
.loader
background-color #F7F7F7
border 1px solid #F7F7F7
border-radius 5px
color #000000
text-shadow none
// alternating background colors
.even
background-color transparent
.odd
background-color #F7F7F7
// filters visibility
span.expClpFlt
a.btnExpClpFlt
&:hover
background-color transparent !important
// ezedittable
// selection
.ezActiveRow
background-color #CCCCCC !important
color inherit
.ezSelectedRow
background-color #CCCCCC !important
color inherit
.ezActiveCell
background-color transparent
color inherit
font-weight bold
.ezETSelectedCell
background-color transparent
font-weight bold
color inherit

View file

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

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