1
0
Fork 0
mirror of https://github.com/koalyptus/TableFilter.git synced 2024-06-20 14:45:15 +02:00

Merge branch 'master' into 358-increase-coverage

This commit is contained in:
Max Guglielmi 2017-01-03 13:07:41 +11:00
commit 222587f1f3
42 changed files with 732 additions and 562 deletions

1
.gitignore vendored
View file

@ -5,7 +5,6 @@ report
.grunt
npm-debug.log
*.js.map
.codio
.settings
.vscode

4
dist/starter.html vendored
View file

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

View file

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

View file

@ -1,6 +1,6 @@
/**
* tablefilter v0.4.21 by Max Guglielmi
* build date: 2016-12-09T12:28:56.305Z
* tablefilter v0.4.29 by Max Guglielmi
* build date: 2017-01-01T11:08:21.972Z
* 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}

View file

@ -1,6 +1,6 @@
/**
* tablefilter v0.4.21 by Max Guglielmi
* build date: 2016-12-09T12:28:56.305Z
* tablefilter v0.4.29 by Max Guglielmi
* build date: 2017-01-01T11:08:21.972Z
* MIT License
*/
.activeHeader{background-color:#66afe9 !important;color:#fff !important}

View file

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

View file

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

View file

@ -1,6 +1,6 @@
/**
* tablefilter v0.4.21 by Max Guglielmi
* build date: 2016-12-09T12:28:56.305Z
* tablefilter v0.4.29 by Max Guglielmi
* build date: 2017-01-01T11:08:21.972Z
* 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}

View file

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

File diff suppressed because one or more lines are too long

1
dist/tablefilter/tablefilter.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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1,6 @@
{
"name": "tablefilter",
"version": "0.4.21",
"version": "0.4.29",
"description": "A Javascript library making HTML tables filterable and a bit more",
"license": "MIT",
"author": {
@ -38,7 +38,7 @@
"tag": "next"
},
"devDependencies": {
"babel-core": "^6.20.0",
"babel-core": "^6.21.0",
"babel-eslint": "7.1.1",
"babel-loader": "^6.2.9",
"babel-plugin-transform-es2015-classes": "^6.18.0",

View file

@ -34,11 +34,10 @@ export const addEvt = (obj, type, func, capture) => {
* the capturing or in the bubbling phase
*/
export const removeEvt = (obj, type, func, capture) => {
if (obj.detachEvent) {
obj.detachEvent('on' + type, func);
}
else if (obj.removeEventListener) {
if (obj.removeEventListener) {
obj.removeEventListener(type, func, capture);
} else if (obj.detachEvent) {
obj.detachEvent('on' + type, func);
} else {
obj['on' + type] = null;
}
@ -49,7 +48,7 @@ export const removeEvt = (obj, type, func, capture) => {
*
* @param {Event} evt Event on the DOM
*/
export const stopEvt = evt =>{
export const stopEvt = (evt) => {
if (!evt) {
evt = root.event;
}
@ -66,7 +65,7 @@ export const stopEvt = evt =>{
*
* @param {Event} evt Event on the DOM
*/
export const cancelEvt = evt => {
export const cancelEvt = (evt) => {
if (!evt) {
evt = root.event;
}
@ -83,7 +82,7 @@ export const cancelEvt = evt => {
* @param {Event} evt Event on the DOM
* @returns {DOMElement}
*/
export const targetEvt = evt => {
export const targetEvt = (evt) => {
if (!evt) {
evt = root.event;
}
@ -96,7 +95,7 @@ export const targetEvt = evt => {
* @param {Event} evt Event on the DOM
* @returns {Number}
*/
export const keyCode = evt => {
export const keyCode = (evt) => {
return evt.charCode ? evt.charCode :
(evt.keyCode ? evt.keyCode : (evt.which ? evt.which : 0));
};

View file

@ -207,9 +207,9 @@ export default class AdapterEzEditTable extends Feature {
nextRowIndex,
paging = tf.feature('paging'),
//pgup/pgdown keys
d = (keyCode === 34 || keyCode === 33 ?
d = keyCode === 34 || keyCode === 33 ?
(paging && paging.pagingLength || et.nbRowsPerPage) :
1);
1;
//If next row is not valid, next valid filtered row needs to be
//calculated
@ -332,35 +332,35 @@ export default class AdapterEzEditTable extends Feature {
if (cfg.default_selection === 'row') {
let fnB = cfg.on_before_selected_row;
cfg.on_before_selected_row = function () {
onBeforeSelection(arguments[0], arguments[1], arguments[2]);
var args = arguments;
onBeforeSelection(args[0], args[1], args[2]);
if (fnB) {
fnB.call(
null, arguments[0], arguments[1], arguments[2]);
fnB.call(null, args[0], args[1], args[2]);
}
};
let fnA = cfg.on_after_selected_row;
cfg.on_after_selected_row = function () {
onAfterSelection(arguments[0], arguments[1], arguments[2]);
var args = arguments;
onAfterSelection(args[0], args[1], args[2]);
if (fnA) {
fnA.call(
null, arguments[0], arguments[1], arguments[2]);
fnA.call(null, args[0], args[1], args[2]);
}
};
} else {
let fnD = cfg.on_before_selected_cell;
cfg.on_before_selected_cell = function () {
onBeforeSelection(arguments[0], arguments[1], arguments[2]);
var args = arguments;
onBeforeSelection(args[0], args[1], args[2]);
if (fnD) {
fnD.call(
null, arguments[0], arguments[1], arguments[2]);
fnD.call(null, args[0], args[1], args[2]);
}
};
let fnC = cfg.on_after_selected_cell;
cfg.on_after_selected_cell = function () {
onAfterSelection(arguments[0], arguments[1], arguments[2]);
var args = arguments;
onAfterSelection(args[0], args[1], args[2]);
if (fnC) {
fnC.call(
null, arguments[0], arguments[1], arguments[2]);
fnC.call(null, args[0], args[1], args[2]);
}
};
}
@ -369,6 +369,7 @@ export default class AdapterEzEditTable extends Feature {
//Added or removed rows, TF rows number needs to be re-calculated
let fnE = cfg.on_added_dom_row;
cfg.on_added_dom_row = function () {
var args = arguments;
tf.nbFilterableRows++;
if (!tf.paging) {
tf.emitter.emit('rows-changed', tf, this);
@ -382,12 +383,13 @@ export default class AdapterEzEditTable extends Feature {
tf.feature('alternateRows').init();
}
if (fnE) {
fnE.call(null, arguments[0], arguments[1], arguments[2]);
fnE.call(null, args[0], args[1], args[2]);
}
};
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.emitter.emit('rows-changed', tf, this);
@ -401,7 +403,7 @@ export default class AdapterEzEditTable extends Feature {
tf.feature('alternateRows').init();
}
if (fnF) {
fnF.call(null, arguments[0], arguments[1]);
fnF.call(null, args[0], args[1]);
}
};
}

View file

@ -1,6 +1,6 @@
import {Feature} from '../../feature';
import {createText, elm} from '../../dom';
import {isArray, isFn, isUndef} from '../../types';
import {isArray, isFn, isUndef, EMPTY_FN} from '../../types';
const EVENTS = [
'after-filtering',
@ -27,14 +27,14 @@ export default class ColOps extends Feature {
* @type {Function}
*/
this.onBeforeOperation = isFn(opts.on_before_operation) ?
opts.on_before_operation : null;
opts.on_before_operation : EMPTY_FN;
/**
* Callback fired after columns operations are completed
* @type {Function}
*/
this.onAfterOperation = isFn(opts.on_after_operation) ?
opts.on_after_operation : null;
opts.on_after_operation : EMPTY_FN;
/**
* Configuration options
@ -85,9 +85,7 @@ export default class ColOps extends Feature {
return;
}
if (this.onBeforeOperation) {
this.onBeforeOperation.call(null, tf, this);
}
this.onBeforeOperation(tf, this);
this.emitter.emit('before-column-operation', tf, this);
let opts = this.opts,
@ -348,9 +346,7 @@ export default class ColOps extends Feature {
}//for ucol
}//if typeof
if (this.onAfterOperation) {
this.onAfterOperation.call(null, tf, this);
}
this.onAfterOperation(tf, this);
this.emitter.emit('after-column-operation', tf, this);
}

View file

@ -3,7 +3,7 @@ import {
addClass, removeClass, createCheckItem, createElm, elm, removeElm,
getText
} from '../../dom';
import {isFn} from '../../types';
import {isFn, EMPTY_FN} from '../../types';
import {addEvt, targetEvt} from '../../event';
/**
@ -209,59 +209,62 @@ export default class ColsVisibility extends Feature {
* Callback fired when the extension is initialized
* @type {Function}
*/
this.onLoaded = isFn(f.on_loaded) ? f.on_loaded : null;
this.onLoaded = isFn(f.on_loaded) ? f.on_loaded : EMPTY_FN;
/**
* Callback fired before the columns manager is opened
* @type {Function}
*/
this.onBeforeOpen = isFn(f.on_before_open) ? f.on_before_open : null;
this.onBeforeOpen = isFn(f.on_before_open) ?
f.on_before_open : EMPTY_FN;
/**
* Callback fired after the columns manager is opened
* @type {Function}
*/
this.onAfterOpen = isFn(f.on_after_open) ? f.on_after_open : null;
this.onAfterOpen = isFn(f.on_after_open) ? f.on_after_open : EMPTY_FN;
/**
* Callback fired before the columns manager is closed
* @type {Function}
*/
this.onBeforeClose = isFn(f.on_before_close) ? f.on_before_close : null;
this.onBeforeClose = isFn(f.on_before_close) ?
f.on_before_close : EMPTY_FN;
/**
* Callback fired after the columns manager is closed
* @type {Function}
*/
this.onAfterClose = isFn(f.on_after_close) ? f.on_after_close : null;
this.onAfterClose = isFn(f.on_after_close) ?
f.on_after_close : EMPTY_FN;
/**
* Callback fired before a column is hidden
* @type {Function}
*/
this.onBeforeColHidden = isFn(f.on_before_col_hidden) ?
f.on_before_col_hidden : null;
f.on_before_col_hidden : EMPTY_FN;
/**
* Callback fired after a column is hidden
* @type {Function}
*/
this.onAfterColHidden = isFn(f.on_after_col_hidden) ?
f.on_after_col_hidden : null;
f.on_after_col_hidden : EMPTY_FN;
/**
* Callback fired before a column is displayed
* @type {Function}
*/
this.onBeforeColDisplayed = isFn(f.on_before_col_displayed) ?
f.on_before_col_displayed : null;
f.on_before_col_displayed : EMPTY_FN;
/**
* Callback fired after a column is displayed
* @type {Function}
*/
this.onAfterColDisplayed = isFn(f.on_after_col_displayed) ?
f.on_after_col_displayed : null;
f.on_after_col_displayed : EMPTY_FN;
//Grid layout support
if (tf.gridLayout) {
@ -283,26 +286,22 @@ export default class ColsVisibility extends Feature {
*/
toggle() {
let contDisplay = this.contEl.style.display;
let onBeforeOpen = this.onBeforeOpen;
let onBeforeClose = this.onBeforeClose;
let onAfterOpen = this.onAfterOpen;
let onAfterClose = this.onAfterClose;
if (onBeforeOpen && contDisplay !== 'inline') {
onBeforeOpen.call(null, this);
if (contDisplay !== 'inline') {
this.onBeforeOpen(this);
}
if (onBeforeClose && contDisplay === 'inline') {
onBeforeClose.call(null, this);
if (contDisplay === 'inline') {
this.onBeforeClose(this);
}
this.contEl.style.display = contDisplay === 'inline' ?
'none' : 'inline';
if (onAfterOpen && contDisplay !== 'inline') {
onAfterOpen.call(null, this);
if (contDisplay !== 'inline') {
this.onAfterOpen(this);
}
if (onAfterClose && contDisplay === 'inline') {
onAfterClose.call(null, this);
if (contDisplay === 'inline') {
this.onAfterClose(this);
}
}
@ -407,9 +406,7 @@ export default class ColsVisibility extends Feature {
this.spanEl = span;
this.btnEl = this.spanEl.firstChild;
if (this.onLoaded) {
this.onLoaded.call(null, this);
}
this.onLoaded(this);
}
/**
@ -510,11 +507,11 @@ export default class ColsVisibility extends Feature {
let tf = this.tf;
let tbl = tf.tbl;
if (this.onBeforeColHidden && hide) {
this.onBeforeColHidden.call(null, this, colIndex);
if (hide) {
this.onBeforeColHidden(this, colIndex);
}
if (this.onBeforeColDisplayed && !hide) {
this.onBeforeColDisplayed.call(null, this, colIndex);
if (!hide) {
this.onBeforeColDisplayed(this, colIndex);
}
this._hideCells(tbl, colIndex, hide);
@ -553,9 +550,8 @@ export default class ColsVisibility extends Feature {
headTbl.style.width = headTblW - hiddenWidth + 'px';
tbl.style.width = headTbl.style.width;
}
if (this.onAfterColHidden) {
this.onAfterColHidden.call(null, this, colIndex);
}
this.onAfterColHidden(this, colIndex);
this.emitter.emit('column-hidden', tf, this, colIndex,
this.hiddenCols);
}
@ -574,9 +570,8 @@ export default class ColsVisibility extends Feature {
(parseInt(headTbl.style.width, 10) + width) + 'px';
tf.tbl.style.width = headTbl.style.width;
}
if (this.onAfterColDisplayed) {
this.onAfterColDisplayed.call(null, this, colIndex);
}
this.onAfterColDisplayed(this, colIndex);
this.emitter.emit('column-shown', tf, this, colIndex,
this.hiddenCols);
}

View file

@ -1,6 +1,6 @@
import {Feature} from '../../feature';
import {createElm, removeElm, elm} from '../../dom';
import {isFn, isUndef} from '../../types';
import {isFn, isUndef, EMPTY_FN} from '../../types';
import {addEvt} from '../../event';
/**
@ -148,25 +148,27 @@ export default class FiltersVisibility extends Feature {
* Callback fired before filters row is shown
* @type {Function}
*/
this.onBeforeShow = isFn(f.on_before_show) ? f.on_before_show : null;
this.onBeforeShow = isFn(f.on_before_show) ?
f.on_before_show : EMPTY_FN;
/**
* Callback fired after filters row is shown
* @type {Function}
*/
this.onAfterShow = isFn(f.on_after_show) ? f.on_after_show : null;
this.onAfterShow = isFn(f.on_after_show) ? f.on_after_show : EMPTY_FN;
/**
* Callback fired before filters row is hidden
* @type {Function}
*/
this.onBeforeHide = isFn(f.on_before_hide) ? f.on_before_hide : null;
this.onBeforeHide = isFn(f.on_before_hide) ?
f.on_before_hide : EMPTY_FN;
/**
* Callback fired after filters row is hidden
* @type {Function}
*/
this.onAfterHide = isFn(f.on_after_hide) ? f.on_after_hide : null;
this.onAfterHide = isFn(f.on_after_hide) ? f.on_after_hide : EMPTY_FN;
//Import extension's stylesheet
tf.import(f.name + 'Style', tf.stylePath + this.stylesheet, null,
@ -259,11 +261,11 @@ export default class FiltersVisibility extends Feature {
let tbl = tf.gridLayout ? tf.feature('gridLayout').headTbl : tf.tbl;
let fltRow = tbl.rows[this.filtersRowIndex];
if (this.onBeforeShow && visible) {
this.onBeforeShow.call(this, this);
if (visible) {
this.onBeforeShow(this);
}
if (this.onBeforeHide && !visible) {
this.onBeforeHide.call(null, this);
if (!visible) {
this.onBeforeHide(this);
}
fltRow.style.display = visible ? '' : 'none';
@ -272,11 +274,11 @@ export default class FiltersVisibility extends Feature {
this.collapseBtnHtml : this.expandBtnHtml;
}
if (this.onAfterShow && visible) {
this.onAfterShow.call(null, this);
if (visible) {
this.onAfterShow(this);
}
if (this.onAfterHide && !visible) {
this.onAfterHide.call(null, this);
if (!visible) {
this.onAfterHide(this);
}
this.emitter.emit('filters-toggled', tf, this, visible);

View file

@ -1,5 +1,5 @@
import {Feature} from '../../feature';
import {isArray, isFn, isUndef, isObj} from '../../types';
import {isArray, isFn, isUndef, isObj, EMPTY_FN} from '../../types';
import {createElm, elm, getText, tag} from '../../dom';
import {addEvt} from '../../event';
import {parse as parseNb} from '../../number';
@ -109,20 +109,21 @@ export default class AdapterSortableTable extends Feature {
* @type {Function}
*/
this.onSortLoaded = isFn(opts.on_sort_loaded) ?
opts.on_sort_loaded : null;
opts.on_sort_loaded : EMPTY_FN;
/**
* Callback fired before a table column is sorted
* @type {Function}
*/
this.onBeforeSort = isFn(opts.on_before_sort) ?
opts.on_before_sort : null;
opts.on_before_sort : EMPTY_FN;
/**
* Callback fired after a table column is sorted
* @type {Function}
*/
this.onAfterSort = isFn(opts.on_after_sort) ? opts.on_after_sort : null;
this.onAfterSort = isFn(opts.on_after_sort) ?
opts.on_after_sort : EMPTY_FN;
/**
* SortableTable instance
@ -154,21 +155,11 @@ export default class AdapterSortableTable extends Feature {
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);
}
adpt.onBeforeSort(tf, adpt.stt.sortColumn);
/*** sort behaviour for paging ***/
if (tf.paging) {
@ -188,15 +179,17 @@ export default class AdapterSortableTable extends Feature {
paginator.setPage(paginator.getPage());
}
if (adpt.onAfterSort) {
adpt.onAfterSort.call(null, tf, adpt.stt.sortColumn,
adpt.stt.descending);
}
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'],
(tf, colIdx, desc) => this.sortByColumnIndex(colIdx, desc));

View file

@ -46,6 +46,9 @@ export class Feature {
* @type {Boolean}
*/
this.initialized = false;
/** Subscribe to destroy event */
this.emitter.on(['destroy'], () => this.destroy());
}
/**

View file

@ -43,6 +43,7 @@ export class AlternateRows extends Feature {
(tf, rowIndex, arrIndex, isValid) =>
this.processRow(rowIndex, arrIndex, isValid));
this.emitter.on(['column-sorted'], () => this.processAll());
this.emitter.on(['rows-changed'], () => this.processAll());
/** @inherited */
this.initialized = true;
@ -131,6 +132,7 @@ export class AlternateRows extends Feature {
(tf, rowIndex, arrIndex, isValid) =>
this.processRow(rowIndex, arrIndex, isValid));
this.emitter.off(['column-sorted'], () => this.processAll());
this.emitter.off(['rows-changed'], () => this.processAll());
this.initialized = false;
}

View file

@ -119,6 +119,7 @@ export class CheckList extends Feature {
/**
* Checklist option click event handler
* @param {Event} evt
* @private
*/
optionClick(evt) {
let elm = targetEvt(evt);
@ -132,6 +133,7 @@ export class CheckList extends Feature {
/**
* Checklist container click event handler for load-on-demand feature
* @param {Event} evt
* @private
*/
onCheckListClick(evt) {
let elm = targetEvt(evt);
@ -143,6 +145,19 @@ export class CheckList extends Feature {
}
}
/**
* Refresh all checklist filters
*/
refreshAll() {
let tf = this.tf;
let fltsIdxs = tf.getFiltersByType(CHECKLIST, true);
fltsIdxs.forEach((colIdx) => {
let values = this.getValues(colIdx);
this.build(colIdx, tf.linkedFilters);
this.selectOptions(colIdx, values);
});
}
/**
* Initialize checklist filter
* @param {Number} colIndex Column index
@ -186,9 +201,9 @@ export class CheckList extends Feature {
(tf, colIndex, values) => this.selectOptions(colIndex, values)
);
/**
* @inherited
*/
this.emitter.on(['rows-changed'], () => this.refreshAll());
/** @inherited */
this.initialized = true;
}
@ -502,7 +517,8 @@ export class CheckList extends Feature {
selectOptions(colIndex, values = []) {
let tf = this.tf;
let flt = tf.getFilterElement(colIndex);
if (tf.getFilterType(colIndex) !== CHECKLIST || !flt) {
if (tf.getFilterType(colIndex) !== CHECKLIST || !flt ||
values.length === 0) {
return;
}
@ -567,5 +583,8 @@ export class CheckList extends Feature {
['select-checklist-options'],
(tf, colIndex, values) => this.selectOptions(colIndex, values)
);
this.emitter.off(['rows-changed'], () => this.refreshAll());
this.initialized = false;
}
}

View file

@ -92,6 +92,21 @@ export class Dropdown extends Feature {
}
}
/**
* Refresh all drop-down filters
*/
refreshAll() {
let tf = this.tf;
let selectFlts = tf.getFiltersByType(SELECT, true);
let multipleFlts = tf.getFiltersByType(MULTIPLE, true);
let flts = selectFlts.concat(multipleFlts);
flts.forEach((colIdx) => {
let values = this.getValues(colIdx);
this.build(colIdx, tf.linkedFilters);
this.selectOptions(colIdx, values);
});
}
/**
* Initialize drop-down filter
* @param {Number} colIndex Column index
@ -145,10 +160,9 @@ export class Dropdown extends Feature {
['select-options'],
(tf, colIndex, values) => this.selectOptions(colIndex, values)
);
this.emitter.on(['rows-changed'], () => this.refreshAll());
/**
* @inherited
*/
/** @inherited */
this.initialized = true;
}
@ -367,7 +381,7 @@ export class Dropdown extends Feature {
*/
selectOptions(colIndex, values = []) {
let tf = this.tf;
if (tf.getFilterType(colIndex) !== MULTIPLE || values.length === 0) {
if (values.length === 0) {
return;
}
let slc = tf.getFilterElement(colIndex);
@ -422,5 +436,7 @@ export class Dropdown extends Feature {
['select-options'],
(tf, colIndex, values) => this.selectOptions(colIndex, values)
);
this.emitter.off(['rows-changed'], () => this.refreshAll());
this.initialized = false;
}
}

View file

@ -1,7 +1,8 @@
import {Feature} from '../feature';
import {createElm, createText, elm, removeElm} from '../dom';
import {addEvt} from '../event';
import {addEvt, targetEvt, removeEvt} from '../event';
import {NONE} from '../const';
import {root} from '../root';
const WIKI_URL = 'https://github.com/koalyptus/TableFilter/wiki/' +
'4.-Filter-operators';
@ -80,17 +81,23 @@ export class Help extends Feature {
'helpCont';
/**
* Stores button DOM element
* Button DOM element
* @type {DOMElement}
*/
this.btn = null;
/**
* Stores help container DOM element
* Help container DOM element
* @type {DOMElement}
*/
this.cont = null;
/**
* Bound mouseup wrapper
* @private
*/
this.boundMouseup = null;
/**
* Default HTML appended to instructions text
* @type {String}
@ -105,6 +112,24 @@ export class Help extends Feature {
this.emitter.on(['init-help'], () => this.init());
}
/**
* 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
*/
@ -118,6 +143,8 @@ export class Help extends Feature {
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();
@ -144,7 +171,6 @@ export class Help extends Feature {
if (!this.instrHtml) {
cont.innerHTML = this.instrText;
cont.className = this.contCssClass;
addEvt(cont, 'dblclick', () => this.toggle());
} else {
if (this.contTgtId) {
divContainer.appendChild(cont);
@ -152,7 +178,6 @@ export class Help extends Feature {
cont.innerHTML = this.instrHtml;
if (!this.contTgtId) {
cont.className = this.contCssClass;
addEvt(cont, 'dblclick', () => this.toggle());
}
}
cont.innerHTML += this.defaultHtml;
@ -173,9 +198,14 @@ export class Help extends Feature {
if (this.enabled === false) {
return;
}
// 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';
addEvt(root, 'mouseup', this.boundMouseup);
} else {
this.cont.style.display = NONE;
}
@ -194,6 +224,8 @@ export class Help extends Feature {
removeElm(this.cont);
this.cont = null;
this.boundMouseup = null;
this.initialized = false;
}

View file

@ -1,5 +1,6 @@
import {createText, createElm, getText} from '../dom';
import {isArray} from '../types';
import {rgxEsc} from '../string';
/**
* Highlight matched keywords upon filtering
@ -45,8 +46,7 @@ export class HighlightKeyword {
);
this.emitter.on(
['highlight-keyword'],
(tf, cell, term) =>
this.highlight(cell, term, this.highlightCssClass)
(tf, cell, term) => this._processTerm(cell, term)
);
}
@ -130,9 +130,7 @@ export class HighlightKeyword {
});
}
/**
* Remove feature
*/
/** Remove feature */
destroy() {
this.emitter.off(
['before-filtering', 'destroy'],
@ -140,8 +138,42 @@ export class HighlightKeyword {
);
this.emitter.off(
['highlight-keyword'],
(tf, cell, term) =>
this.highlight(cell, term, this.highlightCssClass)
(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);
}
}

View file

@ -1,6 +1,6 @@
import {Feature} from '../feature';
import {createElm, createText, elm, removeElm} from '../dom';
import {isFn} from '../types';
import {isFn, EMPTY_FN} from '../types';
import {root} from '../root';
import {NONE} from '../const';
@ -75,13 +75,14 @@ export class Loader extends Feature {
* Callback fired when loader is displayed
* @type {Function}
*/
this.onShow = isFn(f.on_show_loader) ? f.on_show_loader : null;
this.onShow = isFn(f.on_show_loader) ?
f.on_show_loader : EMPTY_FN;
/**
* Callback fired when loader is closed
* @type {Function}
*/
this.onHide = isFn(f.on_hide_loader) ? f.on_hide_loader : null;
this.onHide = isFn(f.on_hide_loader) ? f.on_hide_loader : EMPTY_FN;
}
/**
@ -137,12 +138,12 @@ export class Loader extends Feature {
if (!this.cont) {
return;
}
if (this.onShow && p !== NONE) {
this.onShow.call(null, this);
if (p !== NONE) {
this.onShow(this);
}
this.cont.style.display = p;
if (this.onHide && p === NONE) {
this.onHide.call(null, this);
if (p === NONE) {
this.onHide(this);
}
};

View file

@ -1,6 +1,6 @@
import {Feature} from '../feature';
import {createElm, elm, removeElm} from '../dom';
import {isEmpty, isFn} from '../types';
import {isEmpty, isFn, EMPTY_FN} from '../types';
import {NONE} from '../const';
/**
@ -64,28 +64,28 @@ export class NoResults extends Feature {
* @type {Function}
*/
this.onBeforeShow = isFn(f.on_before_show_msg) ?
f.on_before_show_msg : null;
f.on_before_show_msg : EMPTY_FN;
/**
* Callback fired after the message is displayed
* @type {Function}
*/
this.onAfterShow = isFn(f.on_after_show_msg) ?
f.on_after_show_msg : null;
f.on_after_show_msg : EMPTY_FN;
/**
* Callback fired before the message is hidden
* @type {Function}
*/
this.onBeforeHide = isFn(f.on_before_hide_msg) ?
f.on_before_hide_msg : null;
f.on_before_hide_msg : EMPTY_FN;
/**
* Callback fired after the message is hidden
* @type {Function}
*/
this.onAfterHide = isFn(f.on_after_hide_msg) ?
f.on_after_hide_msg : null;
f.on_after_hide_msg : EMPTY_FN;
}
/**
@ -141,17 +141,12 @@ export class NoResults extends Feature {
if (!this.initialized || !this.isEnabled()) {
return;
}
if (this.onBeforeShow) {
this.onBeforeShow.call(null, this.tf, this);
}
this.onBeforeShow(this.tf, this);
this.setWidth();
this.cont.style.display = 'block';
if (this.onAfterShow) {
this.onAfterShow.call(null, this.tf, this);
}
this.onAfterShow(this.tf, this);
}
/**
@ -161,16 +156,11 @@ export class NoResults extends Feature {
if (!this.initialized || !this.isEnabled()) {
return;
}
if (this.onBeforeHide) {
this.onBeforeHide.call(null, this.tf, this);
}
this.onBeforeHide(this.tf, this);
this.cont.style.display = NONE;
if (this.onAfterHide) {
this.onAfterHide.call(null, this.tf, this);
}
this.onAfterHide(this.tf, this);
}
/**

View file

@ -1,6 +1,6 @@
import {Feature} from '../feature';
import {createElm, createOpt, createText, elm, removeElm} from '../dom';
import {isArray, isFn, isNull} from '../types';
import {isArray, isFn, isNull, EMPTY_FN} from '../types';
import {addEvt, keyCode, removeEvt} from '../event';
import {INPUT, SELECT, NONE, ENTER_KEY} from '../const';
@ -211,14 +211,14 @@ export class Paging extends Feature {
* @type {Function}
*/
this.onBeforeChangePage = isFn(f.on_before_change_page) ?
f.on_before_change_page : null;
f.on_before_change_page : EMPTY_FN;
/**
* Callback fired after the page is changed
* @type {Function}
*/
this.onAfterChangePage = isFn(f.on_after_change_page) ?
f.on_after_change_page : null;
f.on_after_change_page : EMPTY_FN;
/**
* Label preciding results per page select
@ -717,9 +717,8 @@ export class Paging extends Feature {
this.pagingSlc.options.selectedIndex : this.pagingSlc.value - 1;
}
if (index >= 0 && index <= (this.nbPages - 1)) {
if (this.onBeforeChangePage) {
this.onBeforeChangePage.call(null, this, (index + 1));
}
this.onBeforeChangePage(this, (index + 1));
this.currentPageNb = parseInt(index, 10) + 1;
if (this.pageSelectorType === SELECT) {
this.pagingSlc.options[index].selected = true;
@ -732,9 +731,7 @@ export class Paging extends Feature {
this.groupByPage();
if (this.onAfterChangePage) {
this.onAfterChangePage.call(null, this, (index + 1));
}
this.onAfterChangePage(this, (index + 1));
}
this.emitter.emit('after-page-change', tf, (index + 1));

View file

@ -1,5 +1,5 @@
import {Feature} from '../feature';
import {isFn, isUndef} from '../types';
import {isFn, 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';
@ -74,28 +74,28 @@ export class PopupFilter extends Feature {
* @type {Function}
*/
this.onBeforeOpen = isFn(f.on_before_popup_filter_open) ?
f.on_before_popup_filter_open : null;
f.on_before_popup_filter_open : EMPTY_FN;
/**
* Callback fired after a popup filter is opened
* @type {Function}
*/
this.onAfterOpen = isFn(f.on_after_popup_filter_open) ?
f.on_after_popup_filter_open : null;
f.on_after_popup_filter_open : EMPTY_FN;
/**
* Callback fired before a popup filter is closed
* @type {Function}
*/
this.onBeforeClose = isFn(f.on_before_popup_filter_close) ?
f.on_before_popup_filter_close : null;
f.on_before_popup_filter_close : EMPTY_FN;
/**
* Callback fired after a popup filter is closed
* @type {Function}
*/
this.onAfterClose = isFn(f.on_after_popup_filter_close) ?
f.on_after_popup_filter_close : null;
f.on_after_popup_filter_close : EMPTY_FN;
/**
* Collection of filters spans
@ -307,9 +307,8 @@ export class PopupFilter extends Feature {
let tf = this.tf,
container = this.fltElms[colIndex];
if (this.onBeforeOpen) {
this.onBeforeOpen.call(null, this, container, colIndex);
}
this.onBeforeOpen(this, container, colIndex);
container.style.display = 'block';
this.activeFilterIdx = colIndex;
addEvt(root, 'mouseup', (evt) => this.onMouseup(evt));
@ -320,9 +319,8 @@ export class PopupFilter extends Feature {
flt.focus();
}
}
if (this.onAfterOpen) {
this.onAfterOpen.call(null, this, container, colIndex);
}
this.onAfterOpen(this, container, colIndex);
}
/**
@ -331,17 +329,16 @@ export class PopupFilter extends Feature {
*/
close(colIndex) {
let container = this.fltElms[colIndex];
if (this.onBeforeClose) {
this.onBeforeClose.call(null, this, container, colIndex);
}
this.onBeforeClose(this, container, colIndex);
container.style.display = NONE;
if (this.activeFilterIdx === colIndex) {
this.activeFilterIdx = -1;
}
removeEvt(root, 'mouseup', (evt) => this.onMouseup(evt));
if (this.onAfterClose) {
this.onAfterClose.call(null, this, container, colIndex);
}
this.onAfterClose(this, container, colIndex);
}
/**

View file

@ -1,6 +1,6 @@
import {Feature} from '../feature';
import {createElm, createText, elm, removeElm} from '../dom';
import {isFn} from '../types';
import {isFn, EMPTY_FN} from '../types';
/**
* Rows counter UI component
@ -72,14 +72,14 @@ export class RowsCounter extends Feature {
* @type {Function}
*/
this.onBeforeRefreshCounter = isFn(f.on_before_refresh_counter) ?
f.on_before_refresh_counter : null;
f.on_before_refresh_counter : EMPTY_FN;
/**
* Callback fired after the counter is refreshed
* @type {Function}
*/
this.onAfterRefreshCounter = isFn(f.on_after_refresh_counter) ?
f.on_after_refresh_counter : null;
f.on_after_refresh_counter : EMPTY_FN;
}
/**
@ -142,9 +142,7 @@ export class RowsCounter extends Feature {
let tf = this.tf;
if (this.onBeforeRefreshCounter) {
this.onBeforeRefreshCounter.call(null, tf, this.label);
}
this.onBeforeRefreshCounter(tf, this.label);
let totTxt;
if (!tf.paging) {
@ -170,9 +168,7 @@ export class RowsCounter extends Feature {
}
this.label.innerHTML = totTxt;
if (this.onAfterRefreshCounter) {
this.onAfterRefreshCounter.call(null, tf, this.label, totTxt);
}
this.onAfterRefreshCounter(tf, this.label, totTxt);
}
/**

View file

@ -1,7 +1,7 @@
import {Feature} from '../feature';
import {root} from '../root';
import {createElm, createText, elm, removeElm} from '../dom';
import {isFn} from '../types';
import {isFn, EMPTY_FN} from '../types';
const EVENTS = [
'after-filtering',
@ -84,14 +84,14 @@ export class StatusBar extends Feature {
* @type {Function}
*/
this.onBeforeShowMsg = isFn(f.on_before_show_msg) ?
f.on_before_show_msg : null;
f.on_before_show_msg : EMPTY_FN;
/**
* Callback fired after the message is displayed
* @type {Function}
*/
this.onAfterShowMsg = isFn(f.on_after_show_msg) ?
f.on_after_show_msg : null;
f.on_after_show_msg : EMPTY_FN;
/**
* Message appearing upon filtering
@ -242,9 +242,7 @@ export class StatusBar extends Feature {
return;
}
if (this.onBeforeShowMsg) {
this.onBeforeShowMsg.call(null, this.tf, t);
}
this.onBeforeShowMsg(this.tf, t);
let d = t === '' ? this.delay : 1;
root.setTimeout(() => {
@ -252,9 +250,8 @@ export class StatusBar extends Feature {
return;
}
this.msgContainer.innerHTML = t;
if (this.onAfterShowMsg) {
this.onAfterShowMsg.call(null, this.tf, t);
}
this.onAfterShowMsg(this.tf, t);
}, d);
}

View file

@ -6,7 +6,7 @@ import {
import {contains, matchCase, rgxEsc, trim} from './string';
import {isEmpty as isEmptyString} from './string';
import {
isArray, isEmpty, isFn, isNumber, isObj, isString, isUndef
isArray, isEmpty, isFn, isNumber, isObj, isString, isUndef, EMPTY_FN
} from './types';
import {parse as parseNb} from './number'
@ -346,13 +346,14 @@ export class TableFilter {
* @type {Function}
*/
this.onBeforeFilter = isFn(f.on_before_filter) ?
f.on_before_filter : null;
f.on_before_filter : EMPTY_FN;
/**
* Callback fired after filtering process is completed
* @type {Function}
*/
this.onAfterFilter = isFn(f.on_after_filter) ? f.on_after_filter : null;
this.onAfterFilter = isFn(f.on_after_filter) ?
f.on_after_filter : EMPTY_FN;
/**
* Enable/disable case sensitivity filtering
@ -436,7 +437,7 @@ export class TableFilter {
* @type {Function}
*/
this.onFiltersLoaded = isFn(f.on_filters_loaded) ?
f.on_filters_loaded : null;
f.on_filters_loaded : EMPTY_FN;
/**
* Enable/disable single filter filtering all columns
@ -449,7 +450,7 @@ export class TableFilter {
* @type {Function}
*/
this.onRowValidated = isFn(f.on_row_validated) ?
f.on_row_validated : null;
f.on_row_validated : EMPTY_FN;
/**
* List of columns implementing custom filtering
@ -463,7 +464,7 @@ export class TableFilter {
* @type {Function}
*/
this.customCellData = isFn(f.custom_cell_data) ?
f.custom_cell_data : null;
f.custom_cell_data : EMPTY_FN;
/**
* Global watermark text for input filter type or watermark for each
@ -516,14 +517,14 @@ export class TableFilter {
* @type {Function}
*/
this.onBeforeActiveColumn = isFn(f.on_before_active_column) ?
f.on_before_active_column : null;
f.on_before_active_column : EMPTY_FN;
/**
* Callback fired after a column is marked as filtered
* @type {Function}
*/
this.onAfterActiveColumn = isFn(f.on_after_active_column) ?
f.on_after_active_column : null;
f.on_after_active_column : EMPTY_FN;
/*** select filter's customisation and behaviours ***/
/**
@ -775,13 +776,14 @@ export class TableFilter {
* @type {Function}
*/
this.onBeforeReset = isFn(f.on_before_reset) ?
f.on_before_reset : null;
f.on_before_reset : EMPTY_FN;
/**
* Callback fired after filters are cleared
* @type {Function}
*/
this.onAfterReset = isFn(f.on_after_reset) ? f.on_after_reset : null;
this.onAfterReset = isFn(f.on_after_reset) ?
f.on_after_reset : EMPTY_FN;
/**
* Enable paging component
@ -1177,14 +1179,11 @@ export class TableFilter {
this.emitter.on(['after-filtering'], () => this.linkFilters());
}
/**
* @inherited
*/
/** @inherited */
this.initialized = true;
if (this.onFiltersLoaded) {
this.onFiltersLoaded.call(null, this);
}
this.onFiltersLoaded(this);
this.emitter.emit('initialized', this);
}
@ -1519,7 +1518,6 @@ export class TableFilter {
return;
}
let Mod = this.Mod;
let emitter = this.emitter;
if (this.isExternalFlt && !this.popupFilters) {
@ -1547,15 +1545,6 @@ export class TableFilter {
// broadcast destroy event
emitter.emit('destroy', this);
// Destroy modules
// TODO: subcribe modules to destroy event instead
Object.keys(Mod).forEach(function (key) {
let feature = Mod[key];
if (feature && isFn(feature.destroy)) {
feature.destroy();
}
});
// unsubscribe to events
if (this.hasVisibleRows) {
emitter.off(['after-filtering'], () => this.enforceVisibility());
@ -1721,10 +1710,8 @@ export class TableFilter {
if (!this.fltGrid || !this.initialized) {
return;
}
//invoke onbefore callback
if (this.onBeforeFilter) {
this.onBeforeFilter.call(null, this);
}
//fire onbefore callback
this.onBeforeFilter(this);
this.emitter.emit('before-filtering', this);
let row = this.tbl.rows,
@ -1735,258 +1722,6 @@ export class TableFilter {
// search args re-init
let searchArgs = this.getFiltersValue();
let numData;
let decimal = this.decimalSeparator;
let re_le = new RegExp(this.leOperator),
re_ge = new RegExp(this.geOperator),
re_l = new RegExp(this.lwOperator),
re_g = new RegExp(this.grOperator),
re_d = new RegExp(this.dfOperator),
re_lk = new RegExp(rgxEsc(this.lkOperator)),
re_eq = new RegExp(this.eqOperator),
re_st = new RegExp(this.stOperator),
re_en = new RegExp(this.enOperator),
// re_an = new RegExp(this.anOperator),
// re_cr = new RegExp(this.curExp),
re_em = this.emOperator,
re_nm = this.nmOperator,
re_re = new RegExp(rgxEsc(this.rgxOperator));
//keyword highlighting
function highlight(str, ok, cell) {
/*jshint validthis:true */
if (this.highlightKeywords && ok) {
str = str.replace(re_lk, '');
str = str.replace(re_eq, '');
str = str.replace(re_st, '');
str = str.replace(re_en, '');
let w = str;
if (re_le.test(str) || re_ge.test(str) || re_l.test(str) ||
re_g.test(str) || re_d.test(str)) {
w = getText(cell);
}
if (w !== '') {
this.emitter.emit('highlight-keyword', this, cell, w);
}
}
}
//looks for search argument in current row
function hasArg(sA, cellData, colIdx) {
sA = matchCase(sA, this.caseSensitive);
let occurence = false;
//Search arg operator tests
let hasLO = re_l.test(sA),
hasLE = re_le.test(sA),
hasGR = re_g.test(sA),
hasGE = re_ge.test(sA),
hasDF = re_d.test(sA),
hasEQ = re_eq.test(sA),
hasLK = re_lk.test(sA),
// hasAN = re_an.test(sA),
hasST = re_st.test(sA),
hasEN = re_en.test(sA),
hasEM = (re_em === sA),
hasNM = (re_nm === sA),
hasRE = re_re.test(sA);
// Check for dates or resolve date type
if (this.hasType(colIdx, [DATE])) {
let dte1, dte2;
let dateType = this.Mod.dateType;
let isValidDate = dateType.isValid.bind(dateType);
let parseDate = dateType.parse.bind(dateType);
let locale = dateType.getOptions(colIdx).locale || this.locale;
// Search arg dates tests
let isLDate = hasLO &&
isValidDate(sA.replace(re_l, ''), locale);
let isLEDate = hasLE &&
isValidDate(sA.replace(re_le, ''), locale);
let isGDate = hasGR &&
isValidDate(sA.replace(re_g, ''), locale);
let isGEDate = hasGE &&
isValidDate(sA.replace(re_ge, ''), locale);
let isDFDate = hasDF &&
isValidDate(sA.replace(re_d, ''), locale);
let isEQDate = hasEQ &&
isValidDate(sA.replace(re_eq, ''), locale);
dte1 = parseDate(cellData, locale);
// lower date
if (isLDate) {
dte2 = parseDate(sA.replace(re_l, ''), locale);
occurence = dte1 < dte2;
}
// lower equal date
else if (isLEDate) {
dte2 = parseDate(sA.replace(re_le, ''), locale);
occurence = dte1 <= dte2;
}
// greater equal date
else if (isGEDate) {
dte2 = parseDate(sA.replace(re_ge, ''), locale);
occurence = dte1 >= dte2;
}
// greater date
else if (isGDate) {
dte2 = parseDate(sA.replace(re_g, ''), locale);
occurence = dte1 > dte2;
}
// different date
else if (isDFDate) {
dte2 = parseDate(sA.replace(re_d, ''), locale);
occurence = dte1.toString() !== dte2.toString();
}
// equal date
else if (isEQDate) {
dte2 = parseDate(sA.replace(re_eq, ''), locale);
occurence = dte1.toString() === dte2.toString();
}
// searched keyword with * operator doesn't have to be a date
else if (re_lk.test(sA)) {// like date
occurence = contains(sA.replace(re_lk, ''), cellData,
false, this.caseSensitive);
}
else if (isValidDate(sA)) {
dte2 = parseDate(sA, locale);
occurence = dte1.toString() === dte2.toString();
}
//empty
else if (hasEM) {
occurence = isEmptyString(cellData);
}
//non-empty
else if (hasNM) {
occurence = !isEmptyString(cellData);
} else {
occurence = contains(sA, cellData,
this.isExactMatch(colIdx), this.caseSensitive);
}
}
else {
if (this.hasType(colIdx, [FORMATTED_NUMBER])) {
let colType = this.colTypes[colIdx];
if (colType.hasOwnProperty('decimal')) {
decimal = colType.decimal;
}
}
// Convert to number anyways to auto-resolve type in case not
// defined by configuration
numData = Number(cellData) || parseNb(cellData, decimal);
// first checks if there is any operator (<,>,<=,>=,!,*,=,{,},
// rgx:)
// lower equal
if (hasLE) {
occurence = numData <= parseNb(
sA.replace(re_le, ''),
decimal
);
}
//greater equal
else if (hasGE) {
occurence = numData >= parseNb(
sA.replace(re_ge, ''),
decimal
);
}
//lower
else if (hasLO) {
occurence = numData < parseNb(
sA.replace(re_l, ''),
decimal
);
}
//greater
else if (hasGR) {
occurence = numData > parseNb(
sA.replace(re_g, ''),
decimal
);
}
//different
else if (hasDF) {
occurence = contains(sA.replace(re_d, ''), cellData,
false, this.caseSensitive) ? false : true;
}
//like
else if (hasLK) {
occurence = contains(sA.replace(re_lk, ''), cellData,
false, this.caseSensitive);
}
//equal
else if (hasEQ) {
occurence = contains(sA.replace(re_eq, ''), cellData,
true, this.caseSensitive);
}
//starts with
else if (hasST) {
occurence = cellData.indexOf(sA.replace(re_st, '')) === 0 ?
true : false;
}
//ends with
else if (hasEN) {
let searchArg = sA.replace(re_en, '');
occurence =
cellData.lastIndexOf(searchArg, cellData.length - 1) ===
(cellData.length - 1) - (searchArg.length - 1) &&
cellData.lastIndexOf(searchArg, cellData.length - 1)
> -1 ? true : false;
}
//empty
else if (hasEM) {
occurence = isEmptyString(cellData);
}
//non-empty
else if (hasNM) {
occurence = !isEmptyString(cellData);
}
//regexp
else if (hasRE) {
//in case regexp throws
try {
//operator is removed
let srchArg = sA.replace(re_re, '');
let rgx = new RegExp(srchArg);
occurence = rgx.test(cellData);
} catch (ex) {
occurence = false;
}
} else {
// If numeric type data, perform a strict equality test and
// fallback to unformatted number string comparison
if (numData &&
this.hasType(colIdx, [NUMBER, FORMATTED_NUMBER]) &&
!this.singleSearchFlt) {
// parseNb can return 0 for strings which are not
// formatted numbers, in that case return the original
// string. TODO: handle this in parseNb
sA = parseNb(sA, decimal) || sA;
occurence = numData === sA ||
contains(sA.toString(), numData.toString(),
this.isExactMatch(colIdx), this.caseSensitive);
} else {
// Finally test search term is contained in cell data
occurence = contains(
sA,
cellData,
this.isExactMatch(colIdx),
this.caseSensitive,
this.ignoresDiacritics(colIdx)
);
}
}
}//else
return occurence;
}//fn
for (let k = this.refRow; k < nbRows; k++) {
// already filtered rows display re-init
row[k].style.display = '';
@ -2035,11 +1770,15 @@ export class TableFilter {
} else {
s = hasMultiOrSA ? sAOrSplit : sAAndSplit;
}
// TODO: improve clarity/readability of this block
// isolate search term and check occurence in cell data
for (let w = 0, len = s.length; w < len; w++) {
cS = trim(s[w]);
occur = hasArg.call(this, cS, cellData, j);
highlight.call(this, cS, occur, cells[j]);
occur = this._testTerm(cS, cellData, j);
if (occur) {
this.emitter.emit('highlight-keyword', this,
cells[j], cS);
}
if ((hasMultiOrSA && occur) ||
(hasMultiAndSA && !occur)) {
break;
@ -2053,8 +1792,11 @@ export class TableFilter {
}
//single search parameter
else {
occurence[j] = hasArg.call(this, trim(sA), cellData, j);
highlight.call(this, sA, occurence[j], cells[j]);
occurence[j] = this._testTerm(trim(sA), cellData, j);
if (occurence[j]) {
this.emitter.emit('highlight-keyword', this, cells[j],
sA);
}
}//else single param
if (!occurence[j]) {
@ -2071,11 +1813,9 @@ export class TableFilter {
isRowValid = true;
}
this.validateRow(k, isRowValid);
if (!isRowValid) {
this.validateRow(k, false);
hiddenRows++;
} else {
this.validateRow(k, true);
}
this.emitter.emit('row-processed', this, k,
@ -2084,14 +1824,252 @@ export class TableFilter {
this.nbHiddenRows = hiddenRows;
//invokes onafterfilter callback
if (this.onAfterFilter) {
this.onAfterFilter.call(null, this);
}
//fire onafterfilter callback
this.onAfterFilter(this);
this.emitter.emit('after-filtering', this, searchArgs);
}
/**
* Test for a match of search term in cell data
* @param {String} term Search term
* @param {String} cellData Cell data
* @param {Number} colIdx Column index
* @returns {Boolean}
*/
_testTerm(term, cellData, colIdx) {
let numData;
let decimal = this.decimalSeparator;
let reLe = new RegExp(this.leOperator),
reGe = new RegExp(this.geOperator),
reL = new RegExp(this.lwOperator),
reG = new RegExp(this.grOperator),
reD = new RegExp(this.dfOperator),
reLk = new RegExp(rgxEsc(this.lkOperator)),
reEq = new RegExp(this.eqOperator),
reSt = new RegExp(this.stOperator),
reEn = new RegExp(this.enOperator),
// re_an = new RegExp(this.anOperator),
// re_cr = new RegExp(this.curExp),
reEm = this.emOperator,
reNm = this.nmOperator,
reRe = new RegExp(rgxEsc(this.rgxOperator));
term = matchCase(term, this.caseSensitive);
let occurence = false;
//Search arg operator tests
let hasLO = reL.test(term),
hasLE = reLe.test(term),
hasGR = reG.test(term),
hasGE = reGe.test(term),
hasDF = reD.test(term),
hasEQ = reEq.test(term),
hasLK = reLk.test(term),
// hatermN = re_an.test(term),
hasST = reSt.test(term),
hasEN = reEn.test(term),
hasEM = (reEm === term),
hasNM = (reNm === term),
hasRE = reRe.test(term);
// Check for dates or resolve date type
if (this.hasType(colIdx, [DATE])) {
let dte1, dte2;
let dateType = this.Mod.dateType;
let isValidDate = dateType.isValid.bind(dateType);
let parseDate = dateType.parse.bind(dateType);
let locale = dateType.getOptions(colIdx).locale || this.locale;
// Search arg dates tests
let isLDate = hasLO &&
isValidDate(term.replace(reL, ''), locale);
let isLEDate = hasLE &&
isValidDate(term.replace(reLe, ''), locale);
let isGDate = hasGR &&
isValidDate(term.replace(reG, ''), locale);
let isGEDate = hasGE &&
isValidDate(term.replace(reGe, ''), locale);
let isDFDate = hasDF &&
isValidDate(term.replace(reD, ''), locale);
let isEQDate = hasEQ &&
isValidDate(term.replace(reEq, ''), locale);
dte1 = parseDate(cellData, locale);
// lower date
if (isLDate) {
dte2 = parseDate(term.replace(reL, ''), locale);
occurence = dte1 < dte2;
}
// lower equal date
else if (isLEDate) {
dte2 = parseDate(term.replace(reLe, ''), locale);
occurence = dte1 <= dte2;
}
// greater equal date
else if (isGEDate) {
dte2 = parseDate(term.replace(reGe, ''), locale);
occurence = dte1 >= dte2;
}
// greater date
else if (isGDate) {
dte2 = parseDate(term.replace(reG, ''), locale);
occurence = dte1 > dte2;
}
// different date
else if (isDFDate) {
dte2 = parseDate(term.replace(reD, ''), locale);
occurence = dte1.toString() !== dte2.toString();
}
// equal date
else if (isEQDate) {
dte2 = parseDate(term.replace(reEq, ''), locale);
occurence = dte1.toString() === dte2.toString();
}
// searched keyword with * operator doesn't have to be a date
else if (reLk.test(term)) {// like date
occurence = contains(term.replace(reLk, ''), cellData,
false, this.caseSensitive);
}
else if (isValidDate(term)) {
dte2 = parseDate(term, locale);
occurence = dte1.toString() === dte2.toString();
}
//empty
else if (hasEM) {
occurence = isEmptyString(cellData);
}
//non-empty
else if (hasNM) {
occurence = !isEmptyString(cellData);
} else {
occurence = contains(term, cellData,
this.isExactMatch(colIdx), this.caseSensitive);
}
}
else {
if (this.hasType(colIdx, [FORMATTED_NUMBER])) {
let colType = this.colTypes[colIdx];
if (colType.hasOwnProperty('decimal')) {
decimal = colType.decimal;
}
}
// Convert to number anyways to auto-resolve type in case not
// defined by configuration
numData = Number(cellData) || parseNb(cellData, decimal);
// first checks if there is any operator (<,>,<=,>=,!,*,=,{,},
// rgx:)
// lower equal
if (hasLE) {
occurence = numData <= parseNb(
term.replace(reLe, ''),
decimal
);
}
//greater equal
else if (hasGE) {
occurence = numData >= parseNb(
term.replace(reGe, ''),
decimal
);
}
//lower
else if (hasLO) {
occurence = numData < parseNb(
term.replace(reL, ''),
decimal
);
}
//greater
else if (hasGR) {
occurence = numData > parseNb(
term.replace(reG, ''),
decimal
);
}
//different
else if (hasDF) {
occurence = contains(term.replace(reD, ''), cellData,
false, this.caseSensitive) ? false : true;
}
//like
else if (hasLK) {
occurence = contains(term.replace(reLk, ''), cellData,
false, this.caseSensitive);
}
//equal
else if (hasEQ) {
occurence = contains(term.replace(reEq, ''), cellData,
true, this.caseSensitive);
}
//starts with
else if (hasST) {
occurence = cellData.indexOf(term.replace(reSt, '')) === 0 ?
true : false;
}
//ends with
else if (hasEN) {
let searchArg = term.replace(reEn, '');
occurence =
cellData.lastIndexOf(searchArg, cellData.length - 1) ===
(cellData.length - 1) - (searchArg.length - 1) &&
cellData.lastIndexOf(searchArg, cellData.length - 1)
> -1 ? true : false;
}
//empty
else if (hasEM) {
occurence = isEmptyString(cellData);
}
//non-empty
else if (hasNM) {
occurence = !isEmptyString(cellData);
}
//regexp
else if (hasRE) {
//in case regexp throws
try {
//operator is removed
let srchArg = term.replace(reRe, '');
let rgx = new RegExp(srchArg);
occurence = rgx.test(cellData);
} catch (ex) {
occurence = false;
}
} else {
// If numeric type data, perform a strict equality test and
// fallback to unformatted number string comparison
if (numData &&
this.hasType(colIdx, [NUMBER, FORMATTED_NUMBER]) &&
!this.singleSearchFlt) {
// parseNb can return 0 for strings which are not
// formatted numbers, in that case return the original
// string. TODO: handle this in parseNb
term = parseNb(term, decimal) || term;
occurence = numData === term ||
contains(term.toString(), numData.toString(),
this.isExactMatch(colIdx), this.caseSensitive);
} else {
// Finally test search term is contained in cell data
occurence = contains(
term,
cellData,
this.isExactMatch(colIdx),
this.caseSensitive,
this.ignoresDiacritics(colIdx)
);
}
}
}//else
return occurence;
}
/**
* Return the data of a specified column
* @param {Number} colIndex Column index
@ -2281,10 +2259,9 @@ export class TableFilter {
*/
getCellData(cell) {
let idx = cell.cellIndex;
//Check for customCellData callback
if (this.customCellData &&
this.customCellDataCols.indexOf(idx) !== -1) {
return this.customCellData.call(null, this, cell, idx);
//Fire customCellData callback
if (this.customCellDataCols.indexOf(idx) !== -1) {
return this.customCellData(this, cell, idx);
} else {
return getText(cell);
}
@ -2434,9 +2411,7 @@ export class TableFilter {
this.validRowsIndex.push(rowIndex);
}
if (this.onRowValidated) {
this.onRowValidated.call(null, this, rowIndex);
}
this.onRowValidated(this, rowIndex);
this.emitter.emit('row-validated', this, rowIndex);
}
@ -2560,19 +2535,15 @@ export class TableFilter {
}
this.emitter.emit('before-clearing-filters', this);
this.onBeforeReset(this, this.getFiltersValue());
if (this.onBeforeReset) {
this.onBeforeReset.call(null, this, this.getFiltersValue());
}
for (let i = 0, len = this.fltIds.length; i < len; i++) {
this.setFilterValue(i, '');
}
this.filter();
if (this.onAfterReset) {
this.onAfterReset.call(null, this);
}
this.onAfterReset(this);
this.emitter.emit('after-clearing-filters', this);
}
@ -2594,13 +2565,11 @@ export class TableFilter {
if (hasClass(header, this.activeColumnsCssClass)) {
return;
}
if (this.onBeforeActiveColumn) {
this.onBeforeActiveColumn.call(null, this, colIndex);
}
this.onBeforeActiveColumn(this, colIndex);
addClass(header, this.activeColumnsCssClass);
if (this.onAfterActiveColumn) {
this.onAfterActiveColumn.call(null, this, colIndex);
}
this.onAfterActiveColumn(this, colIndex);
}
/**
@ -2692,7 +2661,7 @@ export class TableFilter {
this.emitter.emit('build-checklist-filter', this, colIdx,
true);
} else {
this.emitter.emit('build-select-filter', this,colIdx,
this.emitter.emit('build-select-filter', this, colIdx,
true);
}

View file

@ -5,13 +5,19 @@
const UNDEFINED = void 0;
/**
* Return an empty function
* @return {Function}
*/
export const EMPTY_FN = function() {};
/**
* Check passed argument is an object
* @param {Object} obj
* @return {Boolean}
*/
export const isObj =
obj => Object.prototype.toString.call(obj) === '[object Object]';
(obj) => Object.prototype.toString.call(obj) === '[object Object]';
/**
* Check passed argument is a function
@ -19,7 +25,7 @@ export const isObj =
* @return {Boolean}
*/
export const isFn =
obj => Object.prototype.toString.call(obj) === '[object Function]';
(obj) => Object.prototype.toString.call(obj) === '[object Function]';
/**
* Check passed argument is an array
@ -27,7 +33,7 @@ export const isFn =
* @return {Boolean}
*/
export const isArray =
obj => Object.prototype.toString.call(obj) === '[object Array]';
(obj) => Object.prototype.toString.call(obj) === '[object Array]';
/**
* Check passed argument is a string
@ -35,7 +41,7 @@ export const isArray =
* @returns {Boolean}
*/
export const isString =
obj => Object.prototype.toString.call(obj) === '[object String]';
(obj) => Object.prototype.toString.call(obj) === '[object String]';
/**
* Check passed argument is a number
@ -43,14 +49,14 @@ export const isString =
* @returns {Boolean}
*/
export const isNumber =
obj => Object.prototype.toString.call(obj) === '[object Number]';
(obj) => Object.prototype.toString.call(obj) === '[object Number]';
/**
* Check passed argument is undefined
* @param {Any} obj
* @return {Boolean}
*/
export const isUndef = obj => obj === UNDEFINED;
export const isUndef = (obj) => obj === UNDEFINED;
/**
* Check passed argument is null
@ -64,4 +70,4 @@ export const isNull = obj => obj === null;
* @param {Any} obj
* @return {Boolean}
*/
export const isEmpty = obj => isUndef(obj) || isNull(obj) || obj.length === 0;
export const isEmpty = (obj) => isUndef(obj) || isNull(obj) || obj.length === 0;

View file

@ -9,7 +9,7 @@
</head>
<body>
<table id="demo" cellpadding="0" cellspacing="0">
<tbody>
<thead>
<tr>
<th>From</th>
<th>Destination</th>
@ -17,6 +17,8 @@
<th>By Air (hrs)</th>
<th>By Rail (hrs)</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Sydney</strong></td>
<td>Adelaide</td>
@ -75,4 +77,4 @@
<div id="qunit"></div>
<div id="qunit-fixture"></div>
</body>
</html>
</html>

View file

@ -144,7 +144,7 @@ test('Cannot removeRowBg if row index is NaN', function() {
// assert
deepEqual(tbl.querySelectorAll('tr.odd').length, 3, 'Expected odd bgs');
deepEqual(tbl.querySelectorAll('tr.even').length, 3, 'Expected even bg');
deepEqual(tbl.querySelectorAll('tr.even').length, 3, 'Expected even bgs');
});
test('Cannot destroy if not initialised', function() {
@ -188,9 +188,9 @@ test('Grid layout: initialising alternating rows', function() {
altRows = tf.feature('alternateRows');
deepEqual(
tbl.querySelectorAll('tr.odd').length, 4, 'Expected bg for odd rows');
tbl.querySelectorAll('tr.odd').length, 4, 'Expected bg for odd rows');
deepEqual(
tbl.querySelectorAll('tr.even').length, 3, 'Expected bg for even rows');
tbl.querySelectorAll('tr.even').length, 3, 'Expected bg for even rows');
});
test('Grid layout: filter column', function() {
@ -226,8 +226,41 @@ test('Grid layout: remove alternating rows', function() {
deepEqual(tbl.querySelectorAll('tr.even').length, 0, 'Even bg removed');
});
module('Tear-down');
test('can destroy TableFilter DOM elements', function() {
// Issue 365: alternating rows with column sorted at start
test('Sort: alternating rows with column sorted at start', function() {
tf.destroy();
deepEqual(tf.isInitialized(), false, 'Filters removed');
tf = null;
tf = new TableFilter('demo', {
base_path: '../dist/tablefilter/',
alternate_rows: true,
extensions:[{
name: 'sort',
sort_col_at_start: [2, true],
on_sort_loaded: checkAlternateRows
}]
});
tf.init();
altRows = tf.feature('alternateRows');
deepEqual(typeof altRows, 'object', 'AlternateRows instanciated');
deepEqual(altRows.evenCss, 'even', 'Expected even css class');
deepEqual(altRows.oddCss, 'odd', 'Expected odd css class');
function checkAlternateRows(tf) {
tbl = tf.tbl;
altRows = tf.feature('alternateRows');
test('Alternate rows with sort column at start option', function() {
deepEqual(
tbl.rows[2].classList.contains('odd'),
true,
'Expected bg for rows[2]'
);
deepEqual(
tbl.rows[5].classList.contains('even'),
true,
'Expected bg for rows[5]'
);
});
}
});

View file

@ -36,6 +36,21 @@ test('Can filter on checkList item click', function() {
deepEqual(tf.getValidRows().length, 1, 'Table filtered');
deepEqual(tf.getFilteredData()[0][1][3], '1.1', 'Matched value');
});
test('Can refresh all drop-down filters', function() {
//setup
tf.clearFilters();
var build = checkList.build;
var hit = 0;
checkList.build = function() { hit++ };
//act
checkList.refreshAll();
//assert
deepEqual(hit, 1, 'build method called');
checkList.build = build;
});
test('Can select options', function() {
tf.clearFilters();
var flt1 = id(tf.fltIds[3]);
@ -170,4 +185,9 @@ module('Tear down');
test('TableFilter removed', function() {
tf.destroy();
deepEqual(id(tf.fltIds[3]), null, 'CheckList UL element');
deepEqual(
tf.feature('checkList').initialized,
false,
'CheckList not initialised'
);
});

View file

@ -36,6 +36,22 @@ test('Can filter on drop-down change', function() {
deepEqual(tf.getFilteredData()[0][1][3], '1.1', 'Matched value');
});
test('Can refresh all drop-down filters', function() {
//setup
tf.clearFilters();
var build = dropdown.build;
var hit = 0;
dropdown.build = function() { hit++ };
//act
dropdown.refreshAll();
//assert
deepEqual(hit, 2, 'build method called');
dropdown.build = build;
});
test('Can select options', function() {
tf.clearFilters();
var flt1 = id(tf.fltIds[2]);
@ -99,4 +115,9 @@ test('Can sort options', function() {
test('TableFilter removed', function() {
tf.destroy();
deepEqual(id(tf.fltIds[3]), null, 'Filter is removed');
deepEqual(
tf.feature('dropdown').initialized,
false,
'Drop-down not initialised'
);
});

View file

@ -7,7 +7,7 @@ tf.init();
var help = tf.feature('help');
module('Sanity checks');
test('Clear button component', function() {
test('Button element', function() {
deepEqual(typeof help, 'object', 'Help instanciated');
notEqual(help.btn, null, 'btn property');
});
@ -62,6 +62,52 @@ test('Help UI elements', function() {
deepEqual(helpBtn.nodeName, 'SPAN', 'Help button');
});
test('Help container auto-closes when user clicks away', function() {
// setup
help.toggle();
// act
var evObj = document.createEvent('HTMLEvents');
evObj.initEvent('mouseup', true, true);
// mouseup fired from a table cell
tf.tbl.rows[3].cells[2].dispatchEvent(evObj);
// assert
deepEqual(help.cont.style.display, 'none',
'Help container closed after user clicks away'
);
});
// 376 issue: ensure close button closes popup
test('Close button closes popup', function() {
// setup
help.toggle();
// act
var evObj = document.createEvent('HTMLEvents');
evObj.initEvent('click', true, true);
help.cont.querySelector('.close').dispatchEvent(evObj);
// assert
deepEqual(help.cont.style.display, 'none',
'Close button closes popup'
);
});
test('Help button closes popup when already open', function() {
// setup
help.toggle();
// act
var evObj = document.createEvent('HTMLEvents');
evObj.initEvent('click', true, true);
help.btn.querySelector('.helpBtn').dispatchEvent(evObj);
// assert
deepEqual(help.cont.style.display, 'none',
'Close button closes popup'
);
});
module('Destroy and re-init');
test('Remove UI', function() {
help.destroy();

View file

@ -149,7 +149,7 @@ test('Pop-up filter closes upon filtering', function(){
);
});
test('Pop-up filter auto-closes when user clicks away', function(){
test('Pop-up filter auto-closes when user clicks away', function() {
// setup
popupFilter.open(0);

View file

@ -13,8 +13,8 @@ module.exports = {
output: {
path: path.join(__dirname, '/dist/tablefilter'),
filename: 'tablefilter.js',
// chunkFilename: '[name]-[chunkhash].js',
chunkFilename: 'tf-[name].js',
chunkFilename: 'tf-[name]-[chunkhash].js',
// chunkFilename: 'tf-[name].js',
libraryTarget: 'umd'
},
resolve: {
@ -54,6 +54,7 @@ module.exports = {
]
},
build: {
devtool: 'source-map',
plugins: [
new Clean(['dist']),
new webpack.optimize.DedupePlugin(),
@ -76,7 +77,7 @@ module.exports = {
]
},
dev: {
devtool: 'sourcemap',
devtool: 'source-map',
debug: true,
plugins: [
new webpack.optimize.DedupePlugin(),