mirror of
https://github.com/koalyptus/TableFilter.git
synced 2024-05-21 15:56:40 +02:00
Merge pull request #108 from koalyptus/pub-sub-refactoring
Pub sub refactoring
This commit is contained in:
commit
8335d35c39
|
@ -11,7 +11,7 @@
|
|||
"trailing": true,
|
||||
"quotmark": "single",
|
||||
"immed": true,
|
||||
"maxstatements": 198,
|
||||
"maxstatements": 172,
|
||||
"maxdepth": 7,
|
||||
"maxcomplexity": 104
|
||||
"maxcomplexity": 85
|
||||
}
|
|
@ -34,6 +34,10 @@ git clone --bare https://github.com/koalyptus/TableFilter.git
|
|||
```shell
|
||||
npm install tablefilter --save
|
||||
```
|
||||
* or get the future features from the ``next`` release channel:
|
||||
```shell
|
||||
npm install tablefilter@next --save
|
||||
```
|
||||
|
||||
## Setup
|
||||
Copy the ``tablefilter`` directory under ``dist`` and place it at desired location in your project. Then include the main js file in your page:
|
||||
|
|
4
dist/starter.html
vendored
4
dist/starter.html
vendored
|
@ -1,10 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>tablefilter v0.0.23 - Starter</title>
|
||||
<title>tablefilter v0.1.9 - Starter</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>tablefilter v0.0.23</h1>
|
||||
<h1>tablefilter v0.1.9</h1>
|
||||
|
||||
|
||||
|
||||
|
|
4
dist/tablefilter/style/colsVisibility.css
vendored
4
dist/tablefilter/style/colsVisibility.css
vendored
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* tablefilter v0.0.23 by Max Guglielmi
|
||||
* build date: 2016-01-15T07:08:13.103Z
|
||||
* tablefilter v0.1.9 by Max Guglielmi
|
||||
* build date: 2016-01-27T10:49:29.388Z
|
||||
* 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}
|
4
dist/tablefilter/style/filtersVisibility.css
vendored
4
dist/tablefilter/style/filtersVisibility.css
vendored
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* tablefilter v0.0.23 by Max Guglielmi
|
||||
* build date: 2016-01-15T07:08:13.103Z
|
||||
* tablefilter v0.1.9 by Max Guglielmi
|
||||
* build date: 2016-01-27T10:49:29.388Z
|
||||
* 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}
|
4
dist/tablefilter/style/tablefilter.css
vendored
4
dist/tablefilter/style/tablefilter.css
vendored
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* tablefilter v0.0.23 by Max Guglielmi
|
||||
* build date: 2016-01-15T07:08:13.103Z
|
||||
* tablefilter v0.1.9 by Max Guglielmi
|
||||
* build date: 2016-01-27T10:49:29.388Z
|
||||
* MIT License
|
||||
*/
|
||||
.activeHeader{background-color:#66afe9 !important;color:#fff !important}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* tablefilter v0.0.23 by Max Guglielmi
|
||||
* build date: 2016-01-15T07:08:13.103Z
|
||||
* tablefilter v0.1.9 by Max Guglielmi
|
||||
* build date: 2016-01-27T10:49:29.388Z
|
||||
* MIT License
|
||||
*/
|
||||
table.TF{border-left:1px solid #ccc !important;border-top:none !important;border-right:none !important;border-bottom:none !important;}table.TF th{background:#ebecee url("images/bg_th.jpg") left top repeat-x !important;border-bottom:1px solid #d0d0d0 !important;border-right:1px solid #d0d0d0 !important;border-left:1px solid #fff !important;border-top:1px solid #fff !important;color:#333 !important}table.TF td{border-bottom:1px dotted #999 !important;padding:5px !important}.fltrow{background-color:#ebecee !important;}.fltrow th,.fltrow td{border-bottom:1px dotted #666 !important;padding:1px 3px 1px 3px !important}.flt,select.flt,select.flt_multi,.flt_s,.single_flt,.div_checklist{border:1px solid #999 !important}input.flt{width:99% !important}.inf{height:$min-height;background:#d7d7d7 url("images/bg_infDiv.jpg") 0 0 repeat-x !important}input.reset{background:transparent url("images/btn_eraser.gif") center center no-repeat !important}.helpBtn:hover{background-color:transparent}.nextPage{background:transparent url("images/btn_next_page.gif") center center no-repeat !important;}.nextPage:hover{background:transparent url("images/btn_over_next_page.gif") center center no-repeat !important}.previousPage{background:transparent url("images/btn_previous_page.gif") center center no-repeat !important;}.previousPage:hover{background:transparent url("images/btn_over_previous_page.gif") center center no-repeat !important}.firstPage{background:transparent url("images/btn_first_page.gif") center center no-repeat !important;}.firstPage:hover{background:transparent url("images/btn_over_first_page.gif") center center no-repeat !important}.lastPage{background:transparent url("images/btn_last_page.gif") center center no-repeat !important;}.lastPage:hover{background:transparent url("images/btn_over_last_page.gif") center center no-repeat !important}div.grd_Cont{background-color:#ebecee !important;border:1px solid #ccc !important;padding:0 !important;}div.grd_Cont .even{background-color:#fff}div.grd_Cont .odd{background-color:#d5d5d5}div.grd_headTblCont{background-color:#ebecee !important;border-bottom:none !important;}div.grd_headTblCont table{border-right:none !important}div.grd_tblCont table th,div.grd_headTblCont table th,div.grd_headTblCont table td{background:#ebecee url("images/bg_th.jpg") left top repeat-x !important;border-bottom:1px solid #d0d0d0 !important;border-right:1px solid #d0d0d0 !important;border-left:1px solid #fff !important;border-top:1px solid #fff !important}div.grd_tblCont table td{border-bottom:1px solid #999 !important}.grd_inf{background:#d7d7d7 url("images/bg_infDiv.jpg") 0 0 repeat-x !important;border-top:1px solid #d0d0d0 !important}.loader{border:1px solid #999}.defaultLoader{width:32px;height:32px;background:transparent url("images/img_loading.gif") 0 0 no-repeat !important}.even{background-color:#fff}.odd{background-color:#d5d5d5}span.expClpFlt a.btnExpClpFlt:hover{background-color:transparent !important}
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* tablefilter v0.0.23 by Max Guglielmi
|
||||
* build date: 2016-01-15T07:08:13.103Z
|
||||
* tablefilter v0.1.9 by Max Guglielmi
|
||||
* build date: 2016-01-27T10:49:29.388Z
|
||||
* MIT License
|
||||
*/
|
||||
table.TF{border-left:1px dotted #81963b !important;border-top:none !important;border-right:0 !important;border-bottom:none !important;}table.TF th{background:#39424b url("images/bg_headers.jpg") left top repeat-x !important;border-bottom:0 !important;border-right:1px dotted #d0d0d0 !important;border-left:0 !important;border-top:0 !important;color:#fff !important}table.TF td{border-bottom:1px dotted #81963b;border-right:1px dotted #81963b;padding:5px !important}.fltrow{background-color:#81963b !important;}.fltrow th,.fltrow td{border-bottom:1px dotted #39424b !important;border-right:1px dotted #fff !important;border-left:0 !important;border-top:0 !important;padding:1px 3px 1px 3px !important}.flt,select.flt,select.flt_multi,.flt_s,.single_flt,.div_checklist{border:1px solid #687830 !important}input.flt{width:99% !important}.inf{background:#d8d8d8;height:$min-height}input.reset{width:53px;background:transparent url("images/btn_filter.png") center center no-repeat !important}.helpBtn:hover{background-color:transparent}.nextPage{background:transparent url("images/btn_next_page.gif") center center no-repeat !important}.previousPage{background:transparent url("images/btn_previous_page.gif") center center no-repeat !important}.firstPage{background:transparent url("images/btn_first_page.gif") center center no-repeat !important}.lastPage{background:transparent url("images/btn_last_page.gif") center center no-repeat !important}div.grd_Cont{background:#81963b url("images/bg_headers.jpg") left top repeat-x !important;border:1px solid #ccc !important;padding:0 1px 1px 1px !important;}div.grd_Cont .even{background-color:#bccd83}div.grd_Cont .odd{background-color:#fff}div.grd_headTblCont{background-color:#ebecee !important;border-bottom:none !important}div.grd_tblCont table{border-right:none !important;}div.grd_tblCont table td{border-bottom:1px dotted #81963b;border-right:1px dotted #81963b}div.grd_tblCont table th,div.grd_headTblCont table th{background:transparent url("images/bg_headers.jpg") 0 0 repeat-x !important;border-bottom:0 !important;border-right:1px dotted #d0d0d0 !important;border-left:0 !important;border-top:0 !important;padding:0 4px 0 4px !important;color:#fff !important;height:35px !important}div.grd_headTblCont table td{border-bottom:1px dotted #39424b !important;border-right:1px dotted #fff !important;border-left:0 !important;border-top:0 !important;background-color:#81963b !important;padding:1px 3px 1px 3px !important}.grd_inf{background-color:#d8d8d8;border-top:1px solid #d0d0d0 !important}.loader{border:0 !important;background:#81963b !important}.defaultLoader{width:32px;height:32px;background:transparent url("images/img_loading.gif") 0 0 no-repeat !important}.even{background-color:#bccd83}.odd{background-color:#fff}span.expClpFlt a.btnExpClpFlt:hover{background-color:transparent !important}
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* tablefilter v0.0.23 by Max Guglielmi
|
||||
* build date: 2016-01-15T07:08:13.103Z
|
||||
* tablefilter v0.1.9 by Max Guglielmi
|
||||
* build date: 2016-01-27T10:49:29.388Z
|
||||
* 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}
|
12
dist/tablefilter/tablefilter.js
vendored
12
dist/tablefilter/tablefilter.js
vendored
File diff suppressed because one or more lines are too long
8
dist/tablefilter/tf-1.js
vendored
8
dist/tablefilter/tf-1.js
vendored
File diff suppressed because one or more lines are too long
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "tablefilter",
|
||||
"version": "0.0.23",
|
||||
"version": "0.1.9",
|
||||
"description": "A Javascript library making HTML tables filterable and a bit more",
|
||||
"license": "MIT",
|
||||
"author": {
|
||||
|
@ -24,6 +24,9 @@
|
|||
"scripts": {
|
||||
"test": "grunt test"
|
||||
},
|
||||
"publishConfig": {
|
||||
"tag": "next"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.1.2",
|
||||
"babel-loader": "^6.0.1",
|
||||
|
|
50
src/emitter.js
Normal file
50
src/emitter.js
Normal file
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* Event emitter class
|
||||
*/
|
||||
export class Emitter {
|
||||
constructor() {
|
||||
/**
|
||||
* Events object
|
||||
* @type {Object}
|
||||
*/
|
||||
this.events = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribe to an event
|
||||
* @param {Array} evts Collection of event names
|
||||
* @param {Function} fn Function invoked when event is emitted
|
||||
*/
|
||||
on(evts, fn) {
|
||||
evts.forEach((evt)=> {
|
||||
this.events[evt] = this.events[evt] || [];
|
||||
this.events[evt].push(fn);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribe to an event
|
||||
* @param {Array} evts Collection of event names
|
||||
* @param {Function} fn Function invoked when event is emitted
|
||||
*/
|
||||
off(evts, fn) {
|
||||
evts.forEach((evt)=> {
|
||||
if(evt in this.events) {
|
||||
this.events[evt].splice(this.events[evt].indexOf(fn), 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit an event
|
||||
* @param {String} evt Event name followed by any other argument passed to
|
||||
* the invoked function
|
||||
*/
|
||||
emit(evt /*, args...*/) {
|
||||
if(evt in this.events) {
|
||||
for(let i = 0; i < this.events[evt].length; i++) {
|
||||
this.events[evt][i].apply(this, [].slice.call(arguments, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,6 +26,7 @@ export default class AdapterEzEditTable {
|
|||
this._ezEditTable = null;
|
||||
this.cfg = cfg;
|
||||
this.tf = tf;
|
||||
this.emitter = tf.emitter;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -43,6 +44,11 @@ export default class AdapterEzEditTable {
|
|||
if(this.loadStylesheet && !tf.isImported(this.stylesheet, 'link')){
|
||||
tf.import(this.stylesheetName, this.stylesheet, null, 'link');
|
||||
}
|
||||
|
||||
// TODO: hack to prevent ezEditTable enter key event hijaking.
|
||||
// Needs to be fixed in the vendor's library
|
||||
this.emitter.on(['filter-focus', 'filter-blur'],
|
||||
()=> this._toggleForInputFilter());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -293,7 +299,8 @@ export default class AdapterEzEditTable {
|
|||
cfg.on_added_dom_row = function(){
|
||||
tf.nbFilterableRows++;
|
||||
if(!tf.paging){
|
||||
tf.feature('rowsCounter').refresh();
|
||||
tf.emitter.emit('rows-changed', tf, this);
|
||||
//tf.feature('rowsCounter').refresh();
|
||||
} else {
|
||||
tf.nbRows++;
|
||||
tf.nbVisibleRows++;
|
||||
|
@ -314,7 +321,8 @@ export default class AdapterEzEditTable {
|
|||
cfg.actions['delete'].on_after_submit = function(){
|
||||
tf.nbFilterableRows--;
|
||||
if(!tf.paging){
|
||||
tf.feature('rowsCounter').refresh();
|
||||
// tf.feature('rowsCounter').refresh();
|
||||
tf.emitter.emit('rows-changed', tf, this);
|
||||
} else {
|
||||
tf.nbRows--;
|
||||
tf.nbVisibleRows--;
|
||||
|
@ -356,6 +364,35 @@ export default class AdapterEzEditTable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle behaviour
|
||||
*/
|
||||
toggle(){
|
||||
var ezEditTable = this._ezEditTable;
|
||||
if(ezEditTable.editable){
|
||||
ezEditTable.Editable.Remove();
|
||||
} else {
|
||||
ezEditTable.Editable.Set();
|
||||
}
|
||||
if(ezEditTable.selection){
|
||||
ezEditTable.Selection.Remove();
|
||||
} else {
|
||||
ezEditTable.Selection.Set();
|
||||
}
|
||||
}
|
||||
|
||||
_toggleForInputFilter(){
|
||||
var tf = this.tf;
|
||||
if(!tf.activeFlt){
|
||||
return;
|
||||
}
|
||||
var colIndex = tf.activeFlt.getAttribute('ct');
|
||||
var filterType = tf.getFilterType(colIndex);
|
||||
if(filterType === tf.fltTypeInp){
|
||||
this.toggle();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove advanced grid
|
||||
*/
|
||||
|
@ -370,6 +407,9 @@ export default class AdapterEzEditTable {
|
|||
ezEditTable.Editable.Remove();
|
||||
}
|
||||
}
|
||||
|
||||
this.emitter.off(['filter-focus', 'filter-blur'],
|
||||
()=> this._toggleForInputFilter());
|
||||
this.initialized = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,9 @@ export default class ColOps{
|
|||
}
|
||||
|
||||
init(){
|
||||
// subscribe to events
|
||||
this.tf.emitter.on(['after-filtering'], ()=> this.calc());
|
||||
|
||||
this.calc();
|
||||
}
|
||||
|
||||
|
@ -43,7 +46,7 @@ export default class ColOps{
|
|||
*/
|
||||
calc() {
|
||||
var tf = this.tf;
|
||||
if(!tf.isFirstLoad && !tf.hasGrid()){
|
||||
if(!tf.hasGrid()){
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -310,6 +313,9 @@ export default class ColOps{
|
|||
}
|
||||
}
|
||||
|
||||
destroy(){}
|
||||
destroy(){
|
||||
// unsubscribe to events
|
||||
this.tf.emitter.off(['after-filtering'], ()=> this.calc());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ export default class AdapterSortableTable{
|
|||
opts.on_after_sort : null;
|
||||
|
||||
this.tf = tf;
|
||||
this.emitter = tf.emitter;
|
||||
}
|
||||
|
||||
init(){
|
||||
|
@ -85,42 +86,6 @@ export default class AdapterSortableTable{
|
|||
this.stt.onsort = function(){
|
||||
adpt.sorted = true;
|
||||
|
||||
//rows alternating bg issue
|
||||
// TODO: move into AlternateRows component
|
||||
if(tf.alternateRows){
|
||||
let rows = tf.tbl.rows, c = 0;
|
||||
|
||||
let setClass = function(row, i, removeOnly){
|
||||
if(Types.isUndef(removeOnly)){
|
||||
removeOnly = false;
|
||||
}
|
||||
let altRows = tf.feature('alternateRows'),
|
||||
oddCls = altRows.oddCss,
|
||||
evenCls = altRows.evenCss;
|
||||
Dom.removeClass(row, oddCls);
|
||||
Dom.removeClass(row, evenCls);
|
||||
|
||||
if(!removeOnly){
|
||||
Dom.addClass(row, i % 2 ? oddCls : evenCls);
|
||||
}
|
||||
};
|
||||
|
||||
for (let i = tf.refRow; i < tf.nbRows; i++){
|
||||
let isRowValid = rows[i].getAttribute('validRow');
|
||||
if(tf.paging && rows[i].style.display === ''){
|
||||
setClass(rows[i], c);
|
||||
c++;
|
||||
} else {
|
||||
if((isRowValid==='true' || isRowValid===null) &&
|
||||
rows[i].style.display === ''){
|
||||
setClass(rows[i], c);
|
||||
c++;
|
||||
} else {
|
||||
setClass(rows[i], c, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//sort behaviour for paging
|
||||
if(tf.paging){
|
||||
let paginator = tf.feature('paging');
|
||||
|
@ -133,6 +98,8 @@ export default class AdapterSortableTable{
|
|||
if(adpt.onAfterSort){
|
||||
adpt.onAfterSort.call(null, tf, adpt.stt.sortColumn);
|
||||
}
|
||||
|
||||
adpt.emitter.emit('column-sorted', tf, adpt.stt.sortColumn);
|
||||
};
|
||||
|
||||
this.initialized = true;
|
||||
|
|
|
@ -25,9 +25,24 @@ export class AlternateRows extends Feature {
|
|||
return;
|
||||
}
|
||||
|
||||
this.processAll();
|
||||
|
||||
// Subscribe to events
|
||||
this.emitter.on(['row-processed', 'row-paged'],
|
||||
(tf, rowIndex, arrIndex, isValid)=>
|
||||
this.processRow(rowIndex, arrIndex, isValid));
|
||||
this.emitter.on(['column-sorted'], ()=> this.processAll());
|
||||
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
processAll() {
|
||||
if(!this.isEnabled()){
|
||||
return;
|
||||
}
|
||||
var tf = this.tf;
|
||||
var validRowsIndex = tf.validRowsIndex;
|
||||
var noValidRowsIndex = validRowsIndex===null;
|
||||
var validRowsIndex = tf.getValidRows(true);
|
||||
var noValidRowsIndex = validRowsIndex.length === 0;
|
||||
//1st index
|
||||
var beginIndex = noValidRowsIndex ? tf.refRow : 0;
|
||||
// nb indexes
|
||||
|
@ -42,7 +57,19 @@ export class AlternateRows extends Feature {
|
|||
this.setRowBg(rowIdx, idx);
|
||||
idx++;
|
||||
}
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set/remove row background based on row validation
|
||||
* @param {Number} rowIdx Row index
|
||||
* @param {Boolean} isValid Valid row flag
|
||||
*/
|
||||
processRow(rowIdx, arrIdx, isValid) {
|
||||
if(isValid){
|
||||
this.setRowBg(rowIdx, arrIdx);
|
||||
} else {
|
||||
this.removeRowBg(rowIdx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -85,9 +112,16 @@ export class AlternateRows extends Feature {
|
|||
if(!this.initialized){
|
||||
return;
|
||||
}
|
||||
for(var i=this.tf.refRow; i<this.tf.nbRows; i++){
|
||||
for(var i=0; i<this.tf.nbRows; i++){
|
||||
this.removeRowBg(i);
|
||||
}
|
||||
|
||||
// Unsubscribe to events
|
||||
this.emitter.off(['row-processed', 'row-paged'],
|
||||
(tf, rowIndex, arrIndex, isValid)=>
|
||||
this.processRow(rowIndex, arrIndex, isValid));
|
||||
this.emitter.off(['column-sorted'], ()=> this.processAll());
|
||||
|
||||
this.initialized = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
import {Feature} from './feature';
|
||||
import Dom from '../dom';
|
||||
import Arr from '../array';
|
||||
import Str from '../string';
|
||||
import Sort from '../sort';
|
||||
import Event from '../event';
|
||||
|
||||
export class CheckList{
|
||||
export class CheckList extends Feature{
|
||||
|
||||
/**
|
||||
* Checklist UI component
|
||||
* @param {Object} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf){
|
||||
super(tf, 'checkList');
|
||||
|
||||
// Configuration object
|
||||
var f = tf.config();
|
||||
let f = tf.config();
|
||||
|
||||
this.checkListDiv = []; //checklist container div
|
||||
//defines css class for div containing checklist filter
|
||||
|
@ -42,16 +45,14 @@ export class CheckList{
|
|||
this.opts = null;
|
||||
this.optsTxt = null;
|
||||
this.excludedOpts = null;
|
||||
|
||||
this.tf = tf;
|
||||
}
|
||||
|
||||
// TODO: move event here
|
||||
onChange(evt){
|
||||
let elm = evt.target;
|
||||
this.tf.activeFilterId = elm.getAttribute('id');
|
||||
this.tf.activeFlt = Dom.id(this.tf.activeFilterId);
|
||||
this.tf.Evt.onSlcChange.call(this.tf, evt);
|
||||
let tf = this.tf;
|
||||
tf.activeFilterId = elm.getAttribute('id');
|
||||
tf.activeFlt = Dom.id(tf.activeFilterId);
|
||||
tf.filter();
|
||||
}
|
||||
|
||||
optionClick(evt){
|
||||
|
@ -59,18 +60,61 @@ export class CheckList{
|
|||
this.onChange(evt);
|
||||
}
|
||||
|
||||
onCheckListClick(evt){
|
||||
let elm = Event.target(evt);
|
||||
if(this.tf.loadFltOnDemand && elm.getAttribute('filled') === '0'){
|
||||
let ct = elm.getAttribute('ct');
|
||||
let div = this.checkListDiv[ct];
|
||||
this.build(ct);
|
||||
Event.remove(div, 'click', (evt)=> this.onCheckListClick(evt));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build checklist UI asynchronously
|
||||
* @param {Number} colIndex Column index
|
||||
* @param {Boolean} isExternal Render in external container
|
||||
* @param {String} extFltId External container id
|
||||
* Initialize checklist filter
|
||||
* @param {Number} colIndex Column index
|
||||
* @param {Boolean} isExternal External filter flag
|
||||
* @param {DOMElement} container Dom element containing the filter
|
||||
*/
|
||||
build(colIndex, isExternal, extFltId){
|
||||
var tf = this.tf;
|
||||
tf.EvtManager(
|
||||
tf.Evt.name.checklist,
|
||||
{ slcIndex:colIndex, slcExternal:isExternal, slcId:extFltId }
|
||||
init(colIndex, isExternal, container){
|
||||
let tf = this.tf;
|
||||
let externalFltTgtId = isExternal ?
|
||||
tf.externalFltTgtIds[colIndex] : null;
|
||||
|
||||
let divCont = Dom.create('div',
|
||||
['id', this.prfxCheckListDiv+colIndex+'_'+tf.id],
|
||||
['ct', colIndex], ['filled', '0']);
|
||||
divCont.className = this.checkListDivCssClass;
|
||||
|
||||
//filter is appended in desired element
|
||||
if(externalFltTgtId){
|
||||
Dom.id(externalFltTgtId).appendChild(divCont);
|
||||
tf.externalFltEls.push(divCont);
|
||||
} else {
|
||||
container.appendChild(divCont);
|
||||
}
|
||||
|
||||
this.checkListDiv[colIndex] = divCont;
|
||||
tf.fltIds.push(tf.prfxFlt+colIndex+'_'+tf.id);
|
||||
|
||||
if(!tf.loadFltOnDemand){
|
||||
this.build(colIndex);
|
||||
} else {
|
||||
Event.add(divCont, 'click', (evt)=> this.onCheckListClick(evt));
|
||||
divCont.appendChild(Dom.text(this.activateCheckListTxt));
|
||||
}
|
||||
|
||||
this.emitter.on(
|
||||
['build-checklist-filter'],
|
||||
(tf, colIndex, isExternal)=> this.build(colIndex, isExternal)
|
||||
);
|
||||
|
||||
this.emitter.on(
|
||||
['select-checklist-options'],
|
||||
(tf, colIndex, values)=> this.selectOptions(colIndex, values)
|
||||
);
|
||||
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,48 +123,50 @@ export class CheckList{
|
|||
* @param {Boolean} isExternal Render in external container
|
||||
* @param {String} extFltId External container id
|
||||
*/
|
||||
_build(colIndex, isExternal=false, extFltId=null){
|
||||
var tf = this.tf;
|
||||
build(colIndex, isExternal=false, extFltId=null){
|
||||
let tf = this.tf;
|
||||
colIndex = parseInt(colIndex, 10);
|
||||
|
||||
this.emitter.emit('before-populating-filter', tf, colIndex);
|
||||
|
||||
this.opts = [];
|
||||
this.optsTxt = [];
|
||||
|
||||
var divFltId = this.prfxCheckListDiv+colIndex+'_'+tf.id;
|
||||
let divFltId = this.prfxCheckListDiv+colIndex+'_'+tf.id;
|
||||
if((!Dom.id(divFltId) && !isExternal) ||
|
||||
(!Dom.id(extFltId) && isExternal)){
|
||||
return;
|
||||
}
|
||||
|
||||
var flt = !isExternal ? this.checkListDiv[colIndex] : Dom.id(extFltId);
|
||||
var ul = Dom.create(
|
||||
let flt = !isExternal ? this.checkListDiv[colIndex] : Dom.id(extFltId);
|
||||
let ul = Dom.create(
|
||||
'ul', ['id', tf.fltIds[colIndex]], ['colIndex', colIndex]);
|
||||
ul.className = this.checkListCssClass;
|
||||
Event.add(ul, 'change', (evt) => { this.onChange(evt); });
|
||||
Event.add(ul, 'change', (evt)=> this.onChange(evt));
|
||||
|
||||
var rows = tf.tbl.rows;
|
||||
let rows = tf.tbl.rows;
|
||||
this.isCustom = tf.isCustomOptions(colIndex);
|
||||
|
||||
var activeFlt;
|
||||
let activeFlt;
|
||||
if(tf.linkedFilters && tf.activeFilterId){
|
||||
activeFlt = tf.activeFilterId.split('_')[0];
|
||||
activeFlt = activeFlt.split(tf.prfxFlt)[1];
|
||||
}
|
||||
|
||||
var filteredDataCol = [];
|
||||
let filteredDataCol = [];
|
||||
if(tf.linkedFilters && tf.disableExcludedOptions){
|
||||
this.excludedOpts = [];
|
||||
}
|
||||
|
||||
for(var k=tf.refRow; k<tf.nbRows; k++){
|
||||
for(let k=tf.refRow; k<tf.nbRows; k++){
|
||||
// always visible rows don't need to appear on selects as always
|
||||
// valid
|
||||
if(tf.hasVisibleRows && tf.visibleRows.indexOf(k) !== -1){
|
||||
continue;
|
||||
}
|
||||
|
||||
var cells = rows[k].cells;
|
||||
var ncells = cells.length;
|
||||
let cells = rows[k].cells;
|
||||
let ncells = cells.length;
|
||||
|
||||
// checks if row has exact cell #
|
||||
if(ncells !== tf.nbCells || this.isCustom){
|
||||
|
@ -128,7 +174,7 @@ export class CheckList{
|
|||
}
|
||||
|
||||
// this loop retrieves cell data
|
||||
for(var j=0; j<ncells; j++){
|
||||
for(let j=0; j<ncells; j++){
|
||||
// WTF: cyclomatic complexity hell :)
|
||||
if((colIndex===j && (!tf.linkedFilters ||
|
||||
(tf.linkedFilters && tf.disableExcludedOptions)))||
|
||||
|
@ -137,22 +183,21 @@ export class CheckList{
|
|||
(tf.paging && ((!activeFlt || activeFlt===colIndex )||
|
||||
(activeFlt!=colIndex &&
|
||||
tf.validRowsIndex.indexOf(k) != -1)) )))){
|
||||
var cell_data = tf.getCellData(cells[j]);
|
||||
let cell_data = tf.getCellData(cells[j]);
|
||||
//Vary Peter's patch
|
||||
var cell_string = Str.matchCase(cell_data, tf.matchCase);
|
||||
let cell_string = Str.matchCase(cell_data, tf.matchCase);
|
||||
// checks if celldata is already in array
|
||||
if(!Arr.has(this.opts, cell_string, tf.matchCase)){
|
||||
this.opts.push(cell_data);
|
||||
}
|
||||
var filteredCol = filteredDataCol[j];
|
||||
let filteredCol = filteredDataCol[j];
|
||||
if(tf.linkedFilters && tf.disableExcludedOptions){
|
||||
if(!filteredCol){
|
||||
filteredCol = tf.getFilteredDataCol(j);
|
||||
}
|
||||
if(!Arr.has(filteredCol, cell_string, tf.matchCase) &&
|
||||
!Arr.has(this.excludedOpts,
|
||||
cell_string, tf.matchCase) &&
|
||||
!tf.isFirstLoad){
|
||||
cell_string, tf.matchCase)){
|
||||
this.excludedOpts.push(cell_data);
|
||||
}
|
||||
}
|
||||
|
@ -162,7 +207,7 @@ export class CheckList{
|
|||
|
||||
//Retrieves custom values
|
||||
if(this.isCustom){
|
||||
var customValues = tf.getCustomOptions(colIndex);
|
||||
let customValues = tf.getCustomOptions(colIndex);
|
||||
this.opts = customValues[0];
|
||||
this.optsTxt = customValues[1];
|
||||
}
|
||||
|
@ -220,13 +265,15 @@ export class CheckList{
|
|||
}//in case there are alphanumeric values
|
||||
}
|
||||
|
||||
this.addChecks(colIndex, ul, tf.separator);
|
||||
this.addChecks(colIndex, ul);
|
||||
|
||||
if(tf.loadFltOnDemand){
|
||||
flt.innerHTML = '';
|
||||
}
|
||||
flt.appendChild(ul);
|
||||
flt.setAttribute('filled', '1');
|
||||
|
||||
this.emitter.emit('after-populating-filter', tf, colIndex, flt);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -235,55 +282,30 @@ export class CheckList{
|
|||
* @param {Object} ul Ul element
|
||||
*/
|
||||
addChecks(colIndex, ul){
|
||||
var tf = this.tf;
|
||||
var chkCt = this.addTChecks(colIndex, ul);
|
||||
var fltArr = []; //remember grid values
|
||||
var store = tf.feature('store');
|
||||
var tmpVal = store ?
|
||||
store.getFilterValues(tf.fltsValuesCookie)[colIndex] : null;
|
||||
if(tmpVal && Str.trim(tmpVal).length > 0){
|
||||
if(tf.hasCustomSlcOptions &&
|
||||
tf.customSlcOptions.cols.indexOf(colIndex) != -1){
|
||||
fltArr.push(tmpVal);
|
||||
} else {
|
||||
fltArr = tmpVal.split(' '+tf.orOperator+' ');
|
||||
}
|
||||
}
|
||||
let tf = this.tf;
|
||||
let chkCt = this.addTChecks(colIndex, ul);
|
||||
|
||||
for(var y=0; y<this.opts.length; y++){
|
||||
var val = this.opts[y]; //item value
|
||||
var lbl = this.isCustom ? this.optsTxt[y] : val; //item text
|
||||
var li = Dom.createCheckItem(
|
||||
for(let y=0; y<this.opts.length; y++){
|
||||
let val = this.opts[y]; //item value
|
||||
let lbl = this.isCustom ? this.optsTxt[y] : val; //item text
|
||||
let li = Dom.createCheckItem(
|
||||
tf.fltIds[colIndex]+'_'+(y+chkCt), val, lbl);
|
||||
li.className = this.checkListItemCssClass;
|
||||
if(tf.linkedFilters && tf.disableExcludedOptions &&
|
||||
Arr.has(this.excludedOpts,
|
||||
Str.matchCase(val, tf.matchCase), tf.matchCase)){
|
||||
Dom.addClass(li, this.checkListItemDisabledCssClass);
|
||||
li.check.disabled = true;
|
||||
li.disabled = true;
|
||||
Str.matchCase(val, tf.matchCase), tf.matchCase)){
|
||||
Dom.addClass(li, this.checkListItemDisabledCssClass);
|
||||
li.check.disabled = true;
|
||||
li.disabled = true;
|
||||
} else {
|
||||
Event.add(li.check, 'click',
|
||||
(evt) => { this.optionClick(evt); });
|
||||
Event.add(li.check, 'click', (evt)=> this.optionClick(evt));
|
||||
}
|
||||
ul.appendChild(li);
|
||||
|
||||
if(val===''){
|
||||
if(val === ''){
|
||||
//item is hidden
|
||||
li.style.display = 'none';
|
||||
}
|
||||
|
||||
/*** remember grid values ***/
|
||||
if(tf.rememberGridValues){
|
||||
if((tf.hasCustomSlcOptions &&
|
||||
tf.customSlcOptions.cols.indexOf(colIndex) != -1 &&
|
||||
fltArr.toString().indexOf(val) != -1) ||
|
||||
Arr.has(fltArr,
|
||||
Str.matchCase(val, tf.matchCase), tf.matchCase)){
|
||||
li.check.checked = true;
|
||||
this.setCheckListValues(li.check);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -293,43 +315,37 @@ export class CheckList{
|
|||
* @param {Object} ul Ul element
|
||||
*/
|
||||
addTChecks(colIndex, ul){
|
||||
var tf = this.tf;
|
||||
var chkCt = 1;
|
||||
var li0 = Dom.createCheckItem(
|
||||
let tf = this.tf;
|
||||
let chkCt = 1;
|
||||
let li0 = Dom.createCheckItem(
|
||||
tf.fltIds[colIndex]+'_0', '', tf.displayAllText);
|
||||
li0.className = this.checkListItemCssClass;
|
||||
ul.appendChild(li0);
|
||||
|
||||
Event.add(li0.check, 'click', (evt) => {
|
||||
this.optionClick(evt);
|
||||
});
|
||||
Event.add(li0.check, 'click', (evt)=> this.optionClick(evt));
|
||||
|
||||
if(!this.enableCheckListResetFilter){
|
||||
li0.style.display = 'none';
|
||||
}
|
||||
|
||||
if(tf.enableEmptyOption){
|
||||
var li1 = Dom.createCheckItem(
|
||||
let li1 = Dom.createCheckItem(
|
||||
tf.fltIds[colIndex]+'_1', tf.emOperator, tf.emptyText);
|
||||
li1.className = this.checkListItemCssClass;
|
||||
ul.appendChild(li1);
|
||||
Event.add(li1.check, 'click', (evt) => {
|
||||
this.optionClick(evt);
|
||||
});
|
||||
Event.add(li1.check, 'click', (evt)=> this.optionClick(evt));
|
||||
chkCt++;
|
||||
}
|
||||
|
||||
if(tf.enableNonEmptyOption){
|
||||
var li2 = Dom.createCheckItem(
|
||||
let li2 = Dom.createCheckItem(
|
||||
tf.fltIds[colIndex]+'_2',
|
||||
tf.nmOperator,
|
||||
tf.nonEmptyText
|
||||
);
|
||||
li2.className = this.checkListItemCssClass;
|
||||
ul.appendChild(li2);
|
||||
Event.add(li2.check, 'click', (evt) => {
|
||||
this.optionClick(evt);
|
||||
});
|
||||
Event.add(li2.check, 'click', (evt)=> this.optionClick(evt));
|
||||
chkCt++;
|
||||
}
|
||||
return chkCt;
|
||||
|
@ -343,32 +359,32 @@ export class CheckList{
|
|||
if(!o){
|
||||
return;
|
||||
}
|
||||
var tf = this.tf;
|
||||
var chkValue = o.value; //checked item value
|
||||
var chkIndex = parseInt(o.id.split('_')[2], 10);
|
||||
var filterTag = 'ul', itemTag = 'li';
|
||||
var n = o;
|
||||
let tf = this.tf;
|
||||
let chkValue = o.value; //checked item value
|
||||
let chkIndex = parseInt(o.id.split('_')[2], 10);
|
||||
let filterTag = 'ul', itemTag = 'li';
|
||||
let n = o;
|
||||
|
||||
//ul tag search
|
||||
while(Str.lower(n.nodeName)!==filterTag){
|
||||
n = n.parentNode;
|
||||
}
|
||||
|
||||
var li = n.childNodes[chkIndex];
|
||||
var colIndex = n.getAttribute('colIndex');
|
||||
var fltValue = n.getAttribute('value'); //filter value (ul tag)
|
||||
var fltIndexes = n.getAttribute('indexes'); //selected items (ul tag)
|
||||
let li = n.childNodes[chkIndex];
|
||||
let colIndex = n.getAttribute('colIndex');
|
||||
let fltValue = n.getAttribute('value'); //filter value (ul tag)
|
||||
let fltIndexes = n.getAttribute('indexes'); //selected items (ul tag)
|
||||
|
||||
if(o.checked){
|
||||
//show all item
|
||||
if(chkValue===''){
|
||||
if((fltIndexes && fltIndexes!=='')){
|
||||
//items indexes
|
||||
var indSplit = fltIndexes.split(tf.separator);
|
||||
let indSplit = fltIndexes.split(tf.separator);
|
||||
//checked items loop
|
||||
for(var u=0; u<indSplit.length; u++){
|
||||
for(let u=0; u<indSplit.length; u++){
|
||||
//checked item
|
||||
var cChk = Dom.id(tf.fltIds[colIndex]+'_'+indSplit[u]);
|
||||
let cChk = Dom.id(tf.fltIds[colIndex]+'_'+indSplit[u]);
|
||||
if(cChk){
|
||||
cChk.checked = false;
|
||||
Dom.removeClass(
|
||||
|
@ -386,7 +402,7 @@ export class CheckList{
|
|||
chkValue = Str.trim(
|
||||
fltValue+' '+chkValue+' '+tf.orOperator);
|
||||
chkIndex = fltIndexes + chkIndex + tf.separator;
|
||||
n.setAttribute('value', chkValue );
|
||||
n.setAttribute('value', chkValue);
|
||||
n.setAttribute('indexes', chkIndex);
|
||||
//1st option unchecked
|
||||
if(Dom.id(tf.fltIds[colIndex]+'_0')){
|
||||
|
@ -401,12 +417,12 @@ export class CheckList{
|
|||
}
|
||||
} else { //removes values and indexes
|
||||
if(chkValue!==''){
|
||||
var replaceValue = new RegExp(
|
||||
let replaceValue = new RegExp(
|
||||
Str.rgxEsc(chkValue+' '+tf.orOperator));
|
||||
fltValue = fltValue.replace(replaceValue,'');
|
||||
n.setAttribute('value', Str.trim(fltValue));
|
||||
|
||||
var replaceIndex = new RegExp(
|
||||
let replaceIndex = new RegExp(
|
||||
Str.rgxEsc(chkIndex + tf.separator));
|
||||
fltIndexes = fltIndexes.replace(replaceIndex, '');
|
||||
n.setAttribute('indexes', fltIndexes);
|
||||
|
@ -416,4 +432,49 @@ export class CheckList{
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Select filter options programmatically
|
||||
* @param {Number} colIndex Column index
|
||||
* @param {Array} values Array of option values to select
|
||||
*/
|
||||
selectOptions(colIndex, values=[]){
|
||||
let tf = this.tf;
|
||||
if(tf.getFilterType(colIndex) !== tf.fltTypeCheckList ||
|
||||
values.length === 0){
|
||||
return;
|
||||
}
|
||||
let flt = tf.getFilterElement(colIndex);
|
||||
|
||||
let lisNb = Dom.tag(flt, 'li').length;
|
||||
|
||||
flt.setAttribute('value', '');
|
||||
flt.setAttribute('indexes', '');
|
||||
|
||||
for(let k=0; k<lisNb; k++){
|
||||
let li = Dom.tag(flt, 'li')[k],
|
||||
lbl = Dom.tag(li, 'label')[0],
|
||||
chk = Dom.tag(li, 'input')[0],
|
||||
lblTxt = Str.matchCase(Dom.getText(lbl), tf.caseSensitive);
|
||||
if(lblTxt !== '' && Arr.has(values, lblTxt, tf.caseSensitive)){
|
||||
chk.checked = true;
|
||||
this.setCheckListValues(chk);
|
||||
}
|
||||
else{
|
||||
chk.checked = false;
|
||||
this.setCheckListValues(chk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
destroy(){
|
||||
this.emitter.off(
|
||||
['build-checklist-filter'],
|
||||
(tf, colIndex, isExternal)=> this.build(colIndex, isExternal)
|
||||
);
|
||||
this.emitter.off(
|
||||
['select-checklist-options'],
|
||||
(tf, colIndex, values)=> this.selectOptions(colIndex, values)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
import {Feature} from './feature';
|
||||
import Dom from '../dom';
|
||||
import Arr from '../array';
|
||||
import Str from '../string';
|
||||
import Sort from '../sort';
|
||||
import Event from '../event';
|
||||
|
||||
export class Dropdown{
|
||||
export class Dropdown extends Feature{
|
||||
|
||||
/**
|
||||
* Dropdown UI component
|
||||
* @param {Object} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf){
|
||||
super(tf, 'dropdown');
|
||||
|
||||
// Configuration object
|
||||
var f = tf.config();
|
||||
let f = tf.config();
|
||||
|
||||
this.enableSlcResetFilter = f.enable_slc_reset_filter===false ?
|
||||
false : true;
|
||||
|
@ -30,51 +34,108 @@ export class Dropdown{
|
|||
this.opts = null;
|
||||
this.optsTxt = null;
|
||||
this.slcInnerHtml = null;
|
||||
}
|
||||
|
||||
this.tf = tf;
|
||||
onSlcFocus(e) {
|
||||
let elm = Event.target(e);
|
||||
let tf = this.tf;
|
||||
tf.activeFilterId = elm.getAttribute('id');
|
||||
tf.activeFlt = Dom.id(tf.activeFilterId);
|
||||
// select is populated when element has focus
|
||||
if(tf.loadFltOnDemand && elm.getAttribute('filled') === '0'){
|
||||
let ct = elm.getAttribute('ct');
|
||||
this.build(ct);
|
||||
}
|
||||
this.emitter.emit('filter-focus', tf, this);
|
||||
}
|
||||
|
||||
onSlcChange() {
|
||||
if(this.tf.onSlcChange){
|
||||
this.tf.filter();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build drop-down filter UI asynchronously
|
||||
* @param {Number} colIndex Column index
|
||||
* @param {Boolean} isLinked Enable linked refresh behaviour
|
||||
* @param {Boolean} isExternal Render in external container
|
||||
* @param {String} extSlcId External container id
|
||||
* Initialize drop-down filter
|
||||
* @param {Number} colIndex Column index
|
||||
* @param {Boolean} isExternal External filter flag
|
||||
* @param {DOMElement} container Dom element containing the filter
|
||||
*/
|
||||
build(colIndex, isLinked, isExternal, extSlcId){
|
||||
var tf = this.tf;
|
||||
tf.EvtManager(
|
||||
tf.Evt.name.dropdown,
|
||||
{
|
||||
slcIndex: colIndex,
|
||||
slcRefreshed: isLinked,
|
||||
slcExternal: isExternal,
|
||||
slcId: extSlcId
|
||||
}
|
||||
init(colIndex, isExternal, container){
|
||||
let tf = this.tf;
|
||||
let col = tf.getFilterType(colIndex);
|
||||
let externalFltTgtId = isExternal ?
|
||||
tf.externalFltTgtIds[colIndex] : null;
|
||||
|
||||
let slc = Dom.create(tf.fltTypeSlc,
|
||||
['id', tf.prfxFlt+colIndex+'_'+tf.id],
|
||||
['ct', colIndex], ['filled', '0']
|
||||
);
|
||||
|
||||
if(col === tf.fltTypeMulti){
|
||||
slc.multiple = tf.fltTypeMulti;
|
||||
slc.title = this.multipleSlcTooltip;
|
||||
}
|
||||
slc.className = Str.lower(col) === tf.fltTypeSlc ?
|
||||
tf.fltCssClass : tf.fltMultiCssClass;
|
||||
|
||||
//filter is appended in container element
|
||||
if(externalFltTgtId){
|
||||
Dom.id(externalFltTgtId).appendChild(slc);
|
||||
tf.externalFltEls.push(slc);
|
||||
} else {
|
||||
container.appendChild(slc);
|
||||
}
|
||||
|
||||
tf.fltIds.push(slc.id);
|
||||
|
||||
if(!tf.loadFltOnDemand){
|
||||
this.build(colIndex);
|
||||
} else {
|
||||
//1st option is created here since build isn't invoked
|
||||
let opt0 = Dom.createOpt(tf.displayAllText, '');
|
||||
slc.appendChild(opt0);
|
||||
}
|
||||
|
||||
Event.add(slc, 'change', ()=> this.onSlcChange());
|
||||
Event.add(slc, 'focus', (e)=> this.onSlcFocus(e));
|
||||
|
||||
this.emitter.on(
|
||||
['build-select-filter'],
|
||||
(tf, colIndex, isLinked, isExternal)=>
|
||||
this.build(colIndex, isLinked, isExternal)
|
||||
);
|
||||
this.emitter.on(
|
||||
['select-options'],
|
||||
(tf, colIndex, values)=> this.selectOptions(colIndex, values)
|
||||
);
|
||||
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build drop-down filter UI
|
||||
* @param {Number} colIndex Column index
|
||||
* @param {Boolean} isLinked Enable linked refresh behaviour
|
||||
* @param {Boolean} isLinked Enable linked refresh behaviour
|
||||
* @param {Boolean} isExternal Render in external container
|
||||
* @param {String} extSlcId External container id
|
||||
*/
|
||||
_build(colIndex, isLinked=false, isExternal=false, extSlcId=null){
|
||||
var tf = this.tf;
|
||||
build(colIndex, isLinked=false, isExternal=false, extSlcId=null){
|
||||
let tf = this.tf;
|
||||
colIndex = parseInt(colIndex, 10);
|
||||
|
||||
this.emitter.emit('before-populating-filter', tf, colIndex);
|
||||
|
||||
this.opts = [];
|
||||
this.optsTxt = [];
|
||||
this.slcInnerHtml = '';
|
||||
|
||||
var slcId = tf.fltIds[colIndex];
|
||||
let slcId = tf.fltIds[colIndex];
|
||||
if((!Dom.id(slcId) && !isExternal) ||
|
||||
(!Dom.id(extSlcId) && isExternal)){
|
||||
return;
|
||||
}
|
||||
var slc = !isExternal ? Dom.id(slcId) : Dom.id(extSlcId),
|
||||
let slc = !isExternal ? Dom.id(slcId) : Dom.id(extSlcId),
|
||||
rows = tf.tbl.rows,
|
||||
matchCase = tf.matchCase;
|
||||
|
||||
|
@ -82,41 +143,27 @@ export class Dropdown{
|
|||
this.isCustom = tf.isCustomOptions(colIndex);
|
||||
|
||||
//custom selects text
|
||||
var activeFlt;
|
||||
let activeFlt;
|
||||
if(isLinked && tf.activeFilterId){
|
||||
activeFlt = tf.activeFilterId.split('_')[0];
|
||||
activeFlt = activeFlt.split(tf.prfxFlt)[1];
|
||||
}
|
||||
|
||||
/*** remember grid values ***/
|
||||
var fltsValues = [], fltArr = [];
|
||||
if(tf.rememberGridValues){
|
||||
fltsValues =
|
||||
tf.feature('store').getFilterValues(tf.fltsValuesCookie);
|
||||
if(fltsValues && !Str.isEmpty(fltsValues.toString())){
|
||||
if(this.isCustom){
|
||||
fltArr.push(fltsValues[colIndex]);
|
||||
} else {
|
||||
fltArr = fltsValues[colIndex].split(' '+tf.orOperator+' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var excludedOpts = null,
|
||||
let excludedOpts = null,
|
||||
filteredDataCol = null;
|
||||
if(isLinked && tf.disableExcludedOptions){
|
||||
excludedOpts = [];
|
||||
filteredDataCol = [];
|
||||
}
|
||||
|
||||
for(var k=tf.refRow; k<tf.nbRows; k++){
|
||||
for(let k=tf.refRow; k<tf.nbRows; k++){
|
||||
// always visible rows don't need to appear on selects as always
|
||||
// valid
|
||||
if(tf.hasVisibleRows && tf.visibleRows.indexOf(k) !== -1){
|
||||
continue;
|
||||
}
|
||||
|
||||
var cell = rows[k].cells,
|
||||
let cell = rows[k].cells,
|
||||
nchilds = cell.length;
|
||||
|
||||
// checks if row has exact cell #
|
||||
|
@ -125,7 +172,7 @@ export class Dropdown{
|
|||
}
|
||||
|
||||
// this loop retrieves cell data
|
||||
for(var j=0; j<nchilds; j++){
|
||||
for(let j=0; j<nchilds; j++){
|
||||
// WTF: cyclomatic complexity hell
|
||||
if((colIndex===j &&
|
||||
(!isLinked ||
|
||||
|
@ -138,7 +185,7 @@ export class Dropdown{
|
|||
((activeFlt===undefined || activeFlt==colIndex) ||
|
||||
(activeFlt!=colIndex &&
|
||||
tf.validRowsIndex.indexOf(k) != -1 ))) ))){
|
||||
var cell_data = tf.getCellData(cell[j]),
|
||||
let cell_data = tf.getCellData(cell[j]),
|
||||
//Vary Peter's patch
|
||||
cell_string = Str.matchCase(cell_data, matchCase);
|
||||
|
||||
|
@ -148,14 +195,13 @@ export class Dropdown{
|
|||
}
|
||||
|
||||
if(isLinked && tf.disableExcludedOptions){
|
||||
var filteredCol = filteredDataCol[j];
|
||||
let filteredCol = filteredDataCol[j];
|
||||
if(!filteredCol){
|
||||
filteredCol = tf.getFilteredDataCol(j);
|
||||
}
|
||||
if(!Arr.has(filteredCol, cell_string, matchCase) &&
|
||||
!Arr.has(
|
||||
excludedOpts, cell_string, matchCase) &&
|
||||
!this.isFirstLoad){
|
||||
excludedOpts, cell_string, matchCase)){
|
||||
excludedOpts.push(cell_data);
|
||||
}
|
||||
}
|
||||
|
@ -165,7 +211,7 @@ export class Dropdown{
|
|||
|
||||
//Retrieves custom values
|
||||
if(this.isCustom){
|
||||
var customValues = tf.getCustomOptions(colIndex);
|
||||
let customValues = tf.getCustomOptions(colIndex);
|
||||
this.opts = customValues[0];
|
||||
this.optsTxt = customValues[1];
|
||||
}
|
||||
|
@ -224,8 +270,9 @@ export class Dropdown{
|
|||
}
|
||||
|
||||
//populates drop-down
|
||||
this.addOptions(
|
||||
colIndex, slc, isLinked, excludedOpts, fltsValues, fltArr);
|
||||
this.addOptions(colIndex, slc, isLinked, excludedOpts);
|
||||
|
||||
this.emitter.emit('after-populating-filter', tf, colIndex, slc);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -234,24 +281,22 @@ export class Dropdown{
|
|||
* @param {Object} slc Select Dom element
|
||||
* @param {Boolean} isLinked Enable linked refresh behaviour
|
||||
* @param {Array} excludedOpts Array of excluded options
|
||||
* @param {Array} fltsValues Collection of persisted filter values
|
||||
* @param {Array} fltArr Collection of persisted filter values
|
||||
*/
|
||||
addOptions(colIndex, slc, isLinked, excludedOpts, fltsValues, fltArr){
|
||||
var tf = this.tf,
|
||||
addOptions(colIndex, slc, isLinked, excludedOpts){
|
||||
let tf = this.tf,
|
||||
fillMethod = Str.lower(this.slcFillingMethod),
|
||||
slcValue = slc.value;
|
||||
|
||||
slc.innerHTML = '';
|
||||
slc = this.addFirstOption(slc);
|
||||
|
||||
for(var y=0; y<this.opts.length; y++){
|
||||
for(let y=0; y<this.opts.length; y++){
|
||||
if(this.opts[y]===''){
|
||||
continue;
|
||||
}
|
||||
var val = this.opts[y]; //option value
|
||||
var lbl = this.isCustom ? this.optsTxt[y] : val; //option text
|
||||
var isDisabled = false;
|
||||
let val = this.opts[y]; //option value
|
||||
let lbl = this.isCustom ? this.optsTxt[y] : val; //option text
|
||||
let isDisabled = false;
|
||||
if(isLinked && tf.disableExcludedOptions &&
|
||||
Arr.has(
|
||||
excludedOpts,
|
||||
|
@ -262,7 +307,7 @@ export class Dropdown{
|
|||
}
|
||||
|
||||
if(fillMethod === 'innerhtml'){
|
||||
var slcAttr = '';
|
||||
let slcAttr = '';
|
||||
if(tf.loadFltOnDemand && slcValue===this.opts[y]){
|
||||
slcAttr = 'selected="selected"';
|
||||
}
|
||||
|
@ -270,30 +315,13 @@ export class Dropdown{
|
|||
(isDisabled ? 'disabled="disabled"' : '')+ '>' +
|
||||
lbl+'</option>';
|
||||
} else {
|
||||
var opt;
|
||||
let opt;
|
||||
//fill select on demand
|
||||
if(tf.loadFltOnDemand && slcValue===this.opts[y] &&
|
||||
tf.getFilterType(colIndex) === tf.fltTypeSlc){
|
||||
opt = Dom.createOpt(lbl, val, true);
|
||||
} else {
|
||||
if(tf.getFilterType(colIndex) !== tf.fltTypeMulti){
|
||||
opt = Dom.createOpt(
|
||||
lbl,
|
||||
val,
|
||||
(fltsValues[colIndex]!==' ' &&
|
||||
val===fltsValues[colIndex]) ? true : false
|
||||
);
|
||||
} else {
|
||||
opt = Dom.createOpt(
|
||||
lbl,
|
||||
val,
|
||||
(Arr.has(fltArr,
|
||||
Str.matchCase(this.opts[y], tf.matchCase),
|
||||
tf.matchCase) ||
|
||||
fltArr.toString().indexOf(val)!== -1) ?
|
||||
true : false
|
||||
);
|
||||
}
|
||||
opt = Dom.createOpt(lbl, val, false);
|
||||
}
|
||||
if(isDisabled){
|
||||
opt.disabled = true;
|
||||
|
@ -313,7 +341,7 @@ export class Dropdown{
|
|||
* @param {Object} slc Select DOM element
|
||||
*/
|
||||
addFirstOption(slc){
|
||||
var tf = this.tf,
|
||||
let tf = this.tf,
|
||||
fillMethod = Str.lower(this.slcFillingMethod);
|
||||
|
||||
if(fillMethod === 'innerhtml'){
|
||||
|
@ -321,22 +349,59 @@ export class Dropdown{
|
|||
'</option>';
|
||||
}
|
||||
else {
|
||||
var opt0 = Dom.createOpt(
|
||||
let opt0 = Dom.createOpt(
|
||||
(!this.enableSlcResetFilter ? '' : tf.displayAllText),'');
|
||||
if(!this.enableSlcResetFilter){
|
||||
opt0.style.display = 'none';
|
||||
}
|
||||
slc.appendChild(opt0);
|
||||
if(tf.enableEmptyOption){
|
||||
var opt1 = Dom.createOpt(tf.emptyText, tf.emOperator);
|
||||
let opt1 = Dom.createOpt(tf.emptyText, tf.emOperator);
|
||||
slc.appendChild(opt1);
|
||||
}
|
||||
if(tf.enableNonEmptyOption){
|
||||
var opt2 = Dom.createOpt(tf.nonEmptyText, tf.nmOperator);
|
||||
let opt2 = Dom.createOpt(tf.nonEmptyText, tf.nmOperator);
|
||||
slc.appendChild(opt2);
|
||||
}
|
||||
}
|
||||
return slc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select filter options programmatically
|
||||
* @param {Number} colIndex Column index
|
||||
* @param {Array} values Array of option values to select
|
||||
*/
|
||||
selectOptions(colIndex, values=[]){
|
||||
let tf = this.tf;
|
||||
if(tf.getFilterType(colIndex) !== tf.fltTypeMulti ||
|
||||
values.length === 0){
|
||||
return;
|
||||
}
|
||||
let slc = tf.getFilterElement(colIndex);
|
||||
[].forEach.call(slc.options, (option)=> {
|
||||
// Empty value means clear all selections and first option is the
|
||||
// clear all option
|
||||
if(values[0] === '' || option.value === ''){
|
||||
option.selected = false;
|
||||
}
|
||||
|
||||
if(option.value !== '' &&
|
||||
Arr.has(values, option.value, true)){
|
||||
option.selected = true;
|
||||
}//if
|
||||
});
|
||||
}
|
||||
|
||||
destroy(){
|
||||
this.emitter.off(
|
||||
['build-select-filter'],
|
||||
(colIndex, isLinked, isExternal)=>
|
||||
this.build(colIndex, isLinked, isExternal)
|
||||
);
|
||||
this.emitter.off(
|
||||
['select-options'],
|
||||
(tf, colIndex, values)=> this.selectOptions(colIndex, values)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ export class Feature {
|
|||
this.feature = feature;
|
||||
this.enabled = tf[feature];
|
||||
this.config = tf.config();
|
||||
this.emitter = tf.emitter;
|
||||
this.initialized = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ export class GridLayout extends Feature{
|
|||
constructor(tf){
|
||||
super(tf, 'gridLayout');
|
||||
|
||||
var f = this.config;
|
||||
let f = this.config;
|
||||
|
||||
//defines grid width
|
||||
this.gridWidth = f.grid_width || null;
|
||||
|
@ -54,27 +54,35 @@ export class GridLayout extends Feature{
|
|||
this.prfxGridTh = 'tblHeadTh_';
|
||||
|
||||
this.sourceTblHtml = tf.tbl.outerHTML;
|
||||
|
||||
// filters flag at TF level
|
||||
tf.fltGrid = this.gridEnableFilters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a grid with fixed headers
|
||||
*/
|
||||
init(){
|
||||
var tf = this.tf;
|
||||
var f = this.config;
|
||||
var tbl = tf.tbl;
|
||||
let tf = this.tf;
|
||||
let f = this.config;
|
||||
let tbl = tf.tbl;
|
||||
|
||||
if(this.initialized){
|
||||
return;
|
||||
}
|
||||
|
||||
// Override reference rows indexes
|
||||
tf.refRow = Types.isNull(tf.startRow) ? 0 : tf.startRow;
|
||||
tf.headersRow = 0;
|
||||
tf.filtersRowIndex = 1;
|
||||
|
||||
tf.isExternalFlt = true;
|
||||
|
||||
// default width of 100px if column widths not set
|
||||
if(!tf.hasColWidths){
|
||||
tf.colWidths = [];
|
||||
for(var k=0; k<tf.nbCells; k++){
|
||||
var colW,
|
||||
for(let k=0; k<tf.nbCells; k++){
|
||||
let colW,
|
||||
cell = tbl.rows[this.gridHeadRowIndex].cells[k];
|
||||
if(cell.width !== ''){
|
||||
colW = cell.width;
|
||||
|
@ -89,7 +97,7 @@ export class GridLayout extends Feature{
|
|||
}
|
||||
tf.setColWidths(this.gridHeadRowIndex);
|
||||
|
||||
var tblW;//initial table width
|
||||
let tblW;//initial table width
|
||||
if(tbl.width !== ''){
|
||||
tblW = tbl.width;
|
||||
}
|
||||
|
@ -122,7 +130,7 @@ export class GridLayout extends Feature{
|
|||
this.tblCont.style.height = this.gridHeight;
|
||||
}
|
||||
tbl.parentNode.insertBefore(this.tblCont, tbl);
|
||||
var t = Dom.remove(tbl);
|
||||
let t = Dom.remove(tbl);
|
||||
this.tblCont.appendChild(t);
|
||||
|
||||
//In case table width is expressed in %
|
||||
|
@ -131,7 +139,7 @@ export class GridLayout extends Feature{
|
|||
tbl.clientWidth : tblW) + 'px';
|
||||
}
|
||||
|
||||
var d = Dom.remove(this.tblCont);
|
||||
let d = Dom.remove(this.tblCont);
|
||||
this.tblMainCont.appendChild(d);
|
||||
|
||||
//Headers table container: div wrapping headers table
|
||||
|
@ -148,15 +156,15 @@ export class GridLayout extends Feature{
|
|||
|
||||
//Headers table
|
||||
this.headTbl = Dom.create('table', ['id', this.prfxHeadTbl + tf.id]);
|
||||
var tH = Dom.create('tHead');
|
||||
let tH = Dom.create('tHead');
|
||||
|
||||
//1st row should be headers row, ids are added if not set
|
||||
//Those ids are used by the sort feature
|
||||
var hRow = tbl.rows[this.gridHeadRowIndex];
|
||||
var sortTriggers = [];
|
||||
for(var n=0; n<tf.nbCells; n++){
|
||||
var c = hRow.cells[n];
|
||||
var thId = c.getAttribute('id');
|
||||
let hRow = tbl.rows[this.gridHeadRowIndex];
|
||||
let sortTriggers = [];
|
||||
for(let n=0; n<tf.nbCells; n++){
|
||||
let c = hRow.cells[n];
|
||||
let thId = c.getAttribute('id');
|
||||
if(!thId || thId===''){
|
||||
thId = this.prfxGridTh+n+'_'+tf.id;
|
||||
c.setAttribute('id', thId);
|
||||
|
@ -165,24 +173,24 @@ export class GridLayout extends Feature{
|
|||
}
|
||||
|
||||
//Filters row is created
|
||||
var filtersRow = Dom.create('tr');
|
||||
let filtersRow = Dom.create('tr');
|
||||
if(this.gridEnableFilters && tf.fltGrid){
|
||||
tf.externalFltTgtIds = [];
|
||||
for(var j=0; j<tf.nbCells; j++){
|
||||
var fltTdId = tf.prfxFlt+j+ this.prfxGridFltTd +tf.id;
|
||||
var cl = Dom.create(tf.fltCellTag, ['id', fltTdId]);
|
||||
for(let j=0; j<tf.nbCells; j++){
|
||||
let fltTdId = tf.prfxFlt+j+ this.prfxGridFltTd +tf.id;
|
||||
let cl = Dom.create(tf.fltCellTag, ['id', fltTdId]);
|
||||
filtersRow.appendChild(cl);
|
||||
tf.externalFltTgtIds[j] = fltTdId;
|
||||
}
|
||||
}
|
||||
//Headers row are moved from content table to headers table
|
||||
for(var i=0; i<this.gridHeadRows.length; i++){
|
||||
var headRow = tbl.rows[this.gridHeadRows[0]];
|
||||
for(let i=0; i<this.gridHeadRows.length; i++){
|
||||
let headRow = tbl.rows[this.gridHeadRows[0]];
|
||||
tH.appendChild(headRow);
|
||||
}
|
||||
this.headTbl.appendChild(tH);
|
||||
if(tf.filtersRowIndex === 0){
|
||||
tH.insertBefore(filtersRow,hRow);
|
||||
tH.insertBefore(filtersRow, hRow);
|
||||
} else {
|
||||
tH.appendChild(filtersRow);
|
||||
}
|
||||
|
@ -191,7 +199,7 @@ export class GridLayout extends Feature{
|
|||
this.tblCont.parentNode.insertBefore(this.headTblCont, this.tblCont);
|
||||
|
||||
//THead needs to be removed in content table for sort feature
|
||||
var thead = Dom.tag(tbl, 'thead');
|
||||
let thead = Dom.tag(tbl, 'thead');
|
||||
if(thead.length>0){
|
||||
tbl.removeChild(thead[0]);
|
||||
}
|
||||
|
@ -216,15 +224,15 @@ export class GridLayout extends Feature{
|
|||
|
||||
//scroll synchronisation
|
||||
Event.add(this.tblCont, 'scroll', (evt)=> {
|
||||
var elm = Event.target(evt);
|
||||
var scrollLeft = elm.scrollLeft;
|
||||
let elm = Event.target(evt);
|
||||
let scrollLeft = elm.scrollLeft;
|
||||
this.headTblCont.scrollLeft = scrollLeft;
|
||||
//New pointerX calc taking into account scrollLeft
|
||||
// if(!o.isPointerXOverwritten){
|
||||
// try{
|
||||
// o.Evt.pointerX = function(evt){
|
||||
// var e = evt || global.event;
|
||||
// var bdScrollLeft = tf_StandardBody().scrollLeft +
|
||||
// let e = evt || global.event;
|
||||
// let bdScrollLeft = tf_StandardBody().scrollLeft +
|
||||
// scrollLeft;
|
||||
// return (e.pageX + scrollLeft) ||
|
||||
// (e.clientX + bdScrollLeft);
|
||||
|
@ -237,7 +245,7 @@ export class GridLayout extends Feature{
|
|||
});
|
||||
|
||||
//Configure sort extension if any
|
||||
var sort = (f.extensions || []).filter(function(itm){
|
||||
let sort = (f.extensions || []).filter(function(itm){
|
||||
return itm.name === 'sort';
|
||||
});
|
||||
if(sort.length === 1){
|
||||
|
@ -250,9 +258,9 @@ export class GridLayout extends Feature{
|
|||
|
||||
//Col elements are enough to keep column widths after sorting and
|
||||
//filtering
|
||||
var createColTags = function(){
|
||||
for(var k=(tf.nbCells-1); k>=0; k--){
|
||||
var col = Dom.create('col', ['id', tf.id+'_col_'+k]);
|
||||
let createColTags = function(){
|
||||
for(let k=(tf.nbCells-1); k>=0; k--){
|
||||
let col = Dom.create('col', ['id', tf.id+'_col_'+k]);
|
||||
tbl.insertBefore(col, tbl.firstChild);
|
||||
col.style.width = tf.colWidths[k];
|
||||
this.gridColElms[k] = col;
|
||||
|
@ -263,26 +271,26 @@ export class GridLayout extends Feature{
|
|||
if(!this.tblHasColTag){
|
||||
createColTags.call(this);
|
||||
} else {
|
||||
var cols = Dom.tag(tbl, 'col');
|
||||
for(var ii=0; ii<tf.nbCells; ii++){
|
||||
let cols = Dom.tag(tbl, 'col');
|
||||
for(let ii=0; ii<tf.nbCells; ii++){
|
||||
cols[ii].setAttribute('id', tf.id+'_col_'+ii);
|
||||
cols[ii].style.width = tf.colWidths[ii];
|
||||
this.gridColElms.push(cols[ii]);
|
||||
}
|
||||
}
|
||||
|
||||
var afterColResizedFn = Types.isFn(f.on_after_col_resized) ?
|
||||
let afterColResizedFn = Types.isFn(f.on_after_col_resized) ?
|
||||
f.on_after_col_resized : null;
|
||||
f.on_after_col_resized = function(o, colIndex){
|
||||
if(!colIndex){
|
||||
return;
|
||||
}
|
||||
var w = o.crWColsRow.cells[colIndex].style.width;
|
||||
var col = o.gridColElms[colIndex];
|
||||
let w = o.crWColsRow.cells[colIndex].style.width;
|
||||
let col = o.gridColElms[colIndex];
|
||||
col.style.width = w;
|
||||
|
||||
var thCW = o.crWColsRow.cells[colIndex].clientWidth;
|
||||
var tdCW = o.crWRowDataTbl.cells[colIndex].clientWidth;
|
||||
let thCW = o.crWColsRow.cells[colIndex].clientWidth;
|
||||
let tdCW = o.crWRowDataTbl.cells[colIndex].clientWidth;
|
||||
|
||||
if(thCW != tdCW){
|
||||
o.headTbl.style.width = tbl.clientWidth+'px';
|
||||
|
@ -308,13 +316,13 @@ export class GridLayout extends Feature{
|
|||
* Removes the grid layout
|
||||
*/
|
||||
destroy(){
|
||||
var tf = this.tf;
|
||||
var tbl = tf.tbl;
|
||||
let tf = this.tf;
|
||||
let tbl = tf.tbl;
|
||||
|
||||
if(!this.initialized){
|
||||
return;
|
||||
}
|
||||
var t = Dom.remove(tbl);
|
||||
let t = Dom.remove(tbl);
|
||||
this.tblMainCont.parentNode.insertBefore(t, this.tblMainCont);
|
||||
Dom.remove(this.tblMainCont);
|
||||
|
||||
|
@ -325,7 +333,7 @@ export class GridLayout extends Feature{
|
|||
|
||||
tbl.outerHTML = this.sourceTblHtml;
|
||||
//needed to keep reference of table element for future usage
|
||||
this.tf.tbl = t;
|
||||
this.tf.tbl = Dom.id(tf.id);
|
||||
|
||||
this.initialized = false;
|
||||
}
|
||||
|
|
|
@ -59,6 +59,8 @@ export class Help extends Feature{
|
|||
this.prfxHelpSpan = 'helpSpan_';
|
||||
//id prefix for help elements
|
||||
this.prfxHelpDiv = 'helpDiv_';
|
||||
|
||||
this.emitter.on(['init-help'], ()=> this.init());
|
||||
}
|
||||
|
||||
init(){
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import Dom from '../dom';
|
||||
import Str from '../string';
|
||||
import Types from '../types';
|
||||
|
||||
export class HighlightKeyword{
|
||||
|
||||
|
@ -14,6 +15,19 @@ export class HighlightKeyword{
|
|||
this.highlightedNodes = [];
|
||||
|
||||
this.tf = tf;
|
||||
this.emitter = tf.emitter;
|
||||
}
|
||||
|
||||
init(){
|
||||
this.emitter.on(
|
||||
['before-filtering', 'destroy'],
|
||||
()=> this.unhighlightAll()
|
||||
);
|
||||
this.emitter.on(
|
||||
['highlight-keyword'],
|
||||
(tf, cell, word)=>
|
||||
this.highlight(cell, word, this.highlightCssClass)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -96,13 +110,30 @@ export class HighlightKeyword{
|
|||
* Clear all occurrences of highlighted nodes
|
||||
*/
|
||||
unhighlightAll(){
|
||||
if(!this.tf.highlightKeywords || !this.tf.searchArgs){
|
||||
if(!this.tf.highlightKeywords){
|
||||
return;
|
||||
}
|
||||
for(var y=0; y<this.tf.searchArgs.length; y++){
|
||||
this.unhighlight(
|
||||
this.tf.searchArgs[y], this.highlightCssClass);
|
||||
}
|
||||
// iterate filters values to unhighlight all values
|
||||
this.tf.getFiltersValue().forEach((val)=> {
|
||||
if(Types.isArray(val)){
|
||||
val.forEach((item)=>
|
||||
this.unhighlight(item, this.highlightCssClass));
|
||||
} else {
|
||||
this.unhighlight(val, this.highlightCssClass);
|
||||
}
|
||||
});
|
||||
this.highlightedNodes = [];
|
||||
}
|
||||
|
||||
destroy(){
|
||||
this.emitter.off(
|
||||
['before-filtering', 'destroy'],
|
||||
()=> this.unhighlightAll()
|
||||
);
|
||||
this.emitter.off(
|
||||
['highlight-keyword'],
|
||||
(tf, cell, word)=>
|
||||
this.highlight(cell, word, this.highlightCssClass)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ import {Feature} from './feature';
|
|||
import Dom from '../dom';
|
||||
import Types from '../types';
|
||||
|
||||
var global = window;
|
||||
let global = window;
|
||||
|
||||
export class Loader extends Feature{
|
||||
|
||||
|
@ -10,11 +10,11 @@ export class Loader extends Feature{
|
|||
* Loading message/spinner
|
||||
* @param {Object} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf){
|
||||
constructor(tf) {
|
||||
super(tf, 'loader');
|
||||
|
||||
// TableFilter configuration
|
||||
var f = this.config;
|
||||
let f = this.config;
|
||||
|
||||
//id of container element
|
||||
this.loaderTgtId = f.loader_target_id || null;
|
||||
|
@ -27,7 +27,7 @@ export class Loader extends Feature{
|
|||
//defines css class for loader div
|
||||
this.loaderCssClass = f.loader_css_class || 'loader';
|
||||
//delay for hiding loader
|
||||
this.loaderCloseDelay = 200;
|
||||
this.loaderCloseDelay = 250;
|
||||
//callback function before loader is displayed
|
||||
this.onShowLoader = Types.isFn(f.on_show_loader) ?
|
||||
f.on_show_loader : null;
|
||||
|
@ -43,12 +43,13 @@ export class Loader extends Feature{
|
|||
return;
|
||||
}
|
||||
|
||||
var tf = this.tf;
|
||||
let tf = this.tf;
|
||||
let emitter = this.emitter;
|
||||
|
||||
var containerDiv = Dom.create('div', ['id', this.prfxLoader+tf.id]);
|
||||
let containerDiv = Dom.create('div', ['id', this.prfxLoader+tf.id]);
|
||||
containerDiv.className = this.loaderCssClass;
|
||||
|
||||
var targetEl = !this.loaderTgtId ?
|
||||
let targetEl = !this.loaderTgtId ?
|
||||
tf.tbl.parentNode : Dom.id(this.loaderTgtId);
|
||||
if(!this.loaderTgtId){
|
||||
targetEl.insertBefore(containerDiv, tf.tbl);
|
||||
|
@ -63,15 +64,44 @@ export class Loader extends Feature{
|
|||
}
|
||||
|
||||
this.show('none');
|
||||
|
||||
// Subscribe to events
|
||||
emitter.on([
|
||||
'before-filtering',
|
||||
'before-populating-filter',
|
||||
'before-changing-page',
|
||||
'before-clearing-filters',
|
||||
'before-changing-results-per-page',
|
||||
'before-reset-page',
|
||||
'before-reset-page-length',
|
||||
'before-loading-extensions',
|
||||
'before-loading-themes'
|
||||
],
|
||||
()=> this.show('')
|
||||
);
|
||||
emitter.on([
|
||||
'after-filtering',
|
||||
'after-populating-filter',
|
||||
'after-changing-page',
|
||||
'after-clearing-filters',
|
||||
'after-changing-results-per-page',
|
||||
'after-reset-page',
|
||||
'after-reset-page-length',
|
||||
'after-loading-extensions',
|
||||
'after-loading-themes'
|
||||
],
|
||||
()=> this.show('none')
|
||||
);
|
||||
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
show(p) {
|
||||
if(!this.isEnabled() || this.loaderDiv.style.display === p){
|
||||
if(!this.isEnabled() /*|| this.loaderDiv.style.display === p*/){
|
||||
return;
|
||||
}
|
||||
|
||||
var displayLoader = () => {
|
||||
let displayLoader = () => {
|
||||
if(!this.loaderDiv){
|
||||
return;
|
||||
}
|
||||
|
@ -84,17 +114,48 @@ export class Loader extends Feature{
|
|||
}
|
||||
};
|
||||
|
||||
var t = p === 'none' ? this.loaderCloseDelay : 1;
|
||||
let t = p === 'none' ? this.loaderCloseDelay : 1;
|
||||
global.setTimeout(displayLoader, t);
|
||||
}
|
||||
|
||||
destroy(){
|
||||
destroy() {
|
||||
if(!this.initialized){
|
||||
return;
|
||||
}
|
||||
|
||||
let emitter = this.emitter;
|
||||
|
||||
Dom.remove(this.loaderDiv);
|
||||
this.loaderDiv = null;
|
||||
|
||||
// Unsubscribe to events
|
||||
emitter.off([
|
||||
'before-filtering',
|
||||
'before-populating-filter',
|
||||
'before-changing-page',
|
||||
'before-clearing-filters',
|
||||
'before-changing-results-per-page',
|
||||
'before-reset-page',
|
||||
'before-reset-page-length',
|
||||
'before-loading-extensions',
|
||||
'before-loading-themes'
|
||||
],
|
||||
()=> this.show('')
|
||||
);
|
||||
emitter.off([
|
||||
'after-filtering',
|
||||
'after-populating-filter',
|
||||
'after-changing-page',
|
||||
'after-clearing-filters',
|
||||
'after-changing-results-per-page',
|
||||
'after-reset-page',
|
||||
'after-reset-page-length',
|
||||
'after-loading-extensions',
|
||||
'after-loading-themes'
|
||||
],
|
||||
()=> this.show('none')
|
||||
);
|
||||
|
||||
this.initialized = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,10 +59,22 @@ export class NoResults extends Feature{
|
|||
}
|
||||
|
||||
this.cont = cont;
|
||||
|
||||
// subscribe to after-filtering event
|
||||
this.emitter.on(['after-filtering'], ()=> this.toggle());
|
||||
|
||||
this.initialized = true;
|
||||
this.hide();
|
||||
}
|
||||
|
||||
toggle(){
|
||||
if(this.tf.nbVisibleRows > 0){
|
||||
this.hide();
|
||||
} else {
|
||||
this.show();
|
||||
}
|
||||
}
|
||||
|
||||
show(){
|
||||
if(!this.initialized || !this.isEnabled()){
|
||||
return;
|
||||
|
@ -115,6 +127,9 @@ export class NoResults extends Feature{
|
|||
}
|
||||
Dom.remove(this.cont);
|
||||
this.cont = null;
|
||||
// unsubscribe to after-filtering event
|
||||
this.emitter.off(['after-filtering'], ()=> this.toggle());
|
||||
|
||||
this.initialized = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,8 +120,8 @@ export class Paging extends Feature{
|
|||
//span following pages select (contains ' of ')
|
||||
this.prfxPgAfterSpan = 'pgafterspan_';
|
||||
|
||||
var start_row = this.refRow;
|
||||
var nrows = this.nbRows;
|
||||
var start_row = tf.refRow;
|
||||
var nrows = tf.nbRows;
|
||||
//calculates page nb
|
||||
this.nbPages = Math.ceil((nrows-start_row)/this.pagingLength);
|
||||
|
||||
|
@ -334,6 +334,9 @@ export class Paging extends Feature{
|
|||
this.setPagingInfo(tf.validRowsIndex);
|
||||
}
|
||||
|
||||
this.emitter.on(['after-filtering'], ()=> this.resetPagingInfo());
|
||||
this.emitter.on(['initialized'], ()=> this.resetValues());
|
||||
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
|
@ -343,45 +346,38 @@ export class Paging extends Feature{
|
|||
*/
|
||||
reset(filterTable=false){
|
||||
var tf = this.tf;
|
||||
if(!tf.hasGrid() || this.isEnabled()){
|
||||
if(this.isEnabled()){
|
||||
return;
|
||||
}
|
||||
this.enable();
|
||||
this.init();
|
||||
tf.resetValues();
|
||||
// tf.resetValues();
|
||||
if(filterTable){
|
||||
tf.filter();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset paging info from scratch after a filtering process
|
||||
*/
|
||||
resetPagingInfo(){
|
||||
this.startPagingRow = 0;
|
||||
this.currentPageNb = 1;
|
||||
this.setPagingInfo(this.tf.validRowsIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate number of pages based on valid rows
|
||||
* Refresh paging select according to number of pages
|
||||
* @param {Array} validRows Collection of valid rows
|
||||
*/
|
||||
setPagingInfo(validRows=[]){
|
||||
setPagingInfo(validRows){
|
||||
var tf = this.tf;
|
||||
var rows = tf.tbl.rows;
|
||||
var mdiv = !this.pagingTgtId ? tf.mDiv : Dom.id(this.pagingTgtId);
|
||||
var pgspan = Dom.id(this.prfxPgSpan+tf.id);
|
||||
|
||||
//store valid rows indexes
|
||||
tf.validRowsIndex = validRows;
|
||||
|
||||
if(validRows.length === 0){
|
||||
//counts rows to be grouped
|
||||
for(var j=tf.refRow; j<tf.nbRows; j++){
|
||||
var row = rows[j];
|
||||
if(!row){
|
||||
continue;
|
||||
}
|
||||
|
||||
var isRowValid = row.getAttribute('validRow');
|
||||
if(Types.isNull(isRowValid) || Boolean(isRowValid==='true')){
|
||||
tf.validRowsIndex.push(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
tf.validRowsIndex = validRows || tf.getValidRows(true);
|
||||
|
||||
//calculate nb of pages
|
||||
this.nbPages = Math.ceil(tf.validRowsIndex.length/this.pagingLength);
|
||||
|
@ -417,7 +413,6 @@ export class Paging extends Feature{
|
|||
*/
|
||||
groupByPage(validRows){
|
||||
var tf = this.tf;
|
||||
var alternateRows = tf.feature('alternateRows');
|
||||
var rows = tf.tbl.rows;
|
||||
var startPagingRow = parseInt(this.startPagingRow, 10);
|
||||
var endPagingRow = startPagingRow + parseInt(this.pagingLength, 10);
|
||||
|
@ -432,25 +427,23 @@ export class Paging extends Feature{
|
|||
var validRowIdx = tf.validRowsIndex[h];
|
||||
var r = rows[validRowIdx];
|
||||
var isRowValid = r.getAttribute('validRow');
|
||||
var rowDisplayed = false;
|
||||
|
||||
if(h>=startPagingRow && h<endPagingRow){
|
||||
if(Types.isNull(isRowValid) || Boolean(isRowValid==='true')){
|
||||
r.style.display = '';
|
||||
}
|
||||
if(tf.alternateRows && alternateRows){
|
||||
alternateRows.setRowBg(validRowIdx, h);
|
||||
rowDisplayed = true;
|
||||
}
|
||||
} else {
|
||||
r.style.display = 'none';
|
||||
if(tf.alternateRows && alternateRows){
|
||||
alternateRows.removeRowBg(validRowIdx);
|
||||
}
|
||||
}
|
||||
this.emitter.emit('row-paged', tf, validRowIdx, h, rowDisplayed);
|
||||
}
|
||||
|
||||
tf.nbVisibleRows = tf.validRowsIndex.length;
|
||||
//re-applies filter behaviours after filtering process
|
||||
tf.applyProps();
|
||||
|
||||
// broadcast grouping by page
|
||||
this.emitter.emit('grouped-by-page', tf, this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -504,9 +497,6 @@ export class Paging extends Feature{
|
|||
var tf = this.tf;
|
||||
var evt = this.evt;
|
||||
|
||||
if(!tf.hasGrid() && !tf.isFirstLoad){
|
||||
return;
|
||||
}
|
||||
if(this.resultsPerPageSlc || !this.resultsPerPage){
|
||||
return;
|
||||
}
|
||||
|
@ -569,53 +559,19 @@ export class Paging extends Feature{
|
|||
this.resultsPerPageSlc = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the page asynchronously according to passed index
|
||||
* @param {Number} index Index of the page (0-n)
|
||||
*/
|
||||
changePage(index){
|
||||
var tf = this.tf;
|
||||
var evt = tf.Evt;
|
||||
tf.EvtManager(evt.name.changepage, { pgIndex:index });
|
||||
}
|
||||
|
||||
/**
|
||||
* Change rows asynchronously according to page results
|
||||
*/
|
||||
changeResultsPerPage(){
|
||||
var tf = this.tf;
|
||||
var evt = tf.Evt;
|
||||
tf.EvtManager(evt.name.changeresultsperpage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-set asynchronously page nb at page re-load
|
||||
*/
|
||||
resetPage(){
|
||||
var tf = this.tf;
|
||||
var evt = tf.Evt;
|
||||
tf.EvtManager(evt.name.resetpage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-set asynchronously page length at page re-load
|
||||
*/
|
||||
resetPageLength(){
|
||||
var tf = this.tf;
|
||||
var evt = tf.Evt;
|
||||
tf.EvtManager(evt.name.resetpagelength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the page according to passed index
|
||||
* @param {Number} index Index of the page (0-n)
|
||||
*/
|
||||
_changePage(index){
|
||||
changePage(index){
|
||||
var tf = this.tf;
|
||||
|
||||
if(!this.isEnabled()){
|
||||
return;
|
||||
}
|
||||
|
||||
this.emitter.emit('before-changing-page', tf, index);
|
||||
|
||||
if(index === null){
|
||||
index = this.pageSelectorType===tf.fltTypeSlc ?
|
||||
this.pagingSlc.options.selectedIndex : (this.pagingSlc.value-1);
|
||||
|
@ -643,18 +599,23 @@ export class Paging extends Feature{
|
|||
this.onAfterChangePage.call(null, this, index);
|
||||
}
|
||||
}
|
||||
|
||||
this.emitter.emit('after-changing-page', tf, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change rows according to page results drop-down
|
||||
* TODO: accept a parameter setting the results per page length
|
||||
*/
|
||||
_changeResultsPerPage(){
|
||||
changeResultsPerPage(){
|
||||
var tf = this.tf;
|
||||
|
||||
if(!this.isEnabled()){
|
||||
return;
|
||||
}
|
||||
|
||||
this.emitter.emit('before-changing-results-per-page', tf);
|
||||
|
||||
var slcR = this.resultsPerPageSlc;
|
||||
var slcPagesSelIndex = (this.pageSelectorType===tf.fltTypeSlc) ?
|
||||
this.pagingSlc.selectedIndex :
|
||||
|
@ -678,33 +639,55 @@ export class Paging extends Feature{
|
|||
tf.feature('store').savePageLength(tf.pgLenCookie);
|
||||
}
|
||||
}
|
||||
|
||||
this.emitter.emit('after-changing-results-per-page', tf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-set persisted pagination info
|
||||
*/
|
||||
resetValues(){
|
||||
var tf = this.tf;
|
||||
if(tf.rememberPageLen){
|
||||
this.resetPageLength(tf.pgLenCookie);
|
||||
}
|
||||
if(tf.rememberPageNb){
|
||||
this.resetPage(tf.pgNbCookie);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-set page nb at page re-load
|
||||
*/
|
||||
_resetPage(name){
|
||||
resetPage(name){
|
||||
var tf = this.tf;
|
||||
if(!this.isEnabled()){
|
||||
return;
|
||||
}
|
||||
this.emitter.emit('before-reset-page', tf);
|
||||
var pgnb = tf.feature('store').getPageNb(name);
|
||||
if(pgnb!==''){
|
||||
if(pgnb !== ''){
|
||||
this.changePage((pgnb-1));
|
||||
}
|
||||
this.emitter.emit('after-reset-page', tf, pgnb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-set page length value at page re-load
|
||||
*/
|
||||
_resetPageLength(name){
|
||||
resetPageLength(name){
|
||||
var tf = this.tf;
|
||||
if(!this.isEnabled()){
|
||||
return;
|
||||
}
|
||||
this.emitter.emit('before-reset-page-length', tf);
|
||||
var pglenIndex = tf.feature('store').getPageLength(name);
|
||||
|
||||
if(pglenIndex!==''){
|
||||
this.resultsPerPageSlc.options[pglenIndex].selected = true;
|
||||
this.changeResultsPerPage();
|
||||
}
|
||||
this.emitter.emit('after-reset-page-length', tf, pglenIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -776,6 +759,9 @@ export class Paging extends Feature{
|
|||
this.removeResultsPerPage();
|
||||
}
|
||||
|
||||
this.emitter.off(['after-filtering'], ()=> this.resetPagingInfo());
|
||||
this.emitter.off(['initialized'], ()=> this.resetValues());
|
||||
|
||||
this.pagingSlc = null;
|
||||
this.nbPages = 0;
|
||||
this.disable();
|
||||
|
|
|
@ -15,7 +15,7 @@ export class PopupFilter extends Feature{
|
|||
// Configuration object
|
||||
var f = this.config;
|
||||
|
||||
// Enable external filters behaviour
|
||||
// Enable external filters
|
||||
tf.isExternalFlt = true;
|
||||
tf.externalFltTgtIds = [];
|
||||
|
||||
|
@ -84,6 +84,12 @@ export class PopupFilter extends Feature{
|
|||
}
|
||||
|
||||
var tf = this.tf;
|
||||
|
||||
// Override headers row index if no grouped headers
|
||||
if(tf.headersRow <= 1){
|
||||
tf.headersRow = 0;
|
||||
}
|
||||
|
||||
for(var i=0; i<tf.nbCells; i++){
|
||||
if(tf.getFilterType(i) === tf.fltTypeNone){
|
||||
continue;
|
||||
|
@ -101,6 +107,15 @@ export class PopupFilter extends Feature{
|
|||
this.popUpFltImgs[i] = popUpSpan.firstChild;
|
||||
}
|
||||
|
||||
// subscribe to events
|
||||
this.emitter.on(['before-filtering'], ()=> this.buildIcons());
|
||||
this.emitter.on(['after-filtering'], ()=> this.closeAll());
|
||||
this.emitter.on(['cell-processed'],
|
||||
(tf, cellIndex)=> this.buildIcon(cellIndex, true));
|
||||
this.emitter.on(['filters-row-inserted'], ()=> this.tf.headersRow++);
|
||||
this.emitter.on(['before-filter-init'],
|
||||
(tf, colIndex)=> this.build(colIndex));
|
||||
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
|
@ -204,7 +219,7 @@ export class PopupFilter extends Feature{
|
|||
}
|
||||
|
||||
/**
|
||||
* Build specified icon
|
||||
* Apply specified icon state
|
||||
* @param {Number} colIndex Column index
|
||||
* @param {Boolean} active Apply active state
|
||||
*/
|
||||
|
@ -245,6 +260,16 @@ export class PopupFilter extends Feature{
|
|||
this.popUpFltElms = [];
|
||||
this.popUpFltSpans = [];
|
||||
this.popUpFltImgs = [];
|
||||
|
||||
// unsubscribe to events
|
||||
this.emitter.off(['before-filtering'], ()=> this.buildIcons());
|
||||
this.emitter.off(['after-filtering'], ()=> this.closeAll());
|
||||
this.emitter.off(['cell-processed'],
|
||||
(tf, cellIndex)=> this.buildIcon(cellIndex, true));
|
||||
this.emitter.off(['filters-row-inserted'], ()=> this.tf.headersRow++);
|
||||
this.emitter.off(['before-filter-init'],
|
||||
(tf, colIndex)=> this.build(colIndex));
|
||||
|
||||
this.initialized = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,6 +76,11 @@ export class RowsCounter extends Feature{
|
|||
this.rowsCounterDiv = countDiv;
|
||||
this.rowsCounterSpan = countSpan;
|
||||
|
||||
// subscribe to events
|
||||
this.emitter.on(['after-filtering', 'grouped-by-page'],
|
||||
()=> this.refresh(tf.nbVisibleRows));
|
||||
this.emitter.on(['rows-changed'], ()=> this.refresh());
|
||||
|
||||
this.initialized = true;
|
||||
this.refresh();
|
||||
}
|
||||
|
@ -132,6 +137,12 @@ export class RowsCounter extends Feature{
|
|||
}
|
||||
this.rowsCounterSpan = null;
|
||||
this.rowsCounterDiv = null;
|
||||
|
||||
// unsubscribe to events
|
||||
this.emitter.off(['after-filtering', 'grouped-by-page'],
|
||||
()=> this.refresh(tf.nbVisibleRows));
|
||||
this.emitter.off(['rows-changed'], ()=> this.refresh());
|
||||
|
||||
this.initialized = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import {Feature} from './feature';
|
|||
import Dom from '../dom';
|
||||
import Types from '../types';
|
||||
|
||||
var global = window;
|
||||
let global = window;
|
||||
|
||||
export class StatusBar extends Feature{
|
||||
|
||||
|
@ -14,7 +14,7 @@ export class StatusBar extends Feature{
|
|||
super(tf, 'statusBar');
|
||||
|
||||
// Configuration object
|
||||
var f = this.config;
|
||||
let f = this.config;
|
||||
|
||||
//id of custom container element
|
||||
this.statusBarTgtId = f.status_bar_target_id || null;
|
||||
|
@ -38,6 +38,33 @@ export class StatusBar extends Feature{
|
|||
this.onAfterShowMsg = Types.isFn(f.on_after_show_msg) ?
|
||||
f.on_after_show_msg : null;
|
||||
|
||||
//status messages
|
||||
this.msgFilter = f.msg_filter || 'Filtering data...';
|
||||
//populating drop-downs
|
||||
this.msgPopulate = f.msg_populate || 'Populating filter...';
|
||||
//populating drop-downs
|
||||
this.msgPopulateCheckList = f.msg_populate_checklist ||
|
||||
'Populating list...';
|
||||
//changing paging page
|
||||
this.msgChangePage = f.msg_change_page || 'Collecting paging data...';
|
||||
//clearing filters
|
||||
this.msgClear = f.msg_clear || 'Clearing filters...';
|
||||
//changing nb results/page
|
||||
this.msgChangeResults = f.msg_change_results ||
|
||||
'Changing results per page...';
|
||||
//re-setting page
|
||||
this.msgResetPage = f.msg_reset_page || 'Re-setting page...';
|
||||
//re-setting page length
|
||||
this.msgResetPageLength = f.msg_reset_page_length ||
|
||||
'Re-setting page length...';
|
||||
//table sorting
|
||||
this.msgSort = f.msg_sort || 'Sorting data...';
|
||||
//extensions loading
|
||||
this.msgLoadExtensions = f.msg_load_extensions ||
|
||||
'Loading extensions...';
|
||||
//themes loading
|
||||
this.msgLoadThemes = f.msg_load_themes || 'Loading theme(s)...';
|
||||
|
||||
// status bar div
|
||||
this.prfxStatus = 'status_';
|
||||
// status bar label
|
||||
|
@ -51,16 +78,17 @@ export class StatusBar extends Feature{
|
|||
return;
|
||||
}
|
||||
|
||||
var tf = this.tf;
|
||||
let tf = this.tf;
|
||||
let emitter = this.emitter;
|
||||
|
||||
//status bar container
|
||||
var statusDiv = Dom.create('div', ['id', this.prfxStatus+tf.id]);
|
||||
let statusDiv = Dom.create('div', ['id', this.prfxStatus+tf.id]);
|
||||
statusDiv.className = this.statusBarCssClass;
|
||||
|
||||
//status bar label
|
||||
var statusSpan = Dom.create('span', ['id', this.prfxStatusSpan+tf.id]);
|
||||
let statusSpan = Dom.create('span', ['id', this.prfxStatusSpan+tf.id]);
|
||||
//preceding text
|
||||
var statusSpanText = Dom.create('span',
|
||||
let statusSpanText = Dom.create('span',
|
||||
['id', this.prfxStatusTxt+tf.id]);
|
||||
statusSpanText.appendChild(Dom.text(this.statusBarText));
|
||||
|
||||
|
@ -68,7 +96,7 @@ export class StatusBar extends Feature{
|
|||
if(!this.statusBarTgtId){
|
||||
tf.setToolbar();
|
||||
}
|
||||
var targetEl = (!this.statusBarTgtId) ?
|
||||
let targetEl = (!this.statusBarTgtId) ?
|
||||
tf.lDiv : Dom.id(this.statusBarTgtId);
|
||||
|
||||
//default container: 'lDiv'
|
||||
|
@ -86,6 +114,38 @@ export class StatusBar extends Feature{
|
|||
this.statusBarSpan = statusSpan;
|
||||
this.statusBarSpanText = statusSpanText;
|
||||
|
||||
// Subscribe to events
|
||||
emitter.on(['before-filtering'], ()=> this.message(this.msgFilter));
|
||||
emitter.on(['before-populating-filter'],
|
||||
()=> this.message(this.msgPopulate));
|
||||
emitter.on(['before-changing-page'],
|
||||
()=> this.message(this.msgChangePage));
|
||||
emitter.on(['before-clearing-filters'], ()=>
|
||||
this.message(this.msgClear));
|
||||
emitter.on(['before-changing-results-per-page'],
|
||||
()=> this.message(this.msgChangeResults));
|
||||
emitter.on(['before-reset-page'], ()=> this.message(this.msgResetPage));
|
||||
emitter.on(['before-reset-page-length'],
|
||||
()=> this.message(this.msgResetPageLength));
|
||||
emitter.on(['before-loading-extensions'],
|
||||
()=> this.message(this.msgLoadExtensions));
|
||||
emitter.on(['before-loading-themes'],
|
||||
()=> this.message(this.msgLoadThemes));
|
||||
|
||||
emitter.on([
|
||||
'after-filtering',
|
||||
'after-populating-filter',
|
||||
'after-changing-page',
|
||||
'after-clearing-filters',
|
||||
'after-changing-results-per-page',
|
||||
'after-reset-page',
|
||||
'after-reset-page-length',
|
||||
'after-loading-extensions',
|
||||
'after-loading-themes'
|
||||
],
|
||||
()=> this.message('')
|
||||
);
|
||||
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
|
@ -98,8 +158,11 @@ export class StatusBar extends Feature{
|
|||
this.onBeforeShowMsg.call(null, this.tf, t);
|
||||
}
|
||||
|
||||
var d = t==='' ? this.statusBarCloseDelay : 1;
|
||||
let d = t==='' ? this.statusBarCloseDelay : 1;
|
||||
global.setTimeout(() => {
|
||||
if(!this.initialized){
|
||||
return;
|
||||
}
|
||||
this.statusBarSpan.innerHTML = t;
|
||||
if(this.onAfterShowMsg){
|
||||
this.onAfterShowMsg.call(null, this.tf, t);
|
||||
|
@ -112,11 +175,49 @@ export class StatusBar extends Feature{
|
|||
return;
|
||||
}
|
||||
|
||||
let emitter = this.emitter;
|
||||
|
||||
this.statusBarDiv.innerHTML = '';
|
||||
Dom.remove(this.statusBarDiv);
|
||||
if(!this.statusBarTgtId){
|
||||
Dom.remove(this.statusBarDiv);
|
||||
}
|
||||
this.statusBarSpan = null;
|
||||
this.statusBarSpanText = null;
|
||||
this.statusBarDiv = null;
|
||||
|
||||
// Unsubscribe to events
|
||||
emitter.off(['before-filtering'], ()=> this.message(this.msgFilter));
|
||||
emitter.off(['before-populating-filter'],
|
||||
()=> this.message(this.msgPopulate));
|
||||
emitter.off(['before-changing-page'],
|
||||
()=> this.message(this.msgChangePage));
|
||||
emitter.off(['before-clearing-filters'],
|
||||
()=> this.message(this.msgClear));
|
||||
emitter.off(['before-changing-results-per-page'],
|
||||
()=> this.message(this.msgChangeResults));
|
||||
emitter.off(['before-reset-page'], ()=>
|
||||
this.message(this.msgResetPage));
|
||||
emitter.off(['before-reset-page-length'],
|
||||
()=> this.message(this.msgResetPageLength));
|
||||
emitter.off(['before-loading-extensions'],
|
||||
()=> this.message(this.msgLoadExtensions));
|
||||
emitter.off(['before-loading-themes'],
|
||||
()=> this.message(this.msgLoadThemes));
|
||||
|
||||
emitter.off([
|
||||
'after-filtering',
|
||||
'after-populating-filter',
|
||||
'after-changing-page',
|
||||
'after-clearing-filters',
|
||||
'after-changing-results-per-page',
|
||||
'after-reset-page',
|
||||
'after-reset-page-length',
|
||||
'after-loading-extensions',
|
||||
'after-loading-themes'
|
||||
],
|
||||
()=> this.message('')
|
||||
);
|
||||
|
||||
this.initialized = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import Cookie from '../cookie';
|
||||
import Types from '../types';
|
||||
|
||||
export class Store{
|
||||
|
||||
|
@ -8,13 +9,20 @@ export class Store{
|
|||
*
|
||||
* TODO: use localStorage and fallback to cookie persistence
|
||||
*/
|
||||
constructor(tf) {
|
||||
var f = tf.config();
|
||||
constructor(tf){
|
||||
let f = tf.config();
|
||||
|
||||
this.duration = !isNaN(f.set_cookie_duration) ?
|
||||
parseInt(f.set_cookie_duration, 10) : 100000;
|
||||
|
||||
this.tf = tf;
|
||||
this.emitter = tf.emitter;
|
||||
}
|
||||
|
||||
init(){
|
||||
this.emitter.on(['after-filtering'],
|
||||
()=> this.saveFilterValues(this.tf.fltsValuesCookie));
|
||||
this.emitter.on(['after-clearing-filters'], ()=> this.clearCookies());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -22,20 +30,29 @@ export class Store{
|
|||
* @param {String} cookie name
|
||||
*/
|
||||
saveFilterValues(name){
|
||||
var tf = this.tf;
|
||||
var fltValues = [];
|
||||
let tf = this.tf;
|
||||
let fltValues = [];
|
||||
|
||||
if(!tf.rememberGridValues){
|
||||
return;
|
||||
}
|
||||
|
||||
//store filters' values
|
||||
for(var i=0; i<tf.fltIds.length; i++){
|
||||
var value = tf.getFilterValue(i);
|
||||
for(let i=0; i<tf.fltIds.length; i++){
|
||||
let value = tf.getFilterValue(i);
|
||||
//convert array to a || separated values
|
||||
if(Types.isArray(value)){
|
||||
let rgx = new RegExp(tf.separator, 'g');
|
||||
value = value.toString()
|
||||
.replace(rgx, ' ' + tf.orOperator + ' ');
|
||||
}
|
||||
if (value === ''){
|
||||
value = ' ';
|
||||
}
|
||||
fltValues.push(value);
|
||||
}
|
||||
//adds array size
|
||||
fltValues.push(tf.fltIds.length);
|
||||
|
||||
//writes cookie
|
||||
//write cookie
|
||||
Cookie.write(
|
||||
name,
|
||||
fltValues.join(tf.separator),
|
||||
|
@ -49,8 +66,8 @@ export class Store{
|
|||
* @return {Array}
|
||||
*/
|
||||
getFilterValues(name){
|
||||
var flts = Cookie.read(name);
|
||||
var rgx = new RegExp(this.tf.separator, 'g');
|
||||
let flts = Cookie.read(name);
|
||||
let rgx = new RegExp(this.tf.separator, 'g');
|
||||
// filters' values array
|
||||
return flts.split(rgx);
|
||||
}
|
||||
|
@ -60,6 +77,9 @@ export class Store{
|
|||
* @param {String} cookie name
|
||||
*/
|
||||
savePageNb(name){
|
||||
if(!this.tf.rememberPageNb){
|
||||
return;
|
||||
}
|
||||
Cookie.write(
|
||||
name,
|
||||
this.tf.feature('paging').currentPageNb,
|
||||
|
@ -81,6 +101,9 @@ export class Store{
|
|||
* @param {String} cookie name
|
||||
*/
|
||||
savePageLength(name){
|
||||
if(!this.tf.rememberPageLen){
|
||||
return;
|
||||
}
|
||||
Cookie.write(
|
||||
name,
|
||||
this.tf.feature('paging').resultsPerPageSlc.selectedIndex,
|
||||
|
@ -97,4 +120,18 @@ export class Store{
|
|||
return Cookie.read(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all cookies
|
||||
*/
|
||||
clearCookies(){
|
||||
Cookie.remove(this.tf.fltsValuesCookie);
|
||||
Cookie.remove(this.tf.pgLenCookie);
|
||||
Cookie.remove(this.tf.pgNbCookie);
|
||||
}
|
||||
|
||||
destroy(){
|
||||
this.emitter.off(['after-filtering'],
|
||||
()=> this.saveFilterValues(this.tf.fltsValuesCookie));
|
||||
this.emitter.off(['after-clearing-filters'], ()=> this.clearCookies());
|
||||
}
|
||||
}
|
||||
|
|
1208
src/tablefilter.js
1208
src/tablefilter.js
File diff suppressed because it is too large
Load diff
|
@ -36,9 +36,10 @@
|
|||
<script data-config>
|
||||
var tfConfig = {
|
||||
base_path: '../dist/tablefilter/',
|
||||
col_0: "multiple",
|
||||
col_1: "select",
|
||||
col_2: "checklist",
|
||||
btn: true,
|
||||
col_0: 'multiple',
|
||||
col_1: 'select',
|
||||
col_2: 'checklist',
|
||||
col_number_format: [
|
||||
null, null, 'US',
|
||||
'US', 'US', 'US',
|
||||
|
|
|
@ -21,6 +21,7 @@ test('Properties', function() {
|
|||
deepEqual(altRows.feature, 'alternateRows', 'Feature name');
|
||||
deepEqual(altRows.enabled, true, 'Feature enabled');
|
||||
deepEqual(altRows.initialized, true, 'Feature enabled');
|
||||
deepEqual(typeof altRows.emitter, 'object', 'Feature has emitter instance');
|
||||
deepEqual(typeof altRows.config, 'object', 'TF configuration object');
|
||||
deepEqual(typeof altRows.init, 'function', 'Feature init method');
|
||||
deepEqual(typeof altRows.destroy, 'function', 'Feature destroy method');
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
});
|
||||
|
||||
module('Behaviour');
|
||||
tf.setFilterValue(0, 'Hello');
|
||||
tf.filter();
|
||||
test('for filtered table', function() {
|
||||
tf.setFilterValue(0, 'Hello');
|
||||
tf.filter();
|
||||
var alwaysVisibleRow1 = tf.tbl.rows[4];
|
||||
var alwaysVisibleRow2 = tf.tbl.rows[9];
|
||||
deepEqual(
|
||||
|
@ -29,68 +29,8 @@
|
|||
);
|
||||
});
|
||||
|
||||
tf.clearFilters();
|
||||
test('after filters are cleared', function() {
|
||||
var alwaysVisibleRow1 = tf.tbl.rows[4];
|
||||
var alwaysVisibleRow2 = tf.tbl.rows[9];
|
||||
deepEqual(
|
||||
tf.getRowDisplay(alwaysVisibleRow1),
|
||||
'',
|
||||
'Row display for alwaysVisibleRow1'
|
||||
);
|
||||
deepEqual(
|
||||
tf.getRowDisplay(alwaysVisibleRow2),
|
||||
'',
|
||||
'Row display for alwaysVisibleRow2'
|
||||
);
|
||||
});
|
||||
|
||||
tf.destroy();
|
||||
tf = new TableFilter('demo', {
|
||||
base_path: '../dist/tablefilter/',
|
||||
rows_always_visible: [4, 9],
|
||||
paging: true,
|
||||
paging_length: 2
|
||||
});
|
||||
tf.init();
|
||||
var paging = tf.feature('paging');
|
||||
|
||||
module('Behaviour with paging');
|
||||
tf.setFilterValue(0, 'Hello');
|
||||
tf.filter();
|
||||
test('for filtered table', function() {
|
||||
var alwaysVisibleRow1 = tf.tbl.rows[4];
|
||||
var alwaysVisibleRow2 = tf.tbl.rows[9];
|
||||
deepEqual(
|
||||
tf.getRowDisplay(alwaysVisibleRow1),
|
||||
'',
|
||||
'Row display for alwaysVisibleRow1'
|
||||
);
|
||||
deepEqual(
|
||||
tf.getRowDisplay(alwaysVisibleRow2),
|
||||
'',
|
||||
'Row display for alwaysVisibleRow2'
|
||||
);
|
||||
});
|
||||
|
||||
tf.clearFilters();
|
||||
test('after filters are cleared', function() {
|
||||
var alwaysVisibleRow1 = tf.tbl.rows[4];
|
||||
var alwaysVisibleRow2 = tf.tbl.rows[9];
|
||||
deepEqual(
|
||||
tf.getRowDisplay(alwaysVisibleRow1),
|
||||
'',
|
||||
'Row display for alwaysVisibleRow1'
|
||||
);
|
||||
deepEqual(
|
||||
tf.getRowDisplay(alwaysVisibleRow2),
|
||||
'',
|
||||
'Row display for alwaysVisibleRow2'
|
||||
);
|
||||
});
|
||||
|
||||
paging.setPage(2);
|
||||
test('after changing pagination page', function() {
|
||||
tf.clearFilters();
|
||||
var alwaysVisibleRow1 = tf.tbl.rows[4];
|
||||
var alwaysVisibleRow2 = tf.tbl.rows[9];
|
||||
deepEqual(
|
||||
|
@ -104,8 +44,72 @@
|
|||
'Row display for alwaysVisibleRow2'
|
||||
);
|
||||
|
||||
paging.setPage(0);
|
||||
testPaging();
|
||||
});
|
||||
|
||||
function testPaging(){
|
||||
tf.destroy();
|
||||
});
|
||||
tf = new TableFilter('demo', {
|
||||
base_path: '../dist/tablefilter/',
|
||||
rows_always_visible: [4, 9],
|
||||
paging: true,
|
||||
paging_length: 2
|
||||
});
|
||||
tf.init();
|
||||
var paging = tf.feature('paging');
|
||||
|
||||
module('Behaviour with paging');
|
||||
test('for filtered table', function() {
|
||||
tf.setFilterValue(0, 'Hello');
|
||||
tf.filter();
|
||||
var alwaysVisibleRow1 = tf.tbl.rows[4];
|
||||
var alwaysVisibleRow2 = tf.tbl.rows[9];
|
||||
deepEqual(
|
||||
tf.getRowDisplay(alwaysVisibleRow1),
|
||||
'',
|
||||
'Row display for alwaysVisibleRow1'
|
||||
);
|
||||
deepEqual(
|
||||
tf.getRowDisplay(alwaysVisibleRow2),
|
||||
'',
|
||||
'Row display for alwaysVisibleRow2'
|
||||
);
|
||||
});
|
||||
|
||||
test('after filters are cleared', function() {
|
||||
tf.clearFilters();
|
||||
var alwaysVisibleRow1 = tf.tbl.rows[4];
|
||||
var alwaysVisibleRow2 = tf.tbl.rows[9];
|
||||
deepEqual(
|
||||
tf.getRowDisplay(alwaysVisibleRow1),
|
||||
'none',
|
||||
'Row display for alwaysVisibleRow1'
|
||||
);
|
||||
deepEqual(
|
||||
tf.getRowDisplay(alwaysVisibleRow2),
|
||||
'none',
|
||||
'Row display for alwaysVisibleRow2'
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
test('after changing pagination page', function() {
|
||||
paging.setPage(2);
|
||||
var alwaysVisibleRow1 = tf.tbl.rows[4];
|
||||
var alwaysVisibleRow2 = tf.tbl.rows[9];
|
||||
deepEqual(
|
||||
tf.getRowDisplay(alwaysVisibleRow1),
|
||||
'',
|
||||
'Row display for alwaysVisibleRow1'
|
||||
);
|
||||
deepEqual(
|
||||
tf.getRowDisplay(alwaysVisibleRow2),
|
||||
'none',
|
||||
'Row display for alwaysVisibleRow2'
|
||||
);
|
||||
|
||||
tf.destroy();
|
||||
});
|
||||
}
|
||||
|
||||
})(window, TableFilter);
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
tf.setFilterValue(0, 'Syd');
|
||||
tf.setFilterValue(1, 'Ade');
|
||||
deepEqual(tf.getFilterValue(0), 'Syd', 'Column 0 filter value');
|
||||
deepEqual(tf.getFiltersValue(), ['syd', 'ade', '', '', '']);
|
||||
deepEqual(tf.getFiltersValue(), ['Syd', 'Ade', '', '', '']);
|
||||
});
|
||||
|
||||
test('Filter table', function() {
|
||||
|
@ -65,6 +65,20 @@
|
|||
deepEqual(tf.getValidRows().length, 4, 'Filtered rows number');
|
||||
});
|
||||
|
||||
test('Filter table with range', function() {
|
||||
tf.clearFilters();
|
||||
tf.setFilterValue(2, '>1500 && <=2871');
|
||||
tf.filter();
|
||||
deepEqual(tf.getValidRows().length, 3, 'Filtered rows number');
|
||||
});
|
||||
|
||||
test('Filter table with operator', function() {
|
||||
tf.clearFilters();
|
||||
tf.setFilterValue(1, '{Bri');
|
||||
tf.filter();
|
||||
deepEqual(tf.getValidRows().length, 2, 'Filtered rows number');
|
||||
});
|
||||
|
||||
test('Clear filters', function() {
|
||||
tf.clearFilters();
|
||||
deepEqual(tf.nbVisibleRows, 7, 'Filtered rows number');
|
||||
|
@ -185,17 +199,63 @@
|
|||
tf.setFilterValue(0, 'Sydney');
|
||||
tf.setFilterValue(1, 'Adelaide');
|
||||
deepEqual(tf.getFilterValue(0), 'Sydney', 'Column 0 filter value');
|
||||
deepEqual(tf.getFiltersValue(), ['sydney', 'adelaide', '', '', '']);
|
||||
deepEqual(tf.getFiltersValue(),
|
||||
['Sydney', ['Adelaide'], '', '', '']);
|
||||
});
|
||||
|
||||
test('Filter table', function() {
|
||||
tf.clearFilters();
|
||||
tf.setFilterValue(1, 'Adelaide');
|
||||
tf.setFilterValue(1, 'Alice Springs');
|
||||
tf.filter();
|
||||
deepEqual(tf.getValidRows().length, 1, 'Filtered rows number');
|
||||
});
|
||||
|
||||
module('TableFilter with pop-up filtes');
|
||||
test('Can filter table with multiple filter', function() {
|
||||
tf.clearFilters();
|
||||
tf.setFilterValue(1, ['Alice Springs', 'Canberra']);
|
||||
tf.filter();
|
||||
deepEqual(tf.getValidRows().length, 2, 'Filtered rows number');
|
||||
});
|
||||
|
||||
test('Can filter table with checklist filter', function() {
|
||||
tf.clearFilters();
|
||||
tf.setFilterValue(2, ['2045', '2781']);
|
||||
tf.filter();
|
||||
deepEqual(tf.getValidRows().length, 2, 'Filtered rows number');
|
||||
});
|
||||
|
||||
test('Can select dropdown options with or operator', function() {
|
||||
tf.setFilterValue(1, '');
|
||||
tf.setFilterValue(1, 'Brisbane || Melbourne');
|
||||
|
||||
deepEqual(tf.getFilterValue(1), ['Brisbane', 'Melbourne'],
|
||||
'Column 2 filter values');
|
||||
});
|
||||
|
||||
test('Can select dropdown options with array', function() {
|
||||
tf.setFilterValue(1, '');
|
||||
tf.setFilterValue(1, ['Canberra', 'Perth']);
|
||||
|
||||
deepEqual(tf.getFilterValue(1), ['Canberra', 'Perth'],
|
||||
'Column 2 filter values');
|
||||
});
|
||||
|
||||
test('Can select checklist options', function() {
|
||||
tf.setFilterValue(2, '2045 || 2781');
|
||||
|
||||
deepEqual(tf.getFilterValue(2), ['2045', '2781'],
|
||||
'Column 2 filter values');
|
||||
});
|
||||
|
||||
test('Can select checklist options with array', function() {
|
||||
tf.setFilterValue(2, '');
|
||||
tf.setFilterValue(2, ['1412', '982']);
|
||||
|
||||
deepEqual(tf.getFilterValue(2), ['1412', '982'],
|
||||
'Column 2 filter values');
|
||||
});
|
||||
|
||||
module('TableFilter with pop-up filters');
|
||||
test('Sanity checks', function() {
|
||||
tf.destroy();
|
||||
tf = null;
|
||||
|
@ -217,7 +277,7 @@
|
|||
tf.setFilterValue(0, 'Sydney');
|
||||
tf.setFilterValue(1, 'Adelaide');
|
||||
deepEqual(tf.getFilterValue(0), 'Sydney', 'Column 0 filter value');
|
||||
deepEqual(tf.getFiltersValue(), ['sydney', 'adelaide', '', '', '']);
|
||||
deepEqual(tf.getFiltersValue(), ['Sydney', 'Adelaide', '', '', '']);
|
||||
});
|
||||
|
||||
test('Filter table', function() {
|
||||
|
@ -265,7 +325,7 @@
|
|||
tf.setFilterValue(0, 'Sydney');
|
||||
tf.setFilterValue(1, 'Adelaide');
|
||||
deepEqual(tf.getFilterValue(0), 'Sydney', 'Column 0 filter value');
|
||||
deepEqual(tf.getFiltersValue(), ['sydney', 'adelaide', '', '', '']);
|
||||
deepEqual(tf.getFiltersValue(), ['Sydney', ['Adelaide'], '', '', '']);
|
||||
});
|
||||
|
||||
test('Filter table', function() {
|
||||
|
|
|
@ -14,25 +14,25 @@
|
|||
module('Behaviour');
|
||||
test('After filtering with `sydney`', function() {
|
||||
tf.setFilterValue(0, 'sydney');
|
||||
tf._filter();
|
||||
tf.filter();
|
||||
deepEqual(tf.getValidRows().length, 0, 'No matches');
|
||||
});
|
||||
|
||||
test('After filtering with `Sydney`', function() {
|
||||
tf.setFilterValue(0, 'Sydney');
|
||||
tf._filter();
|
||||
tf.filter();
|
||||
deepEqual(tf.getValidRows().length>0, true, 'Matches');
|
||||
});
|
||||
|
||||
test('After filtering with `ade`', function() {
|
||||
tf.setFilterValue(0, 'ade');
|
||||
tf._filter();
|
||||
tf.filter();
|
||||
deepEqual(tf.getValidRows().length, 0, 'No matches');
|
||||
});
|
||||
|
||||
test('After filtering with `Ade`', function() {
|
||||
tf.setFilterValue(0, 'Ade');
|
||||
tf._filter();
|
||||
tf.filter();
|
||||
deepEqual(tf.getValidRows().length>0, true, 'Matches');
|
||||
});
|
||||
|
||||
|
|
|
@ -22,8 +22,30 @@ test('CheckList UI elements', function() {
|
|||
deepEqual(flt.childNodes.length, 8, 'number of checklist options');
|
||||
});
|
||||
|
||||
module('Behaviour');
|
||||
test('Can filter on checkList change', function() {
|
||||
var flt1 = id(tf.fltIds[3]);
|
||||
|
||||
var evObj = document.createEvent('HTMLEvents');
|
||||
evObj.initEvent('change', true, true);
|
||||
tf.activeFlt = flt1;
|
||||
tf.setFilterValue(3, '1.1');
|
||||
flt1.dispatchEvent(evObj);
|
||||
|
||||
deepEqual(tf.getValidRows().length, 1, 'Table filtered');
|
||||
deepEqual(tf.getFilteredData()[0][1][3], '1.1', 'Matched value');
|
||||
});
|
||||
test('Can select options', function() {
|
||||
tf.clearFilters();
|
||||
var flt1 = id(tf.fltIds[3]);
|
||||
|
||||
checkList.selectOptions(3, ['1.4', '.6']);
|
||||
|
||||
notEqual(flt1.getAttribute('value').indexOf('1.4'), -1, 'Option selected');
|
||||
notEqual(flt1.getAttribute('value').indexOf('.6'), -1, 'Option selected');
|
||||
});
|
||||
|
||||
test('TableFilter removed', function() {
|
||||
tf.destroy();
|
||||
deepEqual(id(tf.fltIds[3]), null, 'CheckList UL element');
|
||||
});
|
||||
|
||||
|
|
|
@ -19,14 +19,16 @@ test('Properties', function() {
|
|||
deepEqual(clearButton.feature, 'btnReset', 'Feature name');
|
||||
deepEqual(clearButton.enabled, true, 'Feature enabled');
|
||||
deepEqual(clearButton.initialized, true, 'Feature enabled');
|
||||
deepEqual(typeof clearButton.emitter, 'object',
|
||||
'Feature has emitter instance');
|
||||
deepEqual(typeof clearButton.config, 'object', 'TF configuration object');
|
||||
deepEqual(typeof clearButton.init, 'function', 'Feature init method');
|
||||
deepEqual(typeof clearButton.destroy, 'function', 'Feature destroy method');
|
||||
deepEqual(typeof clearButton.reset, 'function', 'Feature reset method');
|
||||
deepEqual(typeof clearButton.enable, 'function', 'Feature enable method');
|
||||
deepEqual(typeof clearButton.disable, 'function', 'Feature enable method');
|
||||
deepEqual(
|
||||
typeof clearButton.isEnabled, 'function', 'Feature enable method');
|
||||
deepEqual(typeof clearButton.isEnabled, 'function',
|
||||
'Feature enable method');
|
||||
});
|
||||
test('Can destroy', function() {
|
||||
clearButton.destroy();
|
||||
|
|
78
test/test-disable-filter-onchange.html
Normal file
78
test/test-disable-filter-onchange.html
Normal file
|
@ -0,0 +1,78 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>TableFilter disable select filter onchange event</title>
|
||||
<link rel="stylesheet" href="libs/qunit/qunit.css">
|
||||
<script src="libs/qunit/qunit.js"></script>
|
||||
<script src="libs/polyfill.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<table id="demo" cellpadding="0" cellspacing="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>From</th>
|
||||
<th>Destination</th>
|
||||
<th>Road Distance (km)</th>
|
||||
<th>By Air (hrs)</th>
|
||||
<th>By Rail (hrs)</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Sydney</strong></td>
|
||||
<td>Adelaide</td>
|
||||
<td>1412</td>
|
||||
<td>1.4</td>
|
||||
<td>25.3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Sydney</strong></td>
|
||||
<td>Brisbane</td>
|
||||
<td>982</td>
|
||||
<td>1.5</td>
|
||||
<td>16</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Sydney</strong></td>
|
||||
<td>Canberra</td>
|
||||
<td>286</td>
|
||||
<td>.6</td>
|
||||
<td>4.3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Sydney</strong></td>
|
||||
<td>Melbourne</td>
|
||||
<td>872</td>
|
||||
<td>1.1</td>
|
||||
<td>10.5</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Adelaide</strong></td>
|
||||
<td>Perth</td>
|
||||
<td>2781</td>
|
||||
<td>3.1</td>
|
||||
<td>38</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Adelaide</strong></td>
|
||||
<td>Alice Springs</td>
|
||||
<td>1533</td>
|
||||
<td>2</td>
|
||||
<td>20.25</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Adelaide</strong></td>
|
||||
<td>Brisbane</td>
|
||||
<td>2045</td>
|
||||
<td>2.15</td>
|
||||
<td>40</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<script src="../dist/tablefilter/tablefilter.js"></script>
|
||||
<script src="test-disable-filter-onchange.js"></script>
|
||||
|
||||
<div id="qunit"></div>
|
||||
<div id="qunit-fixture"></div>
|
||||
</body>
|
||||
</html>
|
40
test/test-disable-filter-onchange.js
Normal file
40
test/test-disable-filter-onchange.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
(function(win, TableFilter){
|
||||
var id = function (id){ return document.getElementById(id); };
|
||||
|
||||
var tf = new TableFilter('demo', {
|
||||
base_path: '../dist/tablefilter/',
|
||||
col_0: 'select',
|
||||
col_1: 'multiple',
|
||||
on_change: false
|
||||
});
|
||||
tf.init();
|
||||
|
||||
module('Sanity checks');
|
||||
test('Disable onchange event on select filter', function() {
|
||||
deepEqual(tf instanceof TableFilter, true, 'TableFilter type');
|
||||
deepEqual(tf.onSlcChange, false, 'Onchange event disabled');
|
||||
});
|
||||
|
||||
module('Behaviour');
|
||||
test('Cannot filter on selection change', function() {
|
||||
var flt0 = id(tf.fltIds[0]);
|
||||
var flt1 = id(tf.fltIds[1]);
|
||||
var evObj = document.createEvent('HTMLEvents');
|
||||
evObj.initEvent('change', true, true);
|
||||
|
||||
tf.setFilterValue(0, 'Sydney');
|
||||
flt0.dispatchEvent(evObj);
|
||||
tf.setFilterValue(1, 'Canberra');
|
||||
flt1.dispatchEvent(evObj);
|
||||
|
||||
deepEqual(tf.getValidRows().length, 0, 'Table not filtered');
|
||||
deepEqual(tf.nbHiddenRows, 0, 'No hidden rows');
|
||||
});
|
||||
|
||||
module('Tear-down');
|
||||
test('TableFilter removed', function() {
|
||||
tf.destroy();
|
||||
deepEqual(tf.hasGrid(), false, 'Filters removed');
|
||||
});
|
||||
|
||||
})(window, TableFilter);
|
|
@ -24,6 +24,30 @@ test('Drop-down UI elements', function() {
|
|||
deepEqual(flt2.hasAttribute('multiple'), true, 'Multiple select exists');
|
||||
});
|
||||
|
||||
module('Behaviour');
|
||||
test('Can filter on drop-down change', function() {
|
||||
var flt1 = id(tf.fltIds[3]);
|
||||
|
||||
var evObj = document.createEvent('HTMLEvents');
|
||||
evObj.initEvent('change', true, true);
|
||||
tf.activeFlt = flt1;
|
||||
tf.setFilterValue(3, '1.1');
|
||||
flt1.dispatchEvent(evObj);
|
||||
|
||||
deepEqual(tf.getValidRows().length, 1, 'Table filtered');
|
||||
deepEqual(tf.getFilteredData()[0][1][3], '1.1', 'Matched value');
|
||||
});
|
||||
|
||||
test('Can select options', function() {
|
||||
tf.clearFilters();
|
||||
var flt1 = id(tf.fltIds[2]);
|
||||
|
||||
dropdown.selectOptions(2, ['872', '286']);
|
||||
|
||||
deepEqual(flt1.options[5].selected, true, 'Option selected');
|
||||
deepEqual(flt1.options[6].selected, true, 'Option selected');
|
||||
});
|
||||
|
||||
test('TableFilter removed', function() {
|
||||
tf.destroy();
|
||||
deepEqual(id(tf.fltIds[3]), null, 'Filter is removed');
|
||||
|
|
78
test/test-emitter.html
Normal file
78
test/test-emitter.html
Normal file
|
@ -0,0 +1,78 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>TableFilter event emitter</title>
|
||||
<link rel="stylesheet" href="libs/qunit/qunit.css">
|
||||
<script src="libs/qunit/qunit.js"></script>
|
||||
<script src="libs/polyfill.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<table id="demo" cellpadding="0" cellspacing="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>From</th>
|
||||
<th>Destination</th>
|
||||
<th>Road Distance (km)</th>
|
||||
<th>By Air (hrs)</th>
|
||||
<th>By Rail (hrs)</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Sydney</strong></td>
|
||||
<td>Adelaide</td>
|
||||
<td>1412</td>
|
||||
<td>1.4</td>
|
||||
<td>25.3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Sydney</strong></td>
|
||||
<td>Brisbane</td>
|
||||
<td>982</td>
|
||||
<td>1.5</td>
|
||||
<td>16</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Sydney</strong></td>
|
||||
<td>Canberra</td>
|
||||
<td>286</td>
|
||||
<td>.6</td>
|
||||
<td>4.3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Sydney</strong></td>
|
||||
<td>Melbourne</td>
|
||||
<td>872</td>
|
||||
<td>1.1</td>
|
||||
<td>10.5</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Adelaide</strong></td>
|
||||
<td>Perth</td>
|
||||
<td>2781</td>
|
||||
<td>3.1</td>
|
||||
<td>38</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Adelaide</strong></td>
|
||||
<td>Alice Springs</td>
|
||||
<td>1533</td>
|
||||
<td>2</td>
|
||||
<td>20.25</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Adelaide</strong></td>
|
||||
<td>Brisbane</td>
|
||||
<td>2045</td>
|
||||
<td>2.15</td>
|
||||
<td>40</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<script src="../dist/tablefilter/tablefilter.js"></script>
|
||||
<script src="test-emitter.js"></script>
|
||||
|
||||
<div id="qunit"></div>
|
||||
<div id="qunit-fixture"></div>
|
||||
</body>
|
||||
</html>
|
57
test/test-emitter.js
Normal file
57
test/test-emitter.js
Normal file
|
@ -0,0 +1,57 @@
|
|||
|
||||
var tf = new TableFilter('demo', {
|
||||
base_path: '../dist/tablefilter/'
|
||||
});
|
||||
tf.init();
|
||||
|
||||
module('Sanity checks');
|
||||
test('Emitter instance', function() {
|
||||
deepEqual(typeof tf.emitter, 'object', 'Emitter instanciated');
|
||||
deepEqual(typeof tf.emitter.events, 'object', 'Emitter events property');
|
||||
deepEqual(typeof tf.emitter.on, 'function', 'Emitter on method');
|
||||
deepEqual(typeof tf.emitter.off, 'function', 'Emitter off method');
|
||||
deepEqual(typeof tf.emitter.emit, 'function', 'Emitter emit method');
|
||||
});
|
||||
|
||||
module('Behaviour');
|
||||
test('Can subscribe', function(){
|
||||
var emitter = tf.emitter;
|
||||
var output = null;
|
||||
emitter.on(['before-filtering'],
|
||||
function(){ output = 'before-filtering'; });
|
||||
|
||||
tf.filter();
|
||||
|
||||
deepEqual(emitter.events['before-filtering'].length, 1,
|
||||
'Expected number of listeners');
|
||||
deepEqual(output, 'before-filtering', 'Expected output');
|
||||
});
|
||||
|
||||
test('Can unsubscribe', function(){
|
||||
var emitter = tf.emitter;
|
||||
var output = null;
|
||||
emitter.off(['before-filtering'],
|
||||
function(){ output = 'before-filtering'; });
|
||||
|
||||
tf.filter();
|
||||
|
||||
deepEqual(emitter.events['before-filtering'].length, 0,
|
||||
'Expected number of listeners');
|
||||
deepEqual(output, null, 'Expected output');
|
||||
});
|
||||
|
||||
test('Can emit', function(){
|
||||
var emitter = tf.emitter;
|
||||
var output = null;
|
||||
emitter.on(['hello'], function(arg){ output = arg; });
|
||||
|
||||
emitter.emit('hello', 'world');
|
||||
|
||||
deepEqual(output, 'world', 'Event emitted');
|
||||
});
|
||||
|
||||
module('Tear-down');
|
||||
test('can destroy TableFilter DOM elements', function() {
|
||||
tf.destroy();
|
||||
deepEqual(tf.hasGrid(), false, 'Filters removed');
|
||||
});
|
|
@ -14,13 +14,13 @@
|
|||
module('Behaviour');
|
||||
test('After filtering with `syd`', function() {
|
||||
tf.setFilterValue(0, 'syd');
|
||||
tf._filter();
|
||||
tf.filter();
|
||||
deepEqual(tf.getValidRows().length, 0, 'No matches');
|
||||
});
|
||||
|
||||
test('After filtering with `sydney`', function() {
|
||||
tf.setFilterValue(0, 'sydney');
|
||||
tf._filter();
|
||||
tf.filter();
|
||||
deepEqual(tf.getValidRows().length>0, true, 'Matches');
|
||||
});
|
||||
|
||||
|
@ -42,14 +42,14 @@
|
|||
test('After filtering with `syd`', function() {
|
||||
tf.setFilterValue(0, 'syd');
|
||||
tf.setFilterValue(1, 'bris');
|
||||
tf._filter();
|
||||
tf.filter();
|
||||
deepEqual(tf.getValidRows().length, 0, 'No matches');
|
||||
});
|
||||
|
||||
test('After filtering with `sydney`', function() {
|
||||
tf.clearFilters();
|
||||
tf.setFilterValue(0, 'sydney');
|
||||
tf._filter();
|
||||
tf.filter();
|
||||
deepEqual(tf.getValidRows().length>0, true, 'Matches');
|
||||
});
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
|
||||
var tf = new TableFilter('demo', {
|
||||
base_path: '../dist/tablefilter/',
|
||||
grid_layout: true,
|
||||
sort: false
|
||||
grid_layout: true
|
||||
});
|
||||
tf.init();
|
||||
|
||||
|
@ -14,9 +13,13 @@ test('GridLayout component', function() {
|
|||
notEqual(gridLayout.tblCont, null, 'GridLayout main HTML table container element');
|
||||
notEqual(gridLayout.headTblCont, null, 'GridLayout headers container element');
|
||||
notEqual(gridLayout.headTbl, null, 'GridLayout headers HTML table');
|
||||
deepEqual(tf.startRow, null, 'Optional startRow row index');
|
||||
deepEqual(tf.refRow, 0, 'Reference row index');
|
||||
deepEqual(tf.headersRow, 0, 'Headers row index');
|
||||
deepEqual(tf.filtersRowIndex, 1, 'Filters row index');
|
||||
});
|
||||
|
||||
test('Destroy GridLayout component', function() {
|
||||
test('Destroy TableFilter', function() {
|
||||
gridLayout.destroy();
|
||||
deepEqual(gridLayout.tblMainCont, null, 'Main container element removed');
|
||||
deepEqual(gridLayout.tblCont, null, 'Main HTML table container element removed');
|
||||
|
@ -24,3 +27,10 @@ test('Destroy GridLayout component', function() {
|
|||
deepEqual(gridLayout.headTbl, null, 'Headers HTML table element removed');
|
||||
notEqual(gridLayout.sourceTblHtml, null, 'Table reference is kept');
|
||||
});
|
||||
|
||||
test('Reset TableFilter', function() {
|
||||
tf.destroy();
|
||||
tf.init();
|
||||
deepEqual(tf instanceof TableFilter, true, 'TableFilter type');
|
||||
deepEqual(typeof gridLayout, 'object', 'GridLayout instanciated');
|
||||
});
|
||||
|
|
|
@ -18,6 +18,7 @@ test('Properties', function() {
|
|||
deepEqual(help.feature, 'help', 'Feature name');
|
||||
deepEqual(help.enabled, true, 'Feature enabled');
|
||||
deepEqual(help.initialized, true, 'Feature enabled');
|
||||
deepEqual(typeof help.emitter, 'object', 'Feature has emitter instance');
|
||||
deepEqual(typeof help.config, 'object', 'TF configuration object');
|
||||
deepEqual(typeof help.init, 'function', 'Feature init method');
|
||||
deepEqual(typeof help.destroy, 'function', 'Feature destroy method');
|
||||
|
@ -87,6 +88,19 @@ test('Re-set UI', function() {
|
|||
notEqual(helpBtn.innerHTML.indexOf('→Help←'), -1, 'Help button text');
|
||||
});
|
||||
|
||||
|
||||
module('Destroy and re-init with help property undefined');
|
||||
test('Can init help when property is undefined and toolbar is set', function(){
|
||||
tf.destroy();
|
||||
tf.help = undefined;
|
||||
tf.rowsCounter = true;
|
||||
var help = tf.feature('help');
|
||||
help.btnText = '?';
|
||||
tf.init();
|
||||
|
||||
notEqual(help.btn, null, 'btn property');
|
||||
});
|
||||
|
||||
module('Tear-down');
|
||||
test('can destroy TableFilter DOM elements', function() {
|
||||
tf.destroy();
|
||||
|
|
|
@ -16,20 +16,34 @@ test('HighlightKeyword component', function() {
|
|||
test('Highlighted keywords', function() {
|
||||
tf.setFilterValue(1, 'Perth');
|
||||
tf.setFilterValue(3, '3.1');
|
||||
tf._filter();
|
||||
tf.filter();
|
||||
deepEqual(highlightKeyword.highlightedNodes.length,
|
||||
2, 'Number of highlighted words');
|
||||
deepEqual(tf.tbl.querySelectorAll('.keyword').length, 2,
|
||||
'Number of applied CSS classes');
|
||||
|
||||
tf._clearFilters();
|
||||
tf._filter();
|
||||
tf.clearFilters();
|
||||
deepEqual(highlightKeyword.highlightedNodes.length,
|
||||
0, 'Number of highlighted words');
|
||||
// TODO: uncomment when fixed
|
||||
// deepEqual(tf.tbl.querySelectorAll('.keyword').length, 0,
|
||||
// 'Number of applied CSS classes');
|
||||
});
|
||||
|
||||
module('Reset feature');
|
||||
test('can destroy and init TableFilter', function() {
|
||||
tf.destroy();
|
||||
tf.init();
|
||||
deepEqual(typeof highlightKeyword, 'object', 'Instanciated');
|
||||
deepEqual(highlightKeyword.highlightedNodes instanceof Array,
|
||||
true, 'Property check');
|
||||
});
|
||||
|
||||
module('Tear-down');
|
||||
test('can destroy TableFilter DOM elements', function() {
|
||||
test('can destroy TableFilter DOM elements and clean highlighted words',
|
||||
function() {
|
||||
tf.setFilterValue(1, 'Perth');
|
||||
tf._filter();
|
||||
tf.filter();
|
||||
tf.destroy();
|
||||
deepEqual(tf.hasGrid(), false, 'Filters removed');
|
||||
deepEqual(highlightKeyword.highlightedNodes.length,
|
||||
|
|
|
@ -12,14 +12,14 @@
|
|||
tf.init();
|
||||
tf.setFilterValue(0, 'Sydney');
|
||||
tf.getFilterElement(0).focus();
|
||||
tf._filter();
|
||||
tf.filter();
|
||||
|
||||
module('Sanity checks');
|
||||
test('Linked filters feature', function() {
|
||||
deepEqual(tf instanceof TableFilter, true, 'TableFilter instantiated');
|
||||
deepEqual(tf.linkedFilters, true, 'Linked filters enabled');
|
||||
|
||||
tf._clearFilters();
|
||||
tf.clearFilters();
|
||||
tf.onAfterFilter = null;
|
||||
tf.destroy();
|
||||
tf = null;
|
||||
|
@ -54,7 +54,7 @@
|
|||
tf.init();
|
||||
tf.setFilterValue(0, 'Sydney');
|
||||
tf.getFilterElement(0).focus();
|
||||
tf._filter();
|
||||
tf.filter();
|
||||
}
|
||||
|
||||
function testExcludedOptions(tf){
|
||||
|
@ -75,7 +75,7 @@
|
|||
});
|
||||
|
||||
tf.onAfterFilter = null;
|
||||
tf.clearFilters();
|
||||
setTimeout(tf.clearFilters, 0);
|
||||
}
|
||||
|
||||
// Tests for https://github.com/koalyptus/TableFilter/pull/42 issue
|
||||
|
|
|
@ -18,7 +18,7 @@ var flt3Cont = id(flt3ContId);
|
|||
|
||||
function buildChecklist(tf, colIdx){
|
||||
var checkList = tf.feature('checkList');
|
||||
checkList._build(colIdx);
|
||||
checkList.build(colIdx);
|
||||
checkList.checkListDiv[colIdx].onclick = null;
|
||||
checkList.checkListDiv[colIdx].title = '';
|
||||
}
|
||||
|
|
|
@ -63,10 +63,6 @@ test('Can show loader', function() {
|
|||
loader.show('');
|
||||
deepEqual(loader.loaderDiv.style.display, '', 'Loader is displayed');
|
||||
});
|
||||
test('Can show loader', function() {
|
||||
loader.show('');
|
||||
deepEqual(loader.loaderDiv.style.display, '', 'Loader is displayed');
|
||||
});
|
||||
|
||||
module('Tear-down');
|
||||
test('can destroy TableFilter DOM elements', function() {
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
deepEqual(tf instanceof TableFilter, true, 'TableFilter instanciated');
|
||||
deepEqual(tf.getFilterElement(0), null,
|
||||
'No filter element for column 0');
|
||||
deepEqual(tf.refRow, 1, 'Reference row index');
|
||||
});
|
||||
|
||||
test('Paging with no filters', function() {
|
||||
|
@ -25,6 +26,7 @@
|
|||
tf.init();
|
||||
deepEqual(tf.getFilterElement(4), null,
|
||||
'No filter element for column 4');
|
||||
deepEqual(tf.refRow, 1, 'Reference row index');
|
||||
});
|
||||
|
||||
test('Grid layout with no filters', function() {
|
||||
|
@ -39,6 +41,16 @@
|
|||
tf.init();
|
||||
deepEqual(tf.getFilterElement(2), null,
|
||||
'No filter element for column 2');
|
||||
deepEqual(tf.refRow, 0, 'Reference row index');
|
||||
|
||||
tf.setFilterValue(1, 'Bris');
|
||||
deepEqual(tf.getValidRows().length, 0, 'does not fail on setFilterValue');
|
||||
});
|
||||
|
||||
module('Tear-down');
|
||||
test('TableFilter removed', function() {
|
||||
tf.destroy();
|
||||
deepEqual(tf.hasGrid(), false, 'Filters removed');
|
||||
});
|
||||
|
||||
})(window, TableFilter);
|
||||
|
|
|
@ -19,6 +19,8 @@ test('No Results Feature', function() {
|
|||
deepEqual(noResults.feature, 'noResults', 'Feature name');
|
||||
deepEqual(noResults.enabled, true, 'Feature enabled');
|
||||
deepEqual(noResults.initialized, true, 'Feature initialized');
|
||||
deepEqual(typeof noResults.emitter, 'object',
|
||||
'Feature has emitter instance');
|
||||
deepEqual(typeof noResults.config, 'object', 'TF configuration object');
|
||||
deepEqual(typeof noResults.init, 'function', 'Feature init method');
|
||||
deepEqual(typeof noResults.destroy, 'function',
|
||||
|
@ -60,7 +62,7 @@ test('No Results Feature', function() {
|
|||
module('Behaviour');
|
||||
test('Can display no results message', function() {
|
||||
tf.setFilterValue(0, 'sadasd');
|
||||
tf._filter();
|
||||
tf.filter();
|
||||
deepEqual(tf.getValidRows().length, 0, 'Filtered rows number');
|
||||
deepEqual(noResults.cont.innerHTML, 'No results', 'No results message');
|
||||
deepEqual(noResults.cont.style.display, 'block',
|
||||
|
@ -105,7 +107,7 @@ test('External container sanity checks', function() {
|
|||
|
||||
test('Can display external no results message', function() {
|
||||
tfCustom.setFilterValue(0, 'sadasd');
|
||||
tfCustom._filter();
|
||||
tfCustom.filter();
|
||||
deepEqual(noResultsCustom.cont.innerHTML, '<h3>No results found</h3>',
|
||||
'No results message markup');
|
||||
deepEqual(noResultsCustom.cont.style.display, 'block',
|
||||
|
@ -145,7 +147,7 @@ test('Sanity checks', function() {
|
|||
|
||||
test('Can display no results message in grid layout', function() {
|
||||
tfGl.setFilterValue(0, 'sadasd');
|
||||
tfGl._filter();
|
||||
tfGl.filter();
|
||||
deepEqual(noResultsGl.cont.innerHTML, 'No results',
|
||||
'No results message');
|
||||
deepEqual(noResultsGl.cont.style.display, 'block',
|
||||
|
|
|
@ -23,6 +23,7 @@ test('Properties', function() {
|
|||
deepEqual(paging.feature, 'paging', 'Feature name');
|
||||
deepEqual(paging.enabled, true, 'Feature enabled');
|
||||
deepEqual(paging.initialized, true, 'Feature enabled');
|
||||
deepEqual(typeof paging.emitter, 'object', 'Feature has emitter instance');
|
||||
deepEqual(typeof paging.config, 'object', 'TF configuration object');
|
||||
deepEqual(typeof paging.init, 'function', 'Feature init method');
|
||||
deepEqual(typeof paging.destroy, 'function', 'Feature destroy method');
|
||||
|
@ -209,6 +210,15 @@ test('Set results per page', function() {
|
|||
deepEqual(paging.nbPages, 2, 'Expected number of pages');
|
||||
});
|
||||
|
||||
module('Reset feature');
|
||||
test('can destroy and init TableFilter', function() {
|
||||
tf.destroy();
|
||||
tf.init();
|
||||
notEqual(paging, null, 'Paging instanciated');
|
||||
deepEqual(paging.pagingLength, 2, 'Paging length');
|
||||
deepEqual(paging.nbPages, 4, 'Number of pages');
|
||||
});
|
||||
|
||||
module('Tear-down');
|
||||
test('can destroy TableFilter DOM elements', function() {
|
||||
tf.destroy();
|
||||
|
|
|
@ -16,6 +16,7 @@ test('Pop-up filter component', function() {
|
|||
notEqual(popupFilter, null, 'PopupFilter instanciated');
|
||||
deepEqual(popupFilter.popUpFltElms instanceof Array,
|
||||
true, 'Type of popUpFltElms property');
|
||||
deepEqual(tf.headersRow, 1, 'Headers row index');
|
||||
// issue 99: getHeadersText for pick-list filter types
|
||||
deepEqual(
|
||||
tf.getHeadersText()[2],
|
||||
|
@ -45,6 +46,32 @@ test('Pop-up filter UI elements', function() {
|
|||
deepEqual(fltIcn3, undefined, 'Filter icon does not exist for column 4');
|
||||
});
|
||||
|
||||
test('Pop-up filter state after filtering', function(){
|
||||
var fltIcn0 = popupFilter.popUpFltImgs[0];
|
||||
tf.setFilterValue(0, 'syd');
|
||||
tf.filter();
|
||||
|
||||
deepEqual(fltIcn0.src.indexOf('icn_filterActive') !== -1,
|
||||
true, 'Icon state');
|
||||
});
|
||||
|
||||
test('Pop-up filter state after clearing', function(){
|
||||
var fltIcn0 = popupFilter.popUpFltImgs[0];
|
||||
var fltIcn1 = popupFilter.popUpFltImgs[1];
|
||||
var fltIcn2 = popupFilter.popUpFltImgs[2];
|
||||
var fltIcn3 = popupFilter.popUpFltImgs[3];
|
||||
tf.clearFilters();
|
||||
|
||||
deepEqual(fltIcn0.src.indexOf('icn_filterActive') === -1,
|
||||
true, 'Icon state');
|
||||
deepEqual(fltIcn1.src.indexOf('icn_filterActive') === -1,
|
||||
true, 'Icon state');
|
||||
deepEqual(fltIcn2.src.indexOf('icn_filterActive') === -1,
|
||||
true, 'Icon state');
|
||||
deepEqual(fltIcn3.src.indexOf('icn_filterActive') === -1,
|
||||
true, 'Icon state');
|
||||
});
|
||||
|
||||
test('TableFilter removed', function() {
|
||||
tf.destroy();
|
||||
var fltIcn1 = popupFilter.popUpFltImgs[3];
|
||||
|
@ -76,6 +103,7 @@ test('Re-instantiated with grid-layout', function() {
|
|||
notEqual(popupFilter, null, 'PopupFilter instanciated');
|
||||
deepEqual(popupFilter.popUpFltElms instanceof Array,
|
||||
true, 'Type of popUpFltElms property');
|
||||
deepEqual(tf.headersRow, 0, 'Headers row index');
|
||||
// issue 99: getHeadersText for pick-list filter types
|
||||
deepEqual(
|
||||
tf.getHeadersText()[2],
|
||||
|
@ -105,6 +133,34 @@ test('Pop-up filter UI elements with grid-layout', function() {
|
|||
deepEqual(fltIcn3, undefined, 'Filter icon does not exist for column 4');
|
||||
});
|
||||
|
||||
test('Pop-up filter state after filtering', function(){
|
||||
var popupFilter = tf.feature('popupFilter');
|
||||
var fltIcn0 = popupFilter.popUpFltImgs[0];
|
||||
tf.setFilterValue(0, 'syd');
|
||||
tf.filter();
|
||||
|
||||
deepEqual(fltIcn0.src.indexOf('icn_filterActive') !== -1,
|
||||
true, 'Icon state');
|
||||
});
|
||||
|
||||
test('Pop-up filter state after clearing', function(){
|
||||
var popupFilter = tf.feature('popupFilter');
|
||||
var fltIcn0 = popupFilter.popUpFltImgs[0];
|
||||
var fltIcn1 = popupFilter.popUpFltImgs[1];
|
||||
var fltIcn2 = popupFilter.popUpFltImgs[2];
|
||||
var fltIcn3 = popupFilter.popUpFltImgs[3];
|
||||
tf.clearFilters();
|
||||
|
||||
deepEqual(fltIcn0.src.indexOf('icn_filterActive') === -1,
|
||||
true, 'Icon state');
|
||||
deepEqual(fltIcn1.src.indexOf('icn_filterActive') === -1,
|
||||
true, 'Icon state');
|
||||
deepEqual(fltIcn2.src.indexOf('icn_filterActive') === -1,
|
||||
true, 'Icon state');
|
||||
deepEqual(fltIcn3.src.indexOf('icn_filterActive') === -1,
|
||||
true, 'Icon state');
|
||||
});
|
||||
|
||||
module('Feature interface');
|
||||
test('Properties', function() {
|
||||
var popupFilter = tf.feature('popupFilter');
|
||||
|
@ -114,6 +170,8 @@ test('Properties', function() {
|
|||
deepEqual(popupFilter.feature, 'popupFilters', 'Feature name');
|
||||
deepEqual(popupFilter.enabled, true, 'Feature enabled');
|
||||
deepEqual(popupFilter.initialized, true, 'Feature enabled');
|
||||
deepEqual(typeof popupFilter.emitter, 'object',
|
||||
'Feature has emitter instance');
|
||||
deepEqual(typeof popupFilter.config, 'object', 'TF configuration object');
|
||||
deepEqual(typeof popupFilter.init, 'function', 'Feature init method');
|
||||
deepEqual(typeof popupFilter.destroy, 'function', 'Feature destroy method');
|
||||
|
|
|
@ -18,6 +18,8 @@ test('Properties', function() {
|
|||
deepEqual(rowsCounter.feature, 'rowsCounter', 'Feature name');
|
||||
deepEqual(rowsCounter.enabled, true, 'Feature enabled');
|
||||
deepEqual(rowsCounter.initialized, true, 'Feature enabled');
|
||||
deepEqual(typeof rowsCounter.emitter, 'object',
|
||||
'Feature has emitter instance');
|
||||
deepEqual(typeof rowsCounter.config, 'object', 'TF configuration object');
|
||||
deepEqual(typeof rowsCounter.init, 'function', 'Feature init method');
|
||||
deepEqual(typeof rowsCounter.destroy, 'function', 'Feature destroy method');
|
||||
|
|
|
@ -18,6 +18,8 @@ test('Properties', function() {
|
|||
deepEqual(statusBar.feature, 'statusBar', 'Feature name');
|
||||
deepEqual(statusBar.enabled, true, 'Feature enabled');
|
||||
deepEqual(statusBar.initialized, true, 'Feature enabled');
|
||||
deepEqual(typeof statusBar.emitter, 'object',
|
||||
'Feature has emitter instance');
|
||||
deepEqual(typeof statusBar.config, 'object', 'TF configuration object');
|
||||
deepEqual(typeof statusBar.init, 'function', 'Feature init method');
|
||||
deepEqual(typeof statusBar.destroy, 'function', 'Feature destroy method');
|
||||
|
|
|
@ -9,6 +9,24 @@ function removeCookie(name){
|
|||
document.cookie = name + '=' + expire;
|
||||
}
|
||||
|
||||
function readCookie(name){
|
||||
var cookieValue = '',
|
||||
search = name + '=';
|
||||
if(document.cookie.length > 0){
|
||||
var cookie = document.cookie,
|
||||
offset = cookie.indexOf(search);
|
||||
if(offset !== -1){
|
||||
offset += search.length;
|
||||
var end = cookie.indexOf(';', offset);
|
||||
if(end === -1){
|
||||
end = cookie.length;
|
||||
}
|
||||
cookieValue = unescape(cookie.substring(offset, end));
|
||||
}
|
||||
}
|
||||
return cookieValue;
|
||||
}
|
||||
|
||||
var tf = new TableFilter('demo', {
|
||||
base_path: '../dist/tablefilter/',
|
||||
paging: true,
|
||||
|
@ -42,7 +60,6 @@ test('Page number value', function() {
|
|||
var cookieName = tf.pgNbCookie;
|
||||
deepEqual(tf.feature('store').getPageNb(cookieName), '2', 'Page number value');
|
||||
tf.clearFilters();
|
||||
tf.filter();
|
||||
});
|
||||
|
||||
module('Check page length persistence');
|
||||
|
@ -53,21 +70,86 @@ test('Page length value', function() {
|
|||
var cookieName = tf.pgLenCookie;
|
||||
deepEqual(tf.feature('store').getPageLength(cookieName), '2', 'Page length value');
|
||||
tf.clearFilters();
|
||||
tf.filter();
|
||||
});
|
||||
|
||||
module('Check filters persistence');
|
||||
test('Filters value', function() {
|
||||
test('Filters value in cookie', function() {
|
||||
tf.setFilterValue(0, 'Sydney');
|
||||
tf.setFilterValue(3, '1.5');
|
||||
tf.filter();
|
||||
var cookieName = tf.fltsValuesCookie;
|
||||
deepEqual(tf.feature('store').getFilterValues(cookieName)[0], 'Sydney', 'Filter 0 value');
|
||||
deepEqual(tf.feature('store').getFilterValues(cookieName)[3], '1.5', 'Filter 3 value');
|
||||
tf.destroy();
|
||||
});
|
||||
|
||||
test('Filters value in cookie', function() {
|
||||
tf.setFilterValue(0, 'Sydney');
|
||||
tf.setFilterValue(3, '1.5');
|
||||
tf.filter();
|
||||
var cookieName = tf.fltsValuesCookie;
|
||||
deepEqual(tf.feature('store').getFilterValues(cookieName)[0], 'Sydney', 'Filter 0 value');
|
||||
deepEqual(tf.feature('store').getFilterValues(cookieName)[3], '1.5', 'Filter 3 value');
|
||||
});
|
||||
|
||||
test('Filters value with operators in cookie', function() {
|
||||
tf.setFilterValue(0, '');
|
||||
tf.setFilterValue(1, 'Canberra || Perth');
|
||||
tf.setFilterValue(3, '>.6');
|
||||
tf.filter();
|
||||
var cookieName = tf.fltsValuesCookie;
|
||||
|
||||
deepEqual(tf.feature('store').getFilterValues(cookieName)[0], ' ', 'Filter 0 value');
|
||||
deepEqual(tf.feature('store').getFilterValues(cookieName)[1], 'Canberra || Perth', 'Filter 1 value');
|
||||
deepEqual(tf.feature('store').getFilterValues(cookieName)[3], '>.6', 'Filter 3 value');
|
||||
deepEqual(tf.getValidRows().length, 1, 'Expected nb of filtered rows');
|
||||
});
|
||||
|
||||
test('Apply cookie filters value', function() {
|
||||
tf.setFilterValue(0, 'Adelaide');
|
||||
tf.setFilterValue(3, '>=2');
|
||||
tf.filter();
|
||||
tf.destroy();
|
||||
tf.init();
|
||||
|
||||
deepEqual(tf.getFilterValue(0), 'Adelaide', 'Applied filter value');
|
||||
deepEqual(tf.getFilterValue(3), '>=2', 'Applied filter value');
|
||||
});
|
||||
|
||||
test('Can remove cookies on clearFilters', function() {
|
||||
tf.clearFilters();
|
||||
|
||||
deepEqual(readCookie(tf.fltsValuesCookie), '',
|
||||
'fltsValuesCookie cookie removed');
|
||||
deepEqual(readCookie(tf.pgLenCookie), '', 'pgLenCookie cookie removed');
|
||||
deepEqual(readCookie(tf.pgNbCookie), '', 'pgNbCookie cookie removed');
|
||||
});
|
||||
|
||||
module('Multiple and checklist filters persistence');
|
||||
test('Filters value in cookie', function() {
|
||||
tf.destroy();
|
||||
tf = new TableFilter('demo', {
|
||||
base_path: '../dist/tablefilter/',
|
||||
remember_grid_values: true,
|
||||
col_0: 'multiple',
|
||||
col_1: 'checklist'
|
||||
});
|
||||
tf.init();
|
||||
|
||||
tf.setFilterValue(0, ['Sydney', 'Adelaide']);
|
||||
tf.setFilterValue(1, ['Alice Springs', 'Brisbane']);
|
||||
tf.filter();
|
||||
var cookieName = tf.fltsValuesCookie;
|
||||
deepEqual(tf.feature('store').getFilterValues(cookieName)[0], 'Adelaide || Sydney', 'Filter 0 value');
|
||||
deepEqual(tf.feature('store').getFilterValues(cookieName)[1], 'Alice Springs || Brisbane', 'Filter 1 value');
|
||||
deepEqual(tf.getValidRows().length, 3, 'Expected nb of filtered rows');
|
||||
});
|
||||
|
||||
module('Tear-down');
|
||||
test('TableFilter removed', function() {
|
||||
tf.destroy();
|
||||
removeCookie(tf.fltsValuesCookie);
|
||||
removeCookie(tf.pgNbCookie);
|
||||
removeCookie(tf.pgLenCookie);
|
||||
});
|
||||
|
||||
deepEqual(tf.hasGrid(), false, 'Filters removed');
|
||||
});
|
||||
|
|
80
test/test-watermark.html
Normal file
80
test/test-watermark.html
Normal file
|
@ -0,0 +1,80 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>TableFilter watermark tests</title>
|
||||
<link rel="stylesheet" href="libs/qunit/qunit.css">
|
||||
<script src="libs/qunit/qunit.js"></script>
|
||||
<script src="libs/polyfill.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<table id="demo">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>From</th>
|
||||
<th>Destination</th>
|
||||
<th>Road Distance (km)</th>
|
||||
<th>By Air (hrs)</th>
|
||||
<th>By Rail (hrs)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><strong>Sydney</strong></td>
|
||||
<td>Adelaide</td>
|
||||
<td>1412</td>
|
||||
<td>1.4</td>
|
||||
<td>25.3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Sydney</strong></td>
|
||||
<td>Brisbane</td>
|
||||
<td>982</td>
|
||||
<td>1.5</td>
|
||||
<td>16</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Sydney</strong></td>
|
||||
<td>Canberra</td>
|
||||
<td>286</td>
|
||||
<td>.6</td>
|
||||
<td>4.3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Sydney</strong></td>
|
||||
<td>Melbourne</td>
|
||||
<td>872</td>
|
||||
<td>1.1</td>
|
||||
<td>10.5</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Adelaide</strong></td>
|
||||
<td>Perth</td>
|
||||
<td>2781</td>
|
||||
<td>3.1</td>
|
||||
<td>38</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Adelaide</strong></td>
|
||||
<td>Alice Springs</td>
|
||||
<td>1533</td>
|
||||
<td>2</td>
|
||||
<td>20.25</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Adelaide</strong></td>
|
||||
<td>Brisbane</td>
|
||||
<td>2045</td>
|
||||
<td>2.15</td>
|
||||
<td>40</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<script src="../dist/tablefilter/tablefilter.js"></script>
|
||||
<script src="test-watermark.js"></script>
|
||||
|
||||
<div id="qunit"></div>
|
||||
<div id="qunit-fixture"></div>
|
||||
</body>
|
||||
</html>
|
81
test/test-watermark.js
Normal file
81
test/test-watermark.js
Normal file
|
@ -0,0 +1,81 @@
|
|||
(function(win, TableFilter){
|
||||
|
||||
var tf = new TableFilter('demo', {
|
||||
base_path: '../dist/tablefilter/',
|
||||
watermark: 'foobar'
|
||||
});
|
||||
tf.init();
|
||||
|
||||
module('Sanity checks');
|
||||
test('Watermark properties', function() {
|
||||
deepEqual(tf instanceof TableFilter, true, 'TableFilter instanciated');
|
||||
deepEqual(tf.watermark, 'foobar', 'Property value');
|
||||
deepEqual(tf.isWatermarkArray, false,
|
||||
'Type: same watermark for all filters');
|
||||
});
|
||||
|
||||
test('DOM element', function(){
|
||||
var flt0 = tf.getFilterElement(0);
|
||||
var flt1 = tf.getFilterElement(3);
|
||||
deepEqual(flt0.placeholder, 'foobar', 'filter`s placeholder value');
|
||||
deepEqual(flt1.placeholder, 'foobar', 'filter`s placeholder value');
|
||||
});
|
||||
|
||||
module('Per column watermark');
|
||||
test('Sanity checks', function() {
|
||||
tf.destroy();
|
||||
tf = new TableFilter('demo', {
|
||||
base_path: '../dist/tablefilter/',
|
||||
watermark: ['City', 'City', 'Distance', 'Time', 'Time']
|
||||
});
|
||||
tf.init();
|
||||
|
||||
deepEqual(tf instanceof TableFilter, true, 'TableFilter instanciated');
|
||||
deepEqual(tf.isWatermarkArray, true, 'Type: watermark array');
|
||||
deepEqual(
|
||||
tf.watermark,
|
||||
['City', 'City', 'Distance', 'Time', 'Time'],
|
||||
'Property value'
|
||||
);
|
||||
});
|
||||
|
||||
test('DOM element', function(){
|
||||
deepEqual(
|
||||
tf.getFilterElement(0).placeholder,
|
||||
'City',
|
||||
'filter`s placeholder value'
|
||||
);
|
||||
deepEqual(
|
||||
tf.getFilterElement(1).placeholder,
|
||||
'City',
|
||||
'filter`s placeholder value'
|
||||
);
|
||||
deepEqual(
|
||||
tf.getFilterElement(2).placeholder,
|
||||
'Distance',
|
||||
'filter`s placeholder value'
|
||||
);
|
||||
deepEqual(
|
||||
tf.getFilterElement(3).placeholder,
|
||||
'Time',
|
||||
'filter`s placeholder value'
|
||||
);
|
||||
deepEqual(
|
||||
tf.getFilterElement(4).placeholder,
|
||||
'Time',
|
||||
'filter`s placeholder value'
|
||||
);
|
||||
});
|
||||
|
||||
module('Tear-down');
|
||||
test('TableFilter removed', function() {
|
||||
tf.destroy();
|
||||
deepEqual(tf.hasGrid(), false, 'Filters removed');
|
||||
deepEqual(
|
||||
tf.watermark,
|
||||
['City', 'City', 'Distance', 'Time', 'Time'],
|
||||
'Property value'
|
||||
);
|
||||
});
|
||||
|
||||
})(window, TableFilter);
|
Loading…
Reference in a new issue