mirror of
https://github.com/koalyptus/TableFilter.git
synced 2024-06-02 22:12:23 +02:00
Compare commits
No commits in common. "master" and "0.6.66" have entirely different histories.
|
@ -14,7 +14,7 @@
|
|||
"keyword-spacing": ["error", { "after": true, "before": true }],
|
||||
"max-depth": [2, 7],
|
||||
"max-statements": [2, 133],
|
||||
"complexity": [2, 45],
|
||||
"complexity": [2, 41],
|
||||
"no-unused-vars": 2,
|
||||
"no-eval": 2,
|
||||
"no-underscore-dangle": 0,
|
||||
|
|
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
@ -1,38 +0,0 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**Reproduction steps:**
|
||||
Steps to reproduce the behavior:
|
||||
1. [First Step]
|
||||
2. [Second Step]
|
||||
3. [Other Steps...]
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Observed behavior:**
|
||||
A clear and concise description of observed behavior.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
![Screenshots and GIFs which follow reproduction steps to demonstrate the problem](url)
|
||||
|
||||
**TableFilter version:** [Enter TableFilter version here]
|
||||
**Browser and version:** [Enter Browser name and version here]
|
||||
**OS and version:** [Enter OS name and version here]
|
||||
**Device:** [e.g. iPhone6]
|
||||
|
||||
**Additional information/context:**
|
||||
Add any other context about the problem here.
|
||||
|
||||
* Problem started happening recently, didn't happen in an older version of TableFilter: [Yes/No] if yes [version here]
|
||||
* Problem can be reliably reproduced, doesn't happen randomly: [Yes/No]
|
36
.github/ISSUE_TEMPLATE/feature_request.md
vendored
36
.github/ISSUE_TEMPLATE/feature_request.md
vendored
|
@ -1,36 +0,0 @@
|
|||
---
|
||||
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
17
.github/ISSUE_TEMPLATE/support.md
vendored
|
@ -1,17 +0,0 @@
|
|||
---
|
||||
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/
|
|
@ -13,7 +13,7 @@ module.exports = function (grunt) {
|
|||
coverage: {
|
||||
disposeCollector: true,
|
||||
src: ['dist/tablefilter/*.js'],
|
||||
instrumentedFiles: 'report/temp/',
|
||||
instrumentedFiles: 'temp/',
|
||||
htmlReport: 'report/coverage',
|
||||
coberturaReport: 'report/',
|
||||
lcovReport: 'report/',
|
||||
|
|
|
@ -24,7 +24,7 @@ users to filter and limit the data displayed within a long table. By default, th
|
|||
* Attach to an existing HTML table
|
||||
* Integration with any server-side technology as this is a pure client-side
|
||||
solution
|
||||
* Exhaustive documentation and powerful API
|
||||
* Exhaustive documentation and poweful API
|
||||
|
||||
## Getting started
|
||||
* Clone the repo using Git:
|
||||
|
|
4
dist/starter.html
vendored
4
dist/starter.html
vendored
|
@ -1,10 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>tablefilter v0.7.3 - Starter</title>
|
||||
<title>tablefilter v0.6.65 - Starter</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>tablefilter v0.7.3</h1>
|
||||
<h1>tablefilter v0.6.65</h1>
|
||||
|
||||
|
||||
|
||||
|
|
2
dist/tablefilter/style/tablefilter.css
vendored
2
dist/tablefilter/style/tablefilter.css
vendored
File diff suppressed because one or more lines are too long
3
dist/tablefilter/tablefilter.js
vendored
3
dist/tablefilter/tablefilter.js
vendored
File diff suppressed because one or more lines are too long
1
dist/tablefilter/tablefilter.js.map
vendored
Normal file
1
dist/tablefilter/tablefilter.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
2
dist/tablefilter/tf-0-db54cfc612ffa547f4a3.js
vendored
Normal file
2
dist/tablefilter/tf-0-db54cfc612ffa547f4a3.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/tablefilter/tf-0-db54cfc612ffa547f4a3.js.map
vendored
Normal file
1
dist/tablefilter/tf-0-db54cfc612ffa547f4a3.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
11114
package-lock.json
generated
11114
package-lock.json
generated
File diff suppressed because it is too large
Load diff
26
package.json
26
package.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "tablefilter",
|
||||
"version": "0.7.3",
|
||||
"version": "0.6.66",
|
||||
"description": "A Javascript library making HTML tables filterable and a bit more",
|
||||
"license": "MIT",
|
||||
"author": {
|
||||
|
@ -40,17 +40,17 @@
|
|||
"tag": "next"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.10.0",
|
||||
"@babel/preset-env": "7.10.0",
|
||||
"babel-eslint": "10.1.0",
|
||||
"@babel/core": "7.0.1",
|
||||
"@babel/preset-env": "7.0.0",
|
||||
"babel-eslint": "10.0.0",
|
||||
"babel-loader": "^8.0.2",
|
||||
"babel-preset-env": "1.7.0",
|
||||
"clean-webpack-plugin": "^3.0.0",
|
||||
"codecov": "3.7.1",
|
||||
"clean-webpack-plugin": "^0.1.16",
|
||||
"codecov": "3.1.0",
|
||||
"diacritics": "1.3.0",
|
||||
"esdoc": "1.1.0",
|
||||
"esdoc-standard-plugin": "1.0.0",
|
||||
"eslint": "6.5.0",
|
||||
"eslint": "5.0.1",
|
||||
"format-number": "3.0.0",
|
||||
"grunt": "^1.0.1",
|
||||
"grunt-cli": "1.3.2",
|
||||
|
@ -58,18 +58,18 @@
|
|||
"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-qunit-istanbul": "1.0.0",
|
||||
"grunt-shell": "2.1.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",
|
||||
"sugar-date": "2.0.4",
|
||||
"uglifyjs-webpack-plugin": "2.0.1",
|
||||
"webpack": "^4.0.1",
|
||||
"webpack-cli": "^3.0.8",
|
||||
"webpack-dev-server": "^3.1.11"
|
||||
"webpack-dev-server": "^3.0.0"
|
||||
},
|
||||
"dependencies": {},
|
||||
"bugs": {
|
||||
|
|
88
src/const.js
88
src/const.js
|
@ -1,3 +1,19 @@
|
|||
import {DateType} from './modules/dateType';
|
||||
import {Help} from './modules/help';
|
||||
import {State} from './modules/state';
|
||||
import {GridLayout} from './modules/gridLayout';
|
||||
import {Loader} from './modules/loader';
|
||||
import {HighlightKeyword} from './modules/highlightKeywords';
|
||||
import {PopupFilter} from './modules/popupFilter';
|
||||
import {MarkActiveColumns} from './modules/markActiveColumns';
|
||||
import {RowsCounter} from './modules/rowsCounter';
|
||||
import {StatusBar} from './modules/statusBar';
|
||||
import {ClearButton} from './modules/clearButton';
|
||||
import {AlternateRows} from './modules/alternateRows';
|
||||
import {NoResults} from './modules/noResults';
|
||||
import {Paging} from './modules/paging';
|
||||
import {Toolbar} from './modules/toolbar';
|
||||
|
||||
/**
|
||||
* Filter types
|
||||
*/
|
||||
|
@ -116,3 +132,75 @@ export const IP_ADDRESS = 'ipaddress';
|
|||
* @type {Number}
|
||||
*/
|
||||
export const AUTO_FILTER_DELAY = 750;
|
||||
|
||||
/**
|
||||
* TableFilter features definitions
|
||||
* @type {Object}
|
||||
*/
|
||||
export const FEATURES = {
|
||||
dateType: {
|
||||
class: DateType,
|
||||
name: 'dateType'
|
||||
},
|
||||
help: {
|
||||
class: Help,
|
||||
name: 'help',
|
||||
enforce: true
|
||||
},
|
||||
state: {
|
||||
class: State,
|
||||
name: 'state'
|
||||
},
|
||||
markActiveColumns: {
|
||||
class: MarkActiveColumns,
|
||||
name: 'markActiveColumns'
|
||||
},
|
||||
gridLayout: {
|
||||
class: GridLayout,
|
||||
name: 'gridLayout'
|
||||
},
|
||||
loader: {
|
||||
class: Loader,
|
||||
name: 'loader'
|
||||
},
|
||||
highlightKeyword: {
|
||||
class: HighlightKeyword,
|
||||
name: 'highlightKeyword',
|
||||
property: 'highlightKeywords'
|
||||
},
|
||||
popupFilter: {
|
||||
class: PopupFilter,
|
||||
name: 'popupFilter',
|
||||
property: 'popupFilters'
|
||||
},
|
||||
rowsCounter: {
|
||||
class: RowsCounter,
|
||||
name: 'rowsCounter'
|
||||
},
|
||||
statusBar: {
|
||||
class: StatusBar,
|
||||
name: 'statusBar'
|
||||
},
|
||||
clearButton: {
|
||||
class: ClearButton,
|
||||
name: 'clearButton',
|
||||
property: 'btnReset'
|
||||
},
|
||||
alternateRows: {
|
||||
class: AlternateRows,
|
||||
name: 'alternateRows'
|
||||
},
|
||||
noResults: {
|
||||
class: NoResults,
|
||||
name: 'noResults'
|
||||
},
|
||||
paging: {
|
||||
class: Paging,
|
||||
name: 'paging'
|
||||
},
|
||||
toolbar: {
|
||||
class: Toolbar,
|
||||
name: 'toolbar',
|
||||
enforce: true
|
||||
}
|
||||
};
|
||||
|
|
|
@ -36,7 +36,7 @@ export const getFirstTextNode = (node) => {
|
|||
|
||||
/**
|
||||
* Creates an html element with given collection of attributes
|
||||
* @param {String} tag html tag name
|
||||
* @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
|
||||
|
|
|
@ -21,7 +21,7 @@ export default class AdapterEzEditTable extends Feature {
|
|||
* @param {Object} cfg Configuration options for ezEditTable library
|
||||
*/
|
||||
constructor(tf, cfg) {
|
||||
super(tf, AdapterEzEditTable);
|
||||
super(tf, cfg.name);
|
||||
|
||||
/**
|
||||
* Module description
|
||||
|
@ -505,5 +505,3 @@ export default class AdapterEzEditTable extends Feature {
|
|||
this.initialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
AdapterEzEditTable.meta = {altName: 'advancedGrid'};
|
||||
|
|
|
@ -33,7 +33,7 @@ export default class ColOps extends Feature {
|
|||
* @param {Object} opts Configuration object
|
||||
*/
|
||||
constructor(tf, opts) {
|
||||
super(tf, ColOps);
|
||||
super(tf, opts.name);
|
||||
|
||||
/**
|
||||
* Callback fired before columns operations start
|
||||
|
|
|
@ -23,7 +23,7 @@ export default class ColsVisibility extends Feature {
|
|||
* @param {Object} Configuration object
|
||||
*/
|
||||
constructor(tf, f) {
|
||||
super(tf, ColsVisibility);
|
||||
super(tf, f.name);
|
||||
|
||||
// Configuration object
|
||||
let cfg = this.config;
|
||||
|
|
|
@ -18,7 +18,7 @@ export default class FiltersVisibility extends Feature {
|
|||
* @param {Object} Configuration object
|
||||
*/
|
||||
constructor(tf, f) {
|
||||
super(tf, FiltersVisibility);
|
||||
super(tf, f.name);
|
||||
|
||||
/**
|
||||
* Module name
|
||||
|
|
|
@ -20,7 +20,7 @@ export default class AdapterSortableTable extends Feature {
|
|||
* @param {Object} opts Configuration object
|
||||
*/
|
||||
constructor(tf, opts) {
|
||||
super(tf, AdapterSortableTable);
|
||||
super(tf, opts.name);
|
||||
|
||||
/**
|
||||
* Module name
|
||||
|
@ -508,12 +508,9 @@ export default class AdapterSortableTable extends Feature {
|
|||
|
||||
}
|
||||
|
||||
AdapterSortableTable.meta = {altName: 'sort'};
|
||||
|
||||
//Converters
|
||||
function ipAddress(value) {
|
||||
let vals = value.split('.');
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
for (let x in vals) {
|
||||
let val = vals[x];
|
||||
while (3 > val.length) {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import {toCamelCase} from './string';
|
||||
|
||||
const NOT_IMPLEMENTED = 'Not implemented.';
|
||||
|
||||
|
@ -9,11 +8,9 @@ export class Feature {
|
|||
/**
|
||||
* Creates an instance of Feature
|
||||
* @param {Object} tf TableFilter instance
|
||||
* @param {Class} feature Feature class for TableFilter registration
|
||||
* @param {String} feature Feature name known by TableFilter
|
||||
*/
|
||||
constructor(tf, cls) {
|
||||
cls.meta = cls.meta || {};
|
||||
|
||||
constructor(tf, feature) {
|
||||
/**
|
||||
* TableFilter instance
|
||||
* @type {TableFilter}
|
||||
|
@ -21,18 +18,16 @@ export class Feature {
|
|||
this.tf = tf;
|
||||
|
||||
/**
|
||||
* Feature name is the camelised class name as per TableFilter's
|
||||
* convention
|
||||
* Feature name
|
||||
* @type {String}
|
||||
*/
|
||||
this.feature = cls.meta.altName || cls.meta.name
|
||||
|| toCamelCase(cls.name);
|
||||
this.feature = feature;
|
||||
|
||||
/**
|
||||
* TableFilter feature setting
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.enabled = tf[this.feature];
|
||||
this.enabled = tf[feature];
|
||||
|
||||
/**
|
||||
* TableFilter configuration
|
||||
|
|
|
@ -14,10 +14,9 @@ export class AlternateRows extends Feature {
|
|||
* @param {Object} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, AlternateRows);
|
||||
super(tf, 'alternateRows');
|
||||
|
||||
let config = this.config;
|
||||
|
||||
/**
|
||||
* Css class for even rows (default: 'even')
|
||||
* @type {String}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {Feature} from '../feature';
|
||||
import {
|
||||
ignoreCase, numSortAsc, numSortDesc,
|
||||
dateSortAsc, dateSortDesc, sortNumberStr, sortDateStr
|
||||
dateSortAsc, sortNumberStr, sortDateStr
|
||||
} from '../sort';
|
||||
import {isArray, isObj, isEmpty} from '../types';
|
||||
import {NUMBER, FORMATTED_NUMBER, DATE} from '../const';
|
||||
|
@ -18,8 +18,8 @@ export class BaseDropdown extends Feature {
|
|||
* Creates an instance of BaseDropdown
|
||||
* @param {TableFilter} tf
|
||||
*/
|
||||
constructor(tf, cls) {
|
||||
super(tf, cls);
|
||||
constructor(tf) {
|
||||
super(tf, 'baseDropdown');
|
||||
|
||||
let f = this.config;
|
||||
|
||||
|
@ -33,7 +33,7 @@ export class BaseDropdown extends Feature {
|
|||
f.filter_options_sorter :
|
||||
null;
|
||||
|
||||
// TODO: move here all properties shared by Dropdown and CheckList
|
||||
// TODO: move here all properties shared by Dropdown CheckList
|
||||
|
||||
/**
|
||||
* Has custom options
|
||||
|
@ -72,15 +72,14 @@ export class BaseDropdown extends Feature {
|
|||
* @private
|
||||
*/
|
||||
sortOptions(colIndex, options = []) {
|
||||
let {tf} = this;
|
||||
let tf = this.tf;
|
||||
|
||||
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 { caseSensitive, sortNumDesc } = tf;
|
||||
let compareFn;
|
||||
|
||||
if (this.customSorter &&
|
||||
|
@ -90,18 +89,18 @@ export class BaseDropdown extends Feature {
|
|||
}
|
||||
else if (tf.hasType(colIndex, [NUMBER, FORMATTED_NUMBER])) {
|
||||
let decimal = tf.getDecimal(colIndex);
|
||||
let comparer = isSortDesc ? numSortDesc : numSortAsc;
|
||||
let comparer = numSortAsc;
|
||||
if (sortNumDesc === true || sortNumDesc.indexOf(colIndex) !== -1) {
|
||||
comparer = numSortDesc;
|
||||
}
|
||||
compareFn = sortNumberStr(comparer, decimal);
|
||||
}
|
||||
else if (tf.hasType(colIndex, [DATE])) {
|
||||
let locale = tf.feature('dateType').getLocale(colIndex);
|
||||
let comparer = isSortDesc ? dateSortDesc : dateSortAsc;
|
||||
let comparer = dateSortAsc;
|
||||
compareFn = sortDateStr(comparer, locale);
|
||||
} else { // string
|
||||
compareFn = caseSensitive ? undefined : ignoreCase;
|
||||
if (isSortDesc) {
|
||||
return options.sort(compareFn).reverse();
|
||||
}
|
||||
}
|
||||
|
||||
return options.sort(compareFn);
|
||||
|
|
|
@ -22,7 +22,7 @@ export class CheckList extends BaseDropdown {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, CheckList);
|
||||
super(tf, 'checkList');
|
||||
|
||||
let f = this.config;
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ export class ClearButton extends Feature {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, ClearButton);
|
||||
super(tf, 'btnReset');
|
||||
|
||||
let f = this.config.btn_reset || {};
|
||||
|
||||
|
@ -137,6 +137,3 @@ export class ClearButton extends Feature {
|
|||
this.initialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove as soon as feature name is fixed
|
||||
ClearButton.meta = {altName: 'btnReset'};
|
||||
|
|
|
@ -17,7 +17,7 @@ export class DateType extends Feature {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, DateType);
|
||||
super(tf, 'dateType');
|
||||
|
||||
/**
|
||||
* Global locale
|
||||
|
|
|
@ -19,7 +19,7 @@ export class Dropdown extends BaseDropdown {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, Dropdown);
|
||||
super(tf, 'dropdown');
|
||||
|
||||
// Configuration object
|
||||
let f = this.config;
|
||||
|
|
|
@ -17,7 +17,7 @@ export class GridLayout extends Feature {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, GridLayout);
|
||||
super(tf, 'gridLayout');
|
||||
|
||||
let f = this.config.grid_layout || {};
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ export class Hash {
|
|||
}
|
||||
|
||||
/**
|
||||
* Converts a URL hash into a JSON object
|
||||
* Converts a URL hash into a state JSON object
|
||||
*
|
||||
* @param {String} hash URL hash fragment
|
||||
* @returns {Object} JSON object
|
||||
|
|
|
@ -4,7 +4,7 @@ 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 {defaultsStr} from '../settings';
|
||||
import {RIGHT} from './toolbar';
|
||||
|
||||
const WIKI_URL = 'https://github.com/koalyptus/TableFilter/wiki/' +
|
||||
|
@ -21,7 +21,7 @@ export class Help extends Feature {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, Help);
|
||||
super(tf, 'help');
|
||||
|
||||
let f = this.config.help_instructions || {};
|
||||
|
||||
|
@ -92,15 +92,6 @@ export class Help extends Feature {
|
|||
*/
|
||||
this.cont = null;
|
||||
|
||||
/**
|
||||
* Adjust container left position when table's horizontal scroll is
|
||||
* on, typically when `responsive` option is enabled.
|
||||
* @type {Number}
|
||||
* @defaultValue 25
|
||||
*/
|
||||
this.contAdjustLeftPosition =
|
||||
defaultsNb(f.container_adjust_left_position, 25);
|
||||
|
||||
/**
|
||||
* Bound mouseup wrapper
|
||||
* @private
|
||||
|
@ -223,21 +214,9 @@ export class Help extends Feature {
|
|||
let divDisplay = this.cont.style.display;
|
||||
if (divDisplay === '' || divDisplay === NONE) {
|
||||
this.cont.style.display = 'inline';
|
||||
|
||||
// if table element has an horizontal scrollbar adjust container
|
||||
// left position accordingly
|
||||
if (this.tf.dom().scrollLeft > 0) {
|
||||
this.cont.style.left = `${
|
||||
this.btn.offsetLeft
|
||||
- this.tf.dom().scrollLeft
|
||||
+ this.contAdjustLeftPosition
|
||||
}px`;
|
||||
}
|
||||
|
||||
addEvt(root, 'mouseup', this.boundMouseup);
|
||||
} else {
|
||||
this.cont.style.display = NONE;
|
||||
this.cont.style.left = '';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -259,6 +238,3 @@ export class Help extends Feature {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
// TODO: remove as soon as feature name is fixed
|
||||
Help.meta = {alwaysInstantiate: true};
|
||||
|
|
|
@ -172,9 +172,3 @@ export class HighlightKeyword {
|
|||
this.highlight(cell, term, this.highlightCssClass);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove as soon as feature name is fixed
|
||||
HighlightKeyword.meta = {
|
||||
name: 'highlightKeyword',
|
||||
altName: 'highlightKeywords'
|
||||
};
|
||||
|
|
|
@ -44,7 +44,7 @@ export class Loader extends Feature {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, Loader);
|
||||
super(tf, 'loader');
|
||||
|
||||
let f = this.config.loader || {};
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ export class MarkActiveColumns extends Feature {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, MarkActiveColumns);
|
||||
super(tf, 'markActiveColumns');
|
||||
|
||||
let config = this.config.mark_active_columns || {};
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ export class NoResults extends Feature {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, NoResults);
|
||||
super(tf, 'noResults');
|
||||
|
||||
//configuration object
|
||||
let f = this.config.no_results_message || {};
|
||||
|
|
|
@ -21,7 +21,7 @@ export class Paging extends Feature {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, Paging);
|
||||
super(tf, 'paging');
|
||||
|
||||
// Configuration object
|
||||
let f = this.config.paging || {};
|
||||
|
|
|
@ -19,7 +19,7 @@ export class PopupFilter extends Feature {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, PopupFilter);
|
||||
super(tf, 'popupFilters');
|
||||
|
||||
// Configuration object
|
||||
let f = this.config.popup_filters || {};
|
||||
|
@ -456,6 +456,3 @@ export class PopupFilter extends Feature {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
// TODO: remove as soon as feature name is fixed
|
||||
PopupFilter.meta = {altName: 'popupFilters'};
|
||||
|
|
|
@ -17,7 +17,7 @@ export class RowsCounter extends Feature {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, RowsCounter);
|
||||
super(tf, 'rowsCounter');
|
||||
|
||||
// TableFilter configuration
|
||||
let f = this.config.rows_counter || {};
|
||||
|
|
|
@ -19,7 +19,7 @@ export class State extends Feature {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, State);
|
||||
super(tf, 'state');
|
||||
|
||||
let cfg = this.config.state || {};
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ export class StatusBar extends Feature {
|
|||
* @param {TableFilter} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, StatusBar);
|
||||
super(tf, 'statusBar');
|
||||
|
||||
// Configuration object
|
||||
let f = this.config.status_bar || {};
|
||||
|
|
|
@ -29,7 +29,7 @@ export class Toolbar extends Feature {
|
|||
* @memberof Toolbar
|
||||
*/
|
||||
constructor(tf) {
|
||||
super(tf, Toolbar);
|
||||
super(tf, 'toolbar');
|
||||
|
||||
// Configuration object
|
||||
let f = this.config.toolbar || {};
|
||||
|
@ -219,6 +219,3 @@ export class Toolbar extends Feature {
|
|||
this.initialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove as soon as feature name is fixed
|
||||
Toolbar.meta = {alwaysInstantiate: true};
|
||||
|
|
|
@ -74,39 +74,3 @@ export const contains = (term, data, exactMatch = false, caseSensitive = false,
|
|||
}
|
||||
return regexp.test(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Camelize a string, cutting the string by multiple separators like
|
||||
* hyphens, underscores and spaces.
|
||||
* @param {String} text text to camelize
|
||||
* @return {String} camelized text
|
||||
*/
|
||||
export const toCamelCase = (text = '') => {
|
||||
return text.replace(/^([A-Z])|[\s-_]+(\w)/g, (match, p1, p2) => {
|
||||
if (p2) {
|
||||
return p2.toUpperCase();
|
||||
}
|
||||
return p1.toLowerCase();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a string in the format of a UUID (Universally Unique IDentifier).
|
||||
* NOTE: This format of 8 chars, followed by 3 groups of 4 chars, followed by 12
|
||||
* chars is known as a UUID and is defined in RFC4122 and is a standard for
|
||||
* generating unique IDs. This function DOES NOT implement this standard.
|
||||
* It simply outputs a string that looks similar. The standard is found here:
|
||||
* https://www.ietf.org/rfc/rfc4122.txt
|
||||
* source: https://gist.github.com/gordonbrander/2230317
|
||||
* @return {String}
|
||||
*/
|
||||
export const uuid = () => {
|
||||
const chr4 = () => Math.random().toString(16).slice(-4);
|
||||
|
||||
return chr4() + chr4()
|
||||
+ '-' + chr4()
|
||||
+ '-' + chr4()
|
||||
+ '-' + chr4()
|
||||
+ '-' + chr4()
|
||||
+ chr4() + chr4();
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@ import {addEvt, cancelEvt, stopEvt, targetEvt, isKeyPressed} from './event';
|
|||
import {
|
||||
addClass, createElm, elm, getText, getFirstTextNode, removeClass, tag
|
||||
} from './dom';
|
||||
import {contains, matchCase, rgxEsc, trim, toCamelCase, uuid} from './string';
|
||||
import {contains, matchCase, rgxEsc, trim} from './string';
|
||||
import {
|
||||
isArray, isEmpty, isFn, isNumber, isObj, isString, isUndef, EMPTY_FN,
|
||||
isBoolean
|
||||
|
@ -17,36 +17,16 @@ import {root} from './root';
|
|||
import {Emitter} from './emitter';
|
||||
import {Dropdown} from './modules/dropdown';
|
||||
import {CheckList} from './modules/checkList';
|
||||
import {DateType} from './modules/dateType';
|
||||
import {Help} from './modules/help';
|
||||
import {State} from './modules/state';
|
||||
import {GridLayout} from './modules/gridLayout';
|
||||
import {Loader} from './modules/loader';
|
||||
import {HighlightKeyword} from './modules/highlightKeywords';
|
||||
import {PopupFilter} from './modules/popupFilter';
|
||||
import {MarkActiveColumns} from './modules/markActiveColumns';
|
||||
import {RowsCounter} from './modules/rowsCounter';
|
||||
import {StatusBar} from './modules/statusBar';
|
||||
import {ClearButton} from './modules/clearButton';
|
||||
import {AlternateRows} from './modules/alternateRows';
|
||||
import {NoResults} from './modules/noResults';
|
||||
import {Paging} from './modules/paging';
|
||||
import {Toolbar} from './modules/toolbar';
|
||||
|
||||
import {
|
||||
INPUT, SELECT, MULTIPLE, CHECKLIST, NONE,
|
||||
ENTER_KEY, TAB_KEY, ESC_KEY, UP_ARROW_KEY, DOWN_ARROW_KEY,
|
||||
CELL_TAG, AUTO_FILTER_DELAY, NUMBER, DATE, FORMATTED_NUMBER
|
||||
CELL_TAG, AUTO_FILTER_DELAY, NUMBER, DATE, FORMATTED_NUMBER,
|
||||
FEATURES
|
||||
} from './const';
|
||||
|
||||
let doc = root.document;
|
||||
|
||||
const FEATURES = [
|
||||
DateType, Help, State, MarkActiveColumns, GridLayout, Loader,
|
||||
HighlightKeyword, PopupFilter, RowsCounter, StatusBar, ClearButton,
|
||||
AlternateRows, NoResults, Paging, Toolbar
|
||||
];
|
||||
|
||||
/**
|
||||
* Makes HTML tables filterable and a bit more :)
|
||||
*
|
||||
|
@ -142,7 +122,7 @@ export class TableFilter {
|
|||
args.forEach((arg) => {
|
||||
if (typeof arg === 'object' && arg.nodeName === 'TABLE') {
|
||||
this.tbl = arg;
|
||||
this.id = arg.id || `tf_${uuid()}`;
|
||||
this.id = arg.id || `tf_${new Date().getTime()}_`;
|
||||
this.tbl.id = this.id;
|
||||
} else if (isString(arg)) {
|
||||
this.id = arg;
|
||||
|
@ -337,7 +317,7 @@ export class TableFilter {
|
|||
this.onAfterFilter = defaultsFn(f.on_after_filter, EMPTY_FN);
|
||||
|
||||
/**
|
||||
* Enable/disable case sensitivity for filtering, default false
|
||||
* Enable/disable case sensitivity filtering
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.caseSensitive = Boolean(f.case_sensitive);
|
||||
|
@ -419,7 +399,8 @@ export class TableFilter {
|
|||
* Enable/disable single filter mode
|
||||
* @type {Boolean|Object}
|
||||
*/
|
||||
this.singleFlt = isObj(f.single_filter) || Boolean(f.single_filter);
|
||||
this.singleFlt = isObj(f.single_filter) ||
|
||||
Boolean(f.single_filter);
|
||||
|
||||
/**
|
||||
* Specify columns to be excluded from single filter search, by default
|
||||
|
@ -493,9 +474,7 @@ export class TableFilter {
|
|||
* Text for clear option in drop-down filter types (1st option)
|
||||
* @type {String|Array}
|
||||
*/
|
||||
this.clearFilterText = isArray(f.clear_filter_text)
|
||||
? f.clear_filter_text
|
||||
: defaultsStr(f.clear_filter_text, 'Clear');
|
||||
this.clearFilterText = defaultsStr(f.clear_filter_text, 'Clear');
|
||||
|
||||
/**
|
||||
* Indicate whether empty option is enabled in drop-down filter types
|
||||
|
@ -534,24 +513,38 @@ export class TableFilter {
|
|||
* by default globally or on a column basis
|
||||
* @type {Boolean|Array}
|
||||
*/
|
||||
this.sortSlc = isUndef(f.sort_select)
|
||||
? true
|
||||
: defaultsArr(f.sort_select, Boolean(f.sort_select));
|
||||
this.sortSlc = isUndef(f.sort_select) ? true :
|
||||
isArray(f.sort_select) ? f.sort_select : Boolean(f.sort_select);
|
||||
|
||||
/**
|
||||
* List of columns implementing filter options sorting in ascending
|
||||
* manner based on column data type
|
||||
* @type {Array}
|
||||
* Indicate whether options in drop-down filter types are sorted in a
|
||||
* ascending numeric manner
|
||||
* @type {Boolean}
|
||||
* @private
|
||||
*/
|
||||
this.sortFilterOptionsAsc = defaultsArr(f.sort_filter_options_asc, []);
|
||||
this.isSortNumAsc = Boolean(f.sort_num_asc);
|
||||
|
||||
/**
|
||||
* List of columns implementing filter options sorting in descending
|
||||
* manner based on column data type
|
||||
* List of columns implementing options sorting in a ascending numeric
|
||||
* manner
|
||||
* @type {Array}
|
||||
*/
|
||||
this.sortFilterOptionsDesc =
|
||||
defaultsArr(f.sort_filter_options_desc, []);
|
||||
this.sortNumAsc = this.isSortNumAsc ? f.sort_num_asc : [];
|
||||
|
||||
/**
|
||||
* Indicate whether options in drop-down filter types are sorted in a
|
||||
* descending numeric manner
|
||||
* @type {Boolean}
|
||||
* @private
|
||||
*/
|
||||
this.isSortNumDesc = Boolean(f.sort_num_desc);
|
||||
|
||||
/**
|
||||
* List of columns implementing options sorting in a descending numeric
|
||||
* manner
|
||||
* @type {Array}
|
||||
*/
|
||||
this.sortNumDesc = this.isSortNumDesc ? f.sort_num_desc : [];
|
||||
|
||||
/**
|
||||
* Indicate whether drop-down filter types are populated on demand at
|
||||
|
@ -933,8 +926,10 @@ export class TableFilter {
|
|||
*/
|
||||
this.ExtRegistry = {};
|
||||
|
||||
// instantiate features if needed
|
||||
this.instantiateFeatures(FEATURES);
|
||||
// conditionally instantiate required features
|
||||
this.instantiateFeatures(
|
||||
Object.keys(FEATURES).map((item) => FEATURES[item])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -954,16 +949,20 @@ export class TableFilter {
|
|||
//loads theme
|
||||
this.loadThemes();
|
||||
|
||||
const { dateType, help, state, markActiveColumns, gridLayout, loader,
|
||||
highlightKeyword, popupFilter, rowsCounter, statusBar, clearButton,
|
||||
alternateRows, noResults, paging, toolbar } = FEATURES;
|
||||
|
||||
//explicitly initialise features in given order
|
||||
this.initFeatures([
|
||||
DateType,
|
||||
Help,
|
||||
State,
|
||||
MarkActiveColumns,
|
||||
GridLayout,
|
||||
Loader,
|
||||
HighlightKeyword,
|
||||
PopupFilter
|
||||
dateType,
|
||||
help,
|
||||
state,
|
||||
markActiveColumns,
|
||||
gridLayout,
|
||||
loader,
|
||||
highlightKeyword,
|
||||
popupFilter
|
||||
]);
|
||||
|
||||
//filters grid is not generated
|
||||
|
@ -1036,13 +1035,13 @@ export class TableFilter {
|
|||
}
|
||||
|
||||
this.initFeatures([
|
||||
RowsCounter,
|
||||
StatusBar,
|
||||
ClearButton,
|
||||
AlternateRows,
|
||||
NoResults,
|
||||
Paging,
|
||||
Toolbar
|
||||
rowsCounter,
|
||||
statusBar,
|
||||
clearButton,
|
||||
alternateRows,
|
||||
noResults,
|
||||
paging,
|
||||
toolbar
|
||||
]);
|
||||
|
||||
this.setColWidths();
|
||||
|
@ -1251,41 +1250,47 @@ export class TableFilter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Conditionally istantiate each feature class in passed collection if
|
||||
* required by configuration and add it to the features registry. A feature
|
||||
* class meta information contains a `name` field and optional `altName` and
|
||||
* `alwaysInstantiate` fields
|
||||
* Istantiate the collection of features required by the
|
||||
* configuration and add them to the features registry. A feature is
|
||||
* described by a `class` and `name` fields and and optional `property`
|
||||
* field:
|
||||
* {
|
||||
* class: AClass,
|
||||
* name: 'aClass'
|
||||
* }
|
||||
* @param {Array} [features=[]]
|
||||
* @private
|
||||
*/
|
||||
instantiateFeatures(features = []) {
|
||||
features.forEach(featureCls => {
|
||||
let Cls = featureCls;
|
||||
features.forEach((feature) => {
|
||||
// TODO: remove the property field.
|
||||
// Due to naming convention inconsistencies, a `property`
|
||||
// field is added to allow a conditional instanciation based
|
||||
// on that property on TableFilter, if supplied.
|
||||
feature.property = feature.property || feature.name;
|
||||
if (!this.hasConfig || this[feature.property] === true ||
|
||||
feature.enforce === true) {
|
||||
let {class: Cls, name} = feature;
|
||||
|
||||
// assign meta info if not present
|
||||
Cls.meta = Cls.meta || {name: null, altName: null};
|
||||
Cls.meta.name = toCamelCase(Cls.name);
|
||||
let {name, altName, alwaysInstantiate} = Cls.meta;
|
||||
let prop = altName || name;
|
||||
|
||||
if (!this.hasConfig || this[prop] === true
|
||||
|| Boolean(alwaysInstantiate)) {
|
||||
this.Mod[name] = this.Mod[name] || new Cls(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise each feature class in passed collection.
|
||||
* Initialise the passed features collection. A feature is described by a
|
||||
* `class` and `name` fields and and optional `property` field:
|
||||
* {
|
||||
* class: AClass,
|
||||
* name: 'aClass'
|
||||
* }
|
||||
* @param {Array} [features=[]]
|
||||
* @private
|
||||
*/
|
||||
initFeatures(features = []) {
|
||||
features.forEach(featureCls => {
|
||||
let {name, altName} = featureCls.meta;
|
||||
let prop = altName || name;
|
||||
|
||||
if (this[prop] === true && this.Mod[name]) {
|
||||
features.forEach((feature) => {
|
||||
let {property, name} = feature;
|
||||
if (this[property] === true && this.Mod[name]) {
|
||||
this.Mod[name].init();
|
||||
}
|
||||
});
|
||||
|
@ -1785,11 +1790,11 @@ export class TableFilter {
|
|||
}
|
||||
//empty
|
||||
else if (hasEM) {
|
||||
occurence = !cell.hasChildNodes() || isEmpty(cellValue);
|
||||
occurence = !cell.hasChildNodes();
|
||||
}
|
||||
//non-empty
|
||||
else if (hasNM) {
|
||||
occurence = cell.hasChildNodes() && !isEmpty(cellValue);
|
||||
occurence = cell.hasChildNodes();
|
||||
} else {
|
||||
occurence = contains(term, cellValue,
|
||||
this.isExactMatch(colIdx), this.caseSensitive);
|
||||
|
@ -1875,11 +1880,11 @@ export class TableFilter {
|
|||
}
|
||||
//empty
|
||||
else if (hasEM) {
|
||||
occurence = !cell.hasChildNodes() || isEmpty(cellValue);
|
||||
occurence = !cell.hasChildNodes();
|
||||
}
|
||||
//non-empty
|
||||
else if (hasNM) {
|
||||
occurence = cell.hasChildNodes() && !isEmpty(cellValue);
|
||||
occurence = cell.hasChildNodes();
|
||||
} else {
|
||||
// If numeric type data, perform a strict equality test and
|
||||
// fallback to unformatted number string comparison
|
||||
|
|
|
@ -32,7 +32,6 @@ table.TF
|
|||
&.resp
|
||||
display block
|
||||
overflow-x auto
|
||||
overflow-y hidden
|
||||
|
||||
.sort-arrow
|
||||
position initial
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
highlight_column: true
|
||||
},
|
||||
no_results_message: true,
|
||||
responsive: true,
|
||||
custom_options: {
|
||||
cols:[3],
|
||||
texts: [
|
||||
|
|
|
@ -40,10 +40,6 @@
|
|||
page_length: true,
|
||||
sort: true
|
||||
},
|
||||
responsive: true,
|
||||
help_instructions: {
|
||||
container_adjust_left_position: 30
|
||||
},
|
||||
alternate_rows: true,
|
||||
btn_reset: true,
|
||||
rows_counter: true,
|
||||
|
|
|
@ -100,43 +100,19 @@ test('Can sort options', function() {
|
|||
tf.destroy();
|
||||
tf = new TableFilter('demo', {
|
||||
base_path: '../dist/tablefilter/',
|
||||
col_0: 'checklist',
|
||||
col_1: 'checklist',
|
||||
col_2: 'checklist',
|
||||
col_3: 'checklist',
|
||||
col_4: 'checklist',
|
||||
col_types: ['string', 'string', 'number', 'number', 'number'],
|
||||
sort_filter_options_asc: [0, 2, 3],
|
||||
sort_filter_options_desc: [1, 4]
|
||||
sort_num_asc: [2, 3],
|
||||
sort_num_desc: [4]
|
||||
});
|
||||
tf.init();
|
||||
|
||||
var flt0 = id(tf.fltIds[0]);
|
||||
var flt1 = id(tf.fltIds[1]);
|
||||
var flt2 = id(tf.fltIds[2]);
|
||||
var flt3 = id(tf.fltIds[3]);
|
||||
var flt4 = id(tf.fltIds[4]);
|
||||
|
||||
deepEqual(
|
||||
flt0.getElementsByTagName('li')[1].firstChild.firstChild.value,
|
||||
'Adelaide',
|
||||
'First option value for column 0'
|
||||
);
|
||||
deepEqual(
|
||||
flt0.getElementsByTagName('li')[2].firstChild.firstChild.value,
|
||||
'Sydney',
|
||||
'Last option value for column 0'
|
||||
);
|
||||
deepEqual(
|
||||
flt1.getElementsByTagName('li')[1].firstChild.firstChild.value,
|
||||
'Perth',
|
||||
'First option value for column 1'
|
||||
);
|
||||
deepEqual(
|
||||
flt1.getElementsByTagName('li')[6].firstChild.firstChild.value,
|
||||
'Adelaide',
|
||||
'Last option value for column 1'
|
||||
);
|
||||
deepEqual(
|
||||
flt2.getElementsByTagName('li')[1].firstChild.firstChild.value,
|
||||
'286',
|
||||
|
@ -206,55 +182,6 @@ test('Can select empty and non-empty options', function() {
|
|||
'Filter 3 options values attribute');
|
||||
});
|
||||
|
||||
// issue 714, clear filter text
|
||||
module('Clear filter text');
|
||||
test('Can define clear filter text for each column', function() {
|
||||
tf.clearFilters();
|
||||
tf.destroy();
|
||||
tf = new TableFilter('demo', {
|
||||
base_path: '../dist/tablefilter/',
|
||||
col_2: 'checklist',
|
||||
col_3: 'checklist',
|
||||
col_4: 'checklist',
|
||||
clear_filter_text: [null, null, 'clear 2', 'clear 3', 'clear 4']
|
||||
});
|
||||
tf.init();
|
||||
|
||||
var flt2 = tf.getFilterElement(2).getElementsByTagName('li');
|
||||
var flt3 = tf.getFilterElement(3).getElementsByTagName('li');
|
||||
var flt4 = tf.getFilterElement(4).getElementsByTagName('li');
|
||||
|
||||
deepEqual(flt2[0].getElementsByTagName('label')[0].innerText,
|
||||
'clear 2', 'clear text filter 2');
|
||||
deepEqual(flt3[0].getElementsByTagName('label')[0].innerText,
|
||||
'clear 3', 'clear text filter 3');
|
||||
deepEqual(flt4[0].getElementsByTagName('label')[0].innerText,
|
||||
'clear 4', 'clear text filter 4');
|
||||
});
|
||||
test('Can define clear filter text globally', function() {
|
||||
tf.clearFilters();
|
||||
tf.destroy();
|
||||
tf = new TableFilter('demo', {
|
||||
base_path: '../dist/tablefilter/',
|
||||
col_2: 'checklist',
|
||||
col_3: 'checklist',
|
||||
col_4: 'checklist',
|
||||
clear_filter_text: 'reset'
|
||||
});
|
||||
tf.init();
|
||||
|
||||
var flt2 = tf.getFilterElement(2).getElementsByTagName('li');
|
||||
var flt3 = tf.getFilterElement(3).getElementsByTagName('li');
|
||||
var flt4 = tf.getFilterElement(4).getElementsByTagName('li');
|
||||
|
||||
deepEqual(flt2[0].getElementsByTagName('label')[0].innerText,
|
||||
'reset', 'clear text filter 2');
|
||||
deepEqual(flt3[0].getElementsByTagName('label')[0].innerText,
|
||||
'reset', 'clear text filter 3');
|
||||
deepEqual(flt4[0].getElementsByTagName('label')[0].innerText,
|
||||
'reset', 'clear text filter 4');
|
||||
});
|
||||
|
||||
module('Tear down');
|
||||
test('TableFilter removed', function() {
|
||||
tf.destroy();
|
||||
|
|
|
@ -6,7 +6,6 @@ var tf = new TableFilter('demo', {
|
|||
tf.init();
|
||||
|
||||
var clearButton = tf.feature('clearButton');
|
||||
|
||||
module('Sanity checks');
|
||||
test('Clear button component', function() {
|
||||
deepEqual(typeof clearButton, 'object', 'ClearButton instanciated');
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
(function(TableFilter) {
|
||||
var id = function (id) { return document.getElementById(id); };
|
||||
|
||||
(function(win, TableFilter){
|
||||
// TODO: add sort to test it with different column types
|
||||
var tf = new TableFilter('demo', {
|
||||
base_path: '../dist/tablefilter/',
|
||||
|
@ -19,6 +17,7 @@
|
|||
]
|
||||
});
|
||||
tf.init();
|
||||
window.tf = tf;
|
||||
|
||||
module('Sanity checks');
|
||||
test('Data types', function() {
|
||||
|
@ -280,7 +279,7 @@
|
|||
tf.filter();
|
||||
|
||||
// assert
|
||||
deepEqual(tf.getValidRows().length, 7, 'Expected rows');
|
||||
deepEqual(tf.getValidRows().length, 8, 'Expected rows');
|
||||
});
|
||||
|
||||
module('Locale helpers');
|
||||
|
@ -301,92 +300,10 @@
|
|||
deepEqual(result, '.', 'Decimal separator for given column');
|
||||
});
|
||||
|
||||
module('Data types filters options sorting');
|
||||
test('Can sort date types', function () {
|
||||
// setup
|
||||
tf.clearFilters();
|
||||
tf.destroy();
|
||||
tf = new TableFilter('demo', {
|
||||
base_path: '../dist/tablefilter/',
|
||||
col_6: 'checklist',
|
||||
col_7: 'multiple',
|
||||
col_8: 'checklist',
|
||||
col_10: 'select',
|
||||
col_types: [
|
||||
null, null, null,
|
||||
{type: 'formatted-number', decimal: ',', thousands: ','},
|
||||
'formatted-number', null,
|
||||
{type: 'date', locale: 'fr',},
|
||||
{type: 'date', locale: 'en', format: '{dd}-{MM}-{yyyy|yy}'},
|
||||
{
|
||||
type: 'date', locale: 'en',
|
||||
format: ['{dd}-{months}-{yyyy|yy}']
|
||||
},
|
||||
'IpAddress',
|
||||
{
|
||||
type: 'date', locale: 'en',
|
||||
format: ['{yyyy|yy}-{MM}-{dd} {HH}:{mm}:{ss}']
|
||||
}
|
||||
],
|
||||
sort_filter_options_asc: [6, 7],
|
||||
sort_filter_options_desc: [8, 10]
|
||||
});
|
||||
|
||||
// act
|
||||
tf.init();
|
||||
|
||||
var flt6 = id(tf.fltIds[6]);
|
||||
var flt7 = id(tf.fltIds[7]);
|
||||
var flt8 = id(tf.fltIds[8]);
|
||||
var flt10 = id(tf.fltIds[10]);
|
||||
|
||||
// assert
|
||||
deepEqual(
|
||||
flt6.getElementsByTagName('li')[1].firstChild.firstChild.value,
|
||||
'19/1/1984',
|
||||
'First option value for column 6'
|
||||
);
|
||||
deepEqual(
|
||||
flt6.getElementsByTagName('li')[20].firstChild.firstChild.value,
|
||||
'3/7/2002',
|
||||
'Last option value for column 6'
|
||||
);
|
||||
deepEqual(
|
||||
flt7.options[1].value,
|
||||
'1/19/1984',
|
||||
'First option value for column 7'
|
||||
);
|
||||
deepEqual(
|
||||
flt7.options[20].value,
|
||||
'7/3/2002',
|
||||
'Last option value for column 7'
|
||||
);
|
||||
deepEqual(
|
||||
flt8.getElementsByTagName('li')[1].firstChild.firstChild.value,
|
||||
'3-Jul-2002',
|
||||
'First option value for column 8'
|
||||
);
|
||||
deepEqual(
|
||||
flt8.getElementsByTagName('li')[20].firstChild.firstChild.value,
|
||||
'19-Jan-1984',
|
||||
'Last option value for column 8'
|
||||
);
|
||||
deepEqual(
|
||||
flt10.options[1].value,
|
||||
'03-11-21 12:02:04',
|
||||
'First option value for column 10'
|
||||
);
|
||||
deepEqual(
|
||||
flt10.options[19].value,
|
||||
'1899-11-27 02:02:04',
|
||||
'Last option value for column 10'
|
||||
);
|
||||
});
|
||||
|
||||
module('Tear-down');
|
||||
test('can destroy TableFilter DOM elements', function() {
|
||||
tf.destroy();
|
||||
deepEqual(tf.isInitialized(), false, 'Filters removed');
|
||||
});
|
||||
|
||||
})(TableFilter);
|
||||
})(window, TableFilter);
|
||||
|
|
|
@ -157,31 +157,24 @@ test('Can enable options sorting on a column basis', function() {
|
|||
deepEqual(flt4.options[7].value, '40', 'Last option value for column 4');
|
||||
});
|
||||
|
||||
test('Can sort options in asc and desc manner', function() {
|
||||
test('Can sort numeric options in asc and desc manner', function() {
|
||||
tf.clearFilters();
|
||||
tf.destroy();
|
||||
tf = new TableFilter('demo', {
|
||||
base_path: '../dist/tablefilter/',
|
||||
col_0: 'select',
|
||||
col_2: 'multiple',
|
||||
col_3: 'select',
|
||||
col_4: 'multiple',
|
||||
col_types: ['string', 'string', 'number', 'number', 'number'],
|
||||
case_sensitive: true,
|
||||
sort_filter_options_asc: [2, 3],
|
||||
sort_filter_options_desc: [0, 4]
|
||||
sort_num_asc: [2, 3],
|
||||
sort_num_desc: [4]
|
||||
});
|
||||
tf.init();
|
||||
|
||||
var flt0 = id(tf.fltIds[0]);
|
||||
var flt2 = id(tf.fltIds[2]);
|
||||
var flt3 = id(tf.fltIds[3]);
|
||||
var flt4 = id(tf.fltIds[4]);
|
||||
|
||||
deepEqual(flt0.options[1].value, 'Sydney',
|
||||
'First option value for column 0');
|
||||
deepEqual(flt0.options[2].value, 'Adelaide',
|
||||
'Last option value for column 0');
|
||||
deepEqual(flt2.options[1].value, '286', 'First option value for column 2');
|
||||
deepEqual(flt2.options[7].value, '2781', 'Last option value for column 2');
|
||||
deepEqual(flt3.options[1].value, '.6', 'First option value for column 3');
|
||||
|
@ -190,51 +183,6 @@ test('Can sort options in asc and desc manner', function() {
|
|||
deepEqual(flt4.options[7].value, '4.3', 'Last option value for column 4');
|
||||
});
|
||||
|
||||
// issue 714, clear filter text
|
||||
module('Clear filter text');
|
||||
test('Can define clear filter text for each column', function() {
|
||||
tf.clearFilters();
|
||||
tf.destroy();
|
||||
tf = new TableFilter('demo', {
|
||||
base_path: '../dist/tablefilter/',
|
||||
col_2: 'multiple',
|
||||
col_3: 'select',
|
||||
col_4: 'multiple',
|
||||
clear_filter_text: [null, null, 'clear 2', 'clear 3', 'clear 4']
|
||||
});
|
||||
tf.init();
|
||||
|
||||
var flt2 = tf.getFilterElement(2);
|
||||
var flt3 = tf.getFilterElement(3);
|
||||
var flt4 = tf.getFilterElement(4);
|
||||
|
||||
deepEqual(flt2.options[0].innerHTML, 'clear 2', 'clear text filter 2');
|
||||
deepEqual(flt3.options[0].innerHTML, 'clear 3', 'clear text filter 3');
|
||||
deepEqual(flt4.options[0].innerHTML, 'clear 4', 'clear text filter 4');
|
||||
});
|
||||
test('Can define clear filter text globally', function() {
|
||||
tf.clearFilters();
|
||||
tf.destroy();
|
||||
tf = new TableFilter('demo', {
|
||||
base_path: '../dist/tablefilter/',
|
||||
col_2: 'multiple',
|
||||
col_3: 'select',
|
||||
col_4: 'multiple',
|
||||
clear_filter_text: 'reset'
|
||||
});
|
||||
tf.init();
|
||||
|
||||
var flt2 = tf.getFilterElement(2);
|
||||
var flt3 = tf.getFilterElement(3);
|
||||
var flt4 = tf.getFilterElement(4);
|
||||
|
||||
deepEqual(flt2.options[0].innerHTML, 'reset', 'clear text filter 2');
|
||||
deepEqual(flt3.options[0].innerHTML, 'reset', 'clear text filter 3');
|
||||
deepEqual(flt4.options[0].innerHTML, 'reset', 'clear text filter 4');
|
||||
});
|
||||
|
||||
|
||||
module('Tear down');
|
||||
test('TableFilter removed', function() {
|
||||
tf.destroy();
|
||||
deepEqual(id(tf.fltIds[3]), null, 'Filter is removed');
|
||||
|
|
|
@ -72,14 +72,7 @@
|
|||
tf.clearFilters();
|
||||
tf.setFilterValue(4, '[empty]');
|
||||
tf.filter();
|
||||
var filteredData = tf.getFilteredData();
|
||||
|
||||
deepEqual(tf.getValidRows().length, 1, 'Expected match');
|
||||
deepEqual(
|
||||
filteredData[0],
|
||||
[6, ['Adelaide', 'Perth', '2781', '3.1', '']],
|
||||
'Expected row data'
|
||||
);
|
||||
deepEqual(tf.getValidRows().length, 0, 'No matches expected');
|
||||
});
|
||||
|
||||
test('Non-empty operator - [nonempty]', function() {
|
||||
|
@ -103,7 +96,7 @@
|
|||
tf.setFilterValue(4, '[nonempty]');
|
||||
tf.filter();
|
||||
|
||||
deepEqual(tf.getValidRows().length, 6, 'Expected number of matches');
|
||||
deepEqual(tf.getValidRows().length, 7, 'Expected number of matches');
|
||||
});
|
||||
|
||||
test('Or operator - ||', function() {
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>TableFilter help pop-up with responsive behaviour</title>
|
||||
<link rel="stylesheet" href="libs/qunit/qunit.css">
|
||||
<script src="libs/qunit/qunit.js"></script>
|
||||
<script src="libs/polyfill.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div style="float: right; width: 80%; border: 1px solid #f4f4f4;"></div>
|
||||
<table id="demo" cellpadding="0" cellspacing="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>From</th>
|
||||
<th>Destination</th>
|
||||
<th>Road Distance (km)</th>
|
||||
<th>By Air (hrs)</th>
|
||||
<th>By Rail (hrs)</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Sydney</strong></td>
|
||||
<td>Adelaide</td>
|
||||
<td>1412</td>
|
||||
<td>1.4</td>
|
||||
<td>25.3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Sydney</strong></td>
|
||||
<td>Brisbane</td>
|
||||
<td>982</td>
|
||||
<td>1.5</td>
|
||||
<td>16</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Sydney</strong></td>
|
||||
<td>Canberra</td>
|
||||
<td>286</td>
|
||||
<td>.6</td>
|
||||
<td>4.3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Sydney</strong></td>
|
||||
<td>Melbourne</td>
|
||||
<td>872</td>
|
||||
<td>1.1</td>
|
||||
<td>10.5</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Adelaide</strong></td>
|
||||
<td>Perth</td>
|
||||
<td>2781</td>
|
||||
<td>3.1</td>
|
||||
<td>38</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Adelaide</strong></td>
|
||||
<td>Alice Springs</td>
|
||||
<td>1533</td>
|
||||
<td>2</td>
|
||||
<td>20.25</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Adelaide</strong></td>
|
||||
<td>Brisbane</td>
|
||||
<td>2045</td>
|
||||
<td>2.15</td>
|
||||
<td>40</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<script src="../dist/tablefilter/tablefilter.js"></script>
|
||||
<script src="test-help-responsive.js"></script>
|
||||
|
||||
<div id="qunit"></div>
|
||||
<div id="qunit-fixture"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,70 +0,0 @@
|
|||
|
||||
var tf = new TableFilter('demo', {
|
||||
base_path: '../dist/tablefilter/',
|
||||
help_instructions: {
|
||||
container_adjust_left_position: 20
|
||||
},
|
||||
responsive: true
|
||||
});
|
||||
tf.init();
|
||||
|
||||
var help = tf.feature('help');
|
||||
module('Sanity checks');
|
||||
test('Button element', function() {
|
||||
deepEqual(typeof help, 'object', 'Help instanciated');
|
||||
notEqual(help.btn, null, 'btn property');
|
||||
});
|
||||
|
||||
module('Pop-up container position');
|
||||
test('Help UI elements', function() {
|
||||
var container = help.cont,
|
||||
helpBtn = help.btn;
|
||||
deepEqual(container.nodeName, 'DIV', 'Help container');
|
||||
deepEqual(helpBtn.nodeName, 'SPAN', 'Help button');
|
||||
});
|
||||
|
||||
// 772 issue: pop-up container position when table feature horizontal scroll
|
||||
test('When table has horizontal scroll', function() {
|
||||
// setup
|
||||
tf.dom().scrollLeft = 10000;
|
||||
|
||||
// act
|
||||
help.toggle();
|
||||
|
||||
// assert
|
||||
deepEqual(
|
||||
parseFloat(help.cont.style.left),
|
||||
(help.btn.offsetLeft
|
||||
- tf.dom().scrollLeft
|
||||
+ help.contAdjustLeftPosition),
|
||||
'Pop-up container position'
|
||||
);
|
||||
});
|
||||
|
||||
test('When table does not have horizontal scroll', function() {
|
||||
tf.destroy();
|
||||
tf = new TableFilter('demo', {
|
||||
base_path: '../dist/tablefilter/',
|
||||
help_instructions: true,
|
||||
responsive: false
|
||||
});
|
||||
tf.init();
|
||||
var help = tf.feature('help');
|
||||
|
||||
// act
|
||||
help.toggle();
|
||||
|
||||
// assert
|
||||
deepEqual(help.cont.style.left, '', 'Pop-up container position');
|
||||
});
|
||||
|
||||
module('Tear-down');
|
||||
test('can destroy Help UI component', function() {
|
||||
// act
|
||||
tf.destroy();
|
||||
var help = tf.feature('help');
|
||||
|
||||
// assert
|
||||
deepEqual(help.btn, null, 'Help button removed');
|
||||
deepEqual(help.cont, null, 'Help pop-up container removed');
|
||||
});
|
|
@ -1,6 +1,6 @@
|
|||
const webpack = require('webpack');
|
||||
const path = require('path');
|
||||
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
|
||||
const Clean = require('clean-webpack-plugin');
|
||||
const StringReplacePlugin = require('string-replace-webpack-plugin');
|
||||
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
|
||||
const fs = require('fs');
|
||||
|
@ -52,14 +52,14 @@ module.exports = {
|
|||
}
|
||||
]
|
||||
},
|
||||
// devtool: 'source-map',
|
||||
devtool: 'source-map',
|
||||
optimization: {
|
||||
minimizer: [
|
||||
new UglifyJsPlugin({
|
||||
// sourceMap: true,
|
||||
sourceMap: true,
|
||||
uglifyOptions: {
|
||||
beautify: false,
|
||||
warnings: false,
|
||||
compress: {warnings: false},
|
||||
comments: false,
|
||||
keep_fnames: true
|
||||
}
|
||||
|
@ -67,9 +67,7 @@ module.exports = {
|
|||
]
|
||||
},
|
||||
plugins: [
|
||||
new CleanWebpackPlugin({
|
||||
cleanOnceBeforeBuildPatterns: [path.join(process.cwd(), 'dist')]
|
||||
}),
|
||||
new Clean(['dist']),
|
||||
new webpack.optimize.AggressiveMergingPlugin(),
|
||||
new StringReplacePlugin(),
|
||||
new webpack.optimize.MinChunkSizePlugin({
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const webpack = require('webpack');
|
||||
const webpackConfig = require('./webpack.config.js');
|
||||
const path = require('path');
|
||||
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
|
||||
const Clean = require('clean-webpack-plugin');
|
||||
|
||||
module.exports = {
|
||||
mode: 'development',
|
||||
|
@ -23,9 +23,7 @@ module.exports = {
|
|||
},
|
||||
devtool: 'source-map',
|
||||
plugins: [
|
||||
new CleanWebpackPlugin({
|
||||
cleanOnceBeforeBuildPatterns: [path.join(process.cwd(), 'dist')]
|
||||
}),
|
||||
new Clean(['dist']),
|
||||
new webpack.LoaderOptionsPlugin({
|
||||
debug: true,
|
||||
options: {
|
||||
|
|
Loading…
Reference in a new issue