1
0
Fork 0
mirror of https://github.com/koalyptus/TableFilter.git synced 2024-05-12 11:27:24 +02:00

Merge pull request #682 from koalyptus/feature-registering

Feature registering
This commit is contained in:
koalyptus 2019-02-16 22:02:55 +11:00 committed by GitHub
commit 0a69a99dc5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
38 changed files with 1026 additions and 1183 deletions

4
dist/starter.html vendored
View file

@ -1,10 +1,10 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<title>tablefilter v0.6.76 - Starter</title> <title>tablefilter v0.6.78 - Starter</title>
</head> </head>
<body> <body>
<h1>tablefilter v0.6.76</h1> <h1>tablefilter v0.6.78</h1>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1880
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{ {
"name": "tablefilter", "name": "tablefilter",
"version": "0.6.77", "version": "0.6.78",
"description": "A Javascript library making HTML tables filterable and a bit more", "description": "A Javascript library making HTML tables filterable and a bit more",
"license": "MIT", "license": "MIT",
"author": { "author": {
@ -40,17 +40,17 @@
"tag": "next" "tag": "next"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "7.2.2", "@babel/core": "7.3.3",
"@babel/preset-env": "7.3.1", "@babel/preset-env": "7.3.1",
"babel-eslint": "10.0.0", "babel-eslint": "10.0.0",
"babel-loader": "^8.0.2", "babel-loader": "^8.0.2",
"babel-preset-env": "1.7.0", "babel-preset-env": "1.7.0",
"clean-webpack-plugin": "^1.0.0", "clean-webpack-plugin": "^1.0.0",
"codecov": "3.1.0", "codecov": "3.2.0",
"diacritics": "1.3.0", "diacritics": "1.3.0",
"esdoc": "1.1.0", "esdoc": "1.1.0",
"esdoc-standard-plugin": "1.0.0", "esdoc-standard-plugin": "1.0.0",
"eslint": "5.0.1", "eslint": "5.14.0",
"format-number": "3.0.0", "format-number": "3.0.0",
"grunt": "^1.0.1", "grunt": "^1.0.1",
"grunt-cli": "1.3.2", "grunt-cli": "1.3.2",

View file

@ -1,19 +1,3 @@
import {DateType} from './modules/dateType';
import {Help} from './modules/help';
import {State} from './modules/state';
import {GridLayout} from './modules/gridLayout';
import {Loader} from './modules/loader';
import {HighlightKeyword} from './modules/highlightKeywords';
import {PopupFilter} from './modules/popupFilter';
import {MarkActiveColumns} from './modules/markActiveColumns';
import {RowsCounter} from './modules/rowsCounter';
import {StatusBar} from './modules/statusBar';
import {ClearButton} from './modules/clearButton';
import {AlternateRows} from './modules/alternateRows';
import {NoResults} from './modules/noResults';
import {Paging} from './modules/paging';
import {Toolbar} from './modules/toolbar';
/** /**
* Filter types * Filter types
*/ */
@ -132,75 +116,3 @@ export const IP_ADDRESS = 'ipaddress';
* @type {Number} * @type {Number}
*/ */
export const AUTO_FILTER_DELAY = 750; 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
}
};

View file

@ -21,7 +21,7 @@ export default class AdapterEzEditTable extends Feature {
* @param {Object} cfg Configuration options for ezEditTable library * @param {Object} cfg Configuration options for ezEditTable library
*/ */
constructor(tf, cfg) { constructor(tf, cfg) {
super(tf, cfg.name); super(tf, AdapterEzEditTable);
/** /**
* Module description * Module description
@ -505,3 +505,5 @@ export default class AdapterEzEditTable extends Feature {
this.initialized = false; this.initialized = false;
} }
} }
AdapterEzEditTable.meta = {altName: 'advancedGrid'};

View file

@ -33,7 +33,7 @@ export default class ColOps extends Feature {
* @param {Object} opts Configuration object * @param {Object} opts Configuration object
*/ */
constructor(tf, opts) { constructor(tf, opts) {
super(tf, opts.name); super(tf, ColOps);
/** /**
* Callback fired before columns operations start * Callback fired before columns operations start

View file

@ -23,7 +23,7 @@ export default class ColsVisibility extends Feature {
* @param {Object} Configuration object * @param {Object} Configuration object
*/ */
constructor(tf, f) { constructor(tf, f) {
super(tf, f.name); super(tf, ColsVisibility);
// Configuration object // Configuration object
let cfg = this.config; let cfg = this.config;

View file

@ -18,7 +18,7 @@ export default class FiltersVisibility extends Feature {
* @param {Object} Configuration object * @param {Object} Configuration object
*/ */
constructor(tf, f) { constructor(tf, f) {
super(tf, f.name); super(tf, FiltersVisibility);
/** /**
* Module name * Module name

View file

@ -20,7 +20,7 @@ export default class AdapterSortableTable extends Feature {
* @param {Object} opts Configuration object * @param {Object} opts Configuration object
*/ */
constructor(tf, opts) { constructor(tf, opts) {
super(tf, opts.name); super(tf, AdapterSortableTable);
/** /**
* Module name * Module name
@ -508,6 +508,8 @@ export default class AdapterSortableTable extends Feature {
} }
AdapterSortableTable.meta = {altName: 'sort'};
//Converters //Converters
function ipAddress(value) { function ipAddress(value) {
let vals = value.split('.'); let vals = value.split('.');

View file

@ -1,3 +1,4 @@
import {toCamelCase} from './string';
const NOT_IMPLEMENTED = 'Not implemented.'; const NOT_IMPLEMENTED = 'Not implemented.';
@ -8,9 +9,11 @@ export class Feature {
/** /**
* Creates an instance of Feature * Creates an instance of Feature
* @param {Object} tf TableFilter instance * @param {Object} tf TableFilter instance
* @param {String} feature Feature name known by TableFilter * @param {Class} feature Feature class for TableFilter registration
*/ */
constructor(tf, feature) { constructor(tf, cls) {
cls.meta = cls.meta || {};
/** /**
* TableFilter instance * TableFilter instance
* @type {TableFilter} * @type {TableFilter}
@ -18,16 +21,18 @@ export class Feature {
this.tf = tf; this.tf = tf;
/** /**
* Feature name * Feature name is the camelised class name as per TableFilter's
* convention
* @type {String} * @type {String}
*/ */
this.feature = feature; this.feature = cls.meta.altName || cls.meta.name
|| toCamelCase(cls.name);
/** /**
* TableFilter feature setting * TableFilter feature setting
* @type {Boolean} * @type {Boolean}
*/ */
this.enabled = tf[feature]; this.enabled = tf[this.feature];
/** /**
* TableFilter configuration * TableFilter configuration

View file

@ -14,9 +14,10 @@ export class AlternateRows extends Feature {
* @param {Object} tf TableFilter instance * @param {Object} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'alternateRows'); super(tf, AlternateRows);
let config = this.config; let config = this.config;
/** /**
* Css class for even rows (default: 'even') * Css class for even rows (default: 'even')
* @type {String} * @type {String}

View file

@ -18,8 +18,8 @@ export class BaseDropdown extends Feature {
* Creates an instance of BaseDropdown * Creates an instance of BaseDropdown
* @param {TableFilter} tf * @param {TableFilter} tf
*/ */
constructor(tf) { constructor(tf, cls) {
super(tf, 'baseDropdown'); super(tf, cls);
let f = this.config; let f = this.config;
@ -33,7 +33,7 @@ export class BaseDropdown extends Feature {
f.filter_options_sorter : f.filter_options_sorter :
null; null;
// TODO: move here all properties shared by Dropdown CheckList // TODO: move here all properties shared by Dropdown and CheckList
/** /**
* Has custom options * Has custom options

View file

@ -22,7 +22,7 @@ export class CheckList extends BaseDropdown {
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'checkList'); super(tf, CheckList);
let f = this.config; let f = this.config;

View file

@ -15,7 +15,7 @@ export class ClearButton extends Feature {
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'btnReset'); super(tf, ClearButton);
let f = this.config.btn_reset || {}; let f = this.config.btn_reset || {};
@ -137,3 +137,6 @@ export class ClearButton extends Feature {
this.initialized = false; this.initialized = false;
} }
} }
// TODO: remove as soon as feature name is fixed
ClearButton.meta = {altName: 'btnReset'};

View file

@ -17,7 +17,7 @@ export class DateType extends Feature {
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'dateType'); super(tf, DateType);
/** /**
* Global locale * Global locale

View file

@ -19,7 +19,7 @@ export class Dropdown extends BaseDropdown {
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'dropdown'); super(tf, Dropdown);
// Configuration object // Configuration object
let f = this.config; let f = this.config;

View file

@ -17,7 +17,7 @@ export class GridLayout extends Feature {
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'gridLayout'); super(tf, GridLayout);
let f = this.config.grid_layout || {}; let f = this.config.grid_layout || {};

View file

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

View file

@ -21,7 +21,7 @@ export class Help extends Feature {
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'help'); super(tf, Help);
let f = this.config.help_instructions || {}; let f = this.config.help_instructions || {};
@ -238,3 +238,6 @@ export class Help extends Feature {
} }
} }
// TODO: remove as soon as feature name is fixed
Help.meta = {alwaysInstantiate: true};

View file

@ -172,3 +172,9 @@ export class HighlightKeyword {
this.highlight(cell, term, this.highlightCssClass); this.highlight(cell, term, this.highlightCssClass);
} }
} }
// TODO: remove as soon as feature name is fixed
HighlightKeyword.meta = {
name: 'highlightKeyword',
altName: 'highlightKeywords'
};

View file

@ -44,7 +44,7 @@ export class Loader extends Feature {
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'loader'); super(tf, Loader);
let f = this.config.loader || {}; let f = this.config.loader || {};

View file

@ -16,7 +16,7 @@ export class MarkActiveColumns extends Feature {
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'markActiveColumns'); super(tf, MarkActiveColumns);
let config = this.config.mark_active_columns || {}; let config = this.config.mark_active_columns || {};

View file

@ -17,7 +17,7 @@ export class NoResults extends Feature {
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'noResults'); super(tf, NoResults);
//configuration object //configuration object
let f = this.config.no_results_message || {}; let f = this.config.no_results_message || {};

View file

@ -21,7 +21,7 @@ export class Paging extends Feature {
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'paging'); super(tf, Paging);
// Configuration object // Configuration object
let f = this.config.paging || {}; let f = this.config.paging || {};

View file

@ -19,7 +19,7 @@ export class PopupFilter extends Feature {
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'popupFilters'); super(tf, PopupFilter);
// Configuration object // Configuration object
let f = this.config.popup_filters || {}; let f = this.config.popup_filters || {};
@ -456,3 +456,6 @@ export class PopupFilter extends Feature {
} }
} }
// TODO: remove as soon as feature name is fixed
PopupFilter.meta = {altName: 'popupFilters'};

View file

@ -17,7 +17,7 @@ export class RowsCounter extends Feature {
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'rowsCounter'); super(tf, RowsCounter);
// TableFilter configuration // TableFilter configuration
let f = this.config.rows_counter || {}; let f = this.config.rows_counter || {};

View file

@ -19,7 +19,7 @@ export class State extends Feature {
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'state'); super(tf, State);
let cfg = this.config.state || {}; let cfg = this.config.state || {};

View file

@ -30,7 +30,7 @@ export class StatusBar extends Feature {
* @param {TableFilter} tf TableFilter instance * @param {TableFilter} tf TableFilter instance
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'statusBar'); super(tf, StatusBar);
// Configuration object // Configuration object
let f = this.config.status_bar || {}; let f = this.config.status_bar || {};

View file

@ -29,7 +29,7 @@ export class Toolbar extends Feature {
* @memberof Toolbar * @memberof Toolbar
*/ */
constructor(tf) { constructor(tf) {
super(tf, 'toolbar'); super(tf, Toolbar);
// Configuration object // Configuration object
let f = this.config.toolbar || {}; let f = this.config.toolbar || {};
@ -219,3 +219,6 @@ export class Toolbar extends Feature {
this.initialized = false; this.initialized = false;
} }
} }
// TODO: remove as soon as feature name is fixed
Toolbar.meta = {alwaysInstantiate: true};

View file

@ -74,3 +74,18 @@ export const contains = (term, data, exactMatch = false, caseSensitive = false,
} }
return regexp.test(data); return regexp.test(data);
}; };
/**
* Camelize a string, cutting the string by multiple separators like
* hyphens, underscores and spaces.
* @param {String} text text to camelize
* @return {String} camelized text
*/
export const toCamelCase = (text = '') => {
return text.replace(/^([A-Z])|[\s-_]+(\w)/g, (match, p1, p2) => {
if (p2) {
return p2.toUpperCase();
}
return p1.toLowerCase();
});
};

View file

@ -2,7 +2,7 @@ import {addEvt, cancelEvt, stopEvt, targetEvt, isKeyPressed} from './event';
import { import {
addClass, createElm, elm, getText, getFirstTextNode, removeClass, tag addClass, createElm, elm, getText, getFirstTextNode, removeClass, tag
} from './dom'; } from './dom';
import {contains, matchCase, rgxEsc, trim} from './string'; import {contains, matchCase, rgxEsc, trim, toCamelCase} from './string';
import { import {
isArray, isEmpty, isFn, isNumber, isObj, isString, isUndef, EMPTY_FN, isArray, isEmpty, isFn, isNumber, isObj, isString, isUndef, EMPTY_FN,
isBoolean isBoolean
@ -17,16 +17,36 @@ import {root} from './root';
import {Emitter} from './emitter'; import {Emitter} from './emitter';
import {Dropdown} from './modules/dropdown'; import {Dropdown} from './modules/dropdown';
import {CheckList} from './modules/checkList'; 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 { import {
INPUT, SELECT, MULTIPLE, CHECKLIST, NONE, INPUT, SELECT, MULTIPLE, CHECKLIST, NONE,
ENTER_KEY, TAB_KEY, ESC_KEY, UP_ARROW_KEY, DOWN_ARROW_KEY, 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'; } from './const';
let doc = root.document; 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 :) * Makes HTML tables filterable and a bit more :)
* *
@ -399,8 +419,7 @@ export class TableFilter {
* Enable/disable single filter mode * Enable/disable single filter mode
* @type {Boolean|Object} * @type {Boolean|Object}
*/ */
this.singleFlt = isObj(f.single_filter) || this.singleFlt = isObj(f.single_filter) || Boolean(f.single_filter);
Boolean(f.single_filter);
/** /**
* Specify columns to be excluded from single filter search, by default * Specify columns to be excluded from single filter search, by default
@ -926,10 +945,8 @@ export class TableFilter {
*/ */
this.ExtRegistry = {}; this.ExtRegistry = {};
// conditionally instantiate required features // instantiate features if needed
this.instantiateFeatures( this.instantiateFeatures(FEATURES);
Object.keys(FEATURES).map((item) => FEATURES[item])
);
} }
/** /**
@ -949,20 +966,16 @@ export class TableFilter {
//loads theme //loads theme
this.loadThemes(); 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 //explicitly initialise features in given order
this.initFeatures([ this.initFeatures([
dateType, DateType,
help, Help,
state, State,
markActiveColumns, MarkActiveColumns,
gridLayout, GridLayout,
loader, Loader,
highlightKeyword, HighlightKeyword,
popupFilter PopupFilter
]); ]);
//filters grid is not generated //filters grid is not generated
@ -1035,13 +1048,13 @@ export class TableFilter {
} }
this.initFeatures([ this.initFeatures([
rowsCounter, RowsCounter,
statusBar, StatusBar,
clearButton, ClearButton,
alternateRows, AlternateRows,
noResults, NoResults,
paging, Paging,
toolbar Toolbar
]); ]);
this.setColWidths(); this.setColWidths();
@ -1250,47 +1263,41 @@ export class TableFilter {
} }
/** /**
* Istantiate the collection of features required by the * Conditionally istantiate each feature class in passed collection if
* configuration and add them to the features registry. A feature is * required by configuration and add it to the features registry. A feature
* described by a `class` and `name` fields and and optional `property` * class meta information contains a `name` field and optional `altName` and
* field: * `alwaysInstantiate` fields
* {
* class: AClass,
* name: 'aClass'
* }
* @param {Array} [features=[]] * @param {Array} [features=[]]
* @private * @private
*/ */
instantiateFeatures(features = []) { instantiateFeatures(features = []) {
features.forEach((feature) => { features.forEach(featureCls => {
// TODO: remove the property field. let Cls = featureCls;
// 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); this.Mod[name] = this.Mod[name] || new Cls(this);
} }
}); });
} }
/** /**
* Initialise the passed features collection. A feature is described by a * Initialise each feature class in passed collection.
* `class` and `name` fields and and optional `property` field:
* {
* class: AClass,
* name: 'aClass'
* }
* @param {Array} [features=[]] * @param {Array} [features=[]]
* @private * @private
*/ */
initFeatures(features = []) { initFeatures(features = []) {
features.forEach((feature) => { features.forEach(featureCls => {
let {property, name} = feature; let {name, altName} = featureCls.meta;
if (this[property] === true && this.Mod[name]) { let prop = altName || name;
if (this[prop] === true && this.Mod[name]) {
this.Mod[name].init(); this.Mod[name].init();
} }
}); });

View file

@ -6,6 +6,7 @@ var tf = new TableFilter('demo', {
tf.init(); tf.init();
var clearButton = tf.feature('clearButton'); var clearButton = tf.feature('clearButton');
module('Sanity checks'); module('Sanity checks');
test('Clear button component', function() { test('Clear button component', function() {
deepEqual(typeof clearButton, 'object', 'ClearButton instanciated'); deepEqual(typeof clearButton, 'object', 'ClearButton instanciated');