mirror of
https://github.com/koalyptus/TableFilter.git
synced 2024-05-23 08:42:18 +02:00
Added highlight keyword feature + associated tests
This commit is contained in:
parent
06ffffaada
commit
0f4d81b9a5
2
dist/filtergrid.css
vendored
2
dist/filtergrid.css
vendored
|
@ -1,6 +1,6 @@
|
|||
/*------------------------------------------------------------------------
|
||||
- TableFilter stylesheet by Max Guglielmi
|
||||
- (build date: Fri Dec 05 2014 11:24:29)
|
||||
- (build date: Sat Dec 13 2014 20:02:51)
|
||||
- Edit below for your projects' needs
|
||||
------------------------------------------------------------------------*/
|
||||
|
||||
|
|
108
src-es6/modules/highlightKeywords.js
Normal file
108
src-es6/modules/highlightKeywords.js
Normal file
|
@ -0,0 +1,108 @@
|
|||
import {Dom} from '../dom';
|
||||
import {Str} from '../string';
|
||||
|
||||
export class HighlightKeyword{
|
||||
|
||||
/**
|
||||
* HighlightKeyword, highlight matched keyword
|
||||
* @param {Object} tf TableFilter instance
|
||||
*/
|
||||
constructor(tf) {
|
||||
var f = tf.fObj;
|
||||
//defines css class for highlighting
|
||||
this.highlightCssClass = f.highlight_css_class || 'keyword';
|
||||
this.highlightedNodes = [];
|
||||
|
||||
this.tf = tf;
|
||||
}
|
||||
|
||||
/**
|
||||
* highlight occurences of searched term in passed node
|
||||
* @param {Node} node
|
||||
* @param {String} word Searched term
|
||||
* @param {String} cssClass Css class name
|
||||
*/
|
||||
highlight(node, word, cssClass){
|
||||
// Iterate into this nodes childNodes
|
||||
if(node.hasChildNodes){
|
||||
var children = node.childNodes;
|
||||
for(var i=0; i<children.length; i++){
|
||||
this.highlight(children[i], word, cssClass);
|
||||
}
|
||||
}
|
||||
|
||||
if(node.nodeType === 3){
|
||||
var tempNodeVal = Str.lower(node.nodeValue);
|
||||
var tempWordVal = Str.lower(word);
|
||||
if(tempNodeVal.indexOf(tempWordVal) != -1){
|
||||
var pn = node.parentNode;
|
||||
if(pn && pn.className != cssClass){
|
||||
// word not highlighted yet
|
||||
var nv = node.nodeValue,
|
||||
ni = tempNodeVal.indexOf(tempWordVal),
|
||||
// Create a load of replacement nodes
|
||||
before = Dom.text(nv.substr(0, ni)),
|
||||
docWordVal = nv.substr(ni,word.length),
|
||||
after = Dom.text(nv.substr(ni+word.length)),
|
||||
hiwordtext = Dom.text(docWordVal),
|
||||
hiword = Dom.create('span');
|
||||
hiword.className = cssClass;
|
||||
hiword.appendChild(hiwordtext);
|
||||
pn.insertBefore(before,node);
|
||||
pn.insertBefore(hiword,node);
|
||||
pn.insertBefore(after,node);
|
||||
pn.removeChild(node);
|
||||
this.highlightedNodes.push(hiword.firstChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes highlight to nodes matching passed string
|
||||
* @param {String} word
|
||||
* @param {String} cssClass Css class to remove
|
||||
*/
|
||||
unhighlight(word, cssClass){
|
||||
var arrRemove = [];
|
||||
var highlightedNodes = this.highlightedNodes;
|
||||
for(var i=0; i<highlightedNodes.length; i++){
|
||||
var n = highlightedNodes[i];
|
||||
if(!n){
|
||||
continue;
|
||||
}
|
||||
var tempNodeVal = Str.lower(n.nodeValue),
|
||||
tempWordVal = Str.lower(word);
|
||||
if(tempNodeVal.indexOf(tempWordVal) !== -1){
|
||||
var pn = n.parentNode;
|
||||
if(pn && pn.className === cssClass){
|
||||
var prevSib = pn.previousSibling,
|
||||
nextSib = pn.nextSibling;
|
||||
if(!prevSib || !nextSib){ continue; }
|
||||
nextSib.nodeValue = prevSib.nodeValue + n.nodeValue +
|
||||
nextSib.nodeValue;
|
||||
prevSib.nodeValue = '';
|
||||
n.nodeValue = '';
|
||||
arrRemove.push(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
for(var k=0; k<arrRemove.length; k++){
|
||||
highlightedNodes.splice(arrRemove[k], 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all occurrences of highlighted nodes
|
||||
*/
|
||||
unhighlightAll(){
|
||||
if(!this.tf.highlightKeywords || !this.tf.searchArgs){
|
||||
return;
|
||||
}
|
||||
for(var y=0; y<this.tf.searchArgs.length; y++){
|
||||
this.unhighlight(
|
||||
this.tf.searchArgs[y], this.highlightCssClass);
|
||||
}
|
||||
this.highlightedNodes = [];
|
||||
}
|
||||
}
|
139
src/core.js
139
src/core.js
|
@ -486,9 +486,9 @@ function TableFilter(id) {
|
|||
/*** keyword highlighting ***/
|
||||
//enables/disables keyword highlighting
|
||||
this.highlightKeywords = f.highlight_keywords===true ? true : false;
|
||||
//defines css class for highlighting
|
||||
this.highlightCssClass = f.highlight_css_class || 'keyword';
|
||||
this.highlightedNodes = [];
|
||||
// //defines css class for highlighting
|
||||
// this.highlightCssClass = f.highlight_css_class || 'keyword';
|
||||
// this.highlightedNodes = [];
|
||||
|
||||
/*** data types ***/
|
||||
//defines default date type (european DMY)
|
||||
|
@ -648,9 +648,6 @@ function TableFilter(id) {
|
|||
true : false;
|
||||
//cookie storing page length
|
||||
this.pgLenCookie = this.prfxCookiePageLen + this.id;
|
||||
//cookie duration
|
||||
// this.cookieDuration = !isNaN(f.set_cookie_duration) ?
|
||||
// parseInt(f.set_cookie_duration, 10) :100000;
|
||||
|
||||
/*** extensions ***/
|
||||
//imports external script
|
||||
|
@ -673,8 +670,9 @@ function TableFilter(id) {
|
|||
alternateRows: null,
|
||||
colOps: null,
|
||||
rowsCounter: null,
|
||||
GridLayout: null,
|
||||
Store: null
|
||||
gridLayout: null,
|
||||
store: null,
|
||||
highlightKeywords: null
|
||||
};
|
||||
|
||||
/*** TF events ***/
|
||||
|
@ -947,7 +945,7 @@ TableFilter.prototype = {
|
|||
if(this.rememberGridValues || this.rememberPageNb ||
|
||||
this.rememberPageLen){
|
||||
var Store = require('modules/store').Store;
|
||||
this.Cpt.Store = new Store(this);
|
||||
this.Cpt.store = new Store(this);
|
||||
}
|
||||
|
||||
if(this.gridLayout){
|
||||
|
@ -961,6 +959,12 @@ TableFilter.prototype = {
|
|||
this.Cpt.loader = new Loader(this);
|
||||
}
|
||||
|
||||
if(this.highlightKeywords){
|
||||
var Highlight =
|
||||
require('modules/highlightKeywords').HighlightKeyword;
|
||||
this.Cpt.highlightKeyword = new Highlight(this);
|
||||
}
|
||||
|
||||
if(this.popUpFilters){
|
||||
if(!this.isFirstLoad && !this.gridLayout){
|
||||
this.headersRow--;
|
||||
|
@ -1171,7 +1175,7 @@ TableFilter.prototype = {
|
|||
inp.onblur = this.Evt._OnInpBlur;
|
||||
|
||||
if(this.rememberGridValues){
|
||||
var flts_values = this.Cpt.Store.getFilterValues(
|
||||
var flts_values = this.Cpt.store.getFilterValues(
|
||||
this.fltsValuesCookie);
|
||||
if(flts_values[i]!=' '){
|
||||
this.SetFilterValue(i,flts_values[i],false);
|
||||
|
@ -1539,7 +1543,8 @@ TableFilter.prototype = {
|
|||
this.RemoveTopDiv();
|
||||
}
|
||||
if(this.highlightKeywords){
|
||||
this.UnhighlightAll();
|
||||
// this.UnhighlightAll();
|
||||
this.Cpt.highlightKeyword.unhighlightAll();
|
||||
}
|
||||
if(this.sort){
|
||||
this.RemoveSort();
|
||||
|
@ -2823,7 +2828,7 @@ TableFilter.prototype = {
|
|||
}
|
||||
|
||||
if(this.rememberPageNb){
|
||||
this.Cpt.Store.savePageNb(this.pgNbCookie);
|
||||
this.Cpt.store.savePageNb(this.pgNbCookie);
|
||||
}
|
||||
this.startPagingRow = (this.pageSelectorType===this.fltTypeSlc) ?
|
||||
this.pagingSlc.value : (index*this.pagingLength);
|
||||
|
@ -2865,7 +2870,7 @@ TableFilter.prototype = {
|
|||
this.pagingSlc.options[slcIndex].selected = true;
|
||||
}
|
||||
if(this.rememberPageLen){
|
||||
this.Cpt.Store.savePageLength(this.pgLenCookie);
|
||||
this.Cpt.store.savePageLength(this.pgLenCookie);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2879,7 +2884,7 @@ TableFilter.prototype = {
|
|||
- name: cookie name (string)
|
||||
===============================================*/
|
||||
_ResetPage: function(name){
|
||||
var pgnb = this.Cpt.Store.getPageNb(name);
|
||||
var pgnb = this.Cpt.store.getPageNb(name);
|
||||
if(pgnb!==''){
|
||||
this.ChangePage((pgnb-1));
|
||||
}
|
||||
|
@ -2897,7 +2902,7 @@ TableFilter.prototype = {
|
|||
if(!this.paging){
|
||||
return;
|
||||
}
|
||||
var pglenIndex = this.Cpt.Store.getPageLength(name);
|
||||
var pglenIndex = this.Cpt.store.getPageLength(name);
|
||||
|
||||
if(pglenIndex!==''){
|
||||
this.resultsPerPageSlc.options[pglenIndex].selected = true;
|
||||
|
@ -2966,7 +2971,7 @@ TableFilter.prototype = {
|
|||
if(this.rememberGridValues){
|
||||
// flts_values = cookie.valueToArray(
|
||||
// this.fltsValuesCookie, this.separator);
|
||||
flts_values = this.Cpt.Store.getFilterValues(this.fltsValuesCookie);
|
||||
flts_values = this.Cpt.store.getFilterValues(this.fltsValuesCookie);
|
||||
if(flts_values && !str.isEmpty(flts_values.toString())){
|
||||
if(isCustomSlc){
|
||||
fltArr.push(flts_values[colIndex]);
|
||||
|
@ -4059,7 +4064,7 @@ TableFilter.prototype = {
|
|||
if(!this.fillSlcOnDemand){
|
||||
return;
|
||||
}
|
||||
var flts_values = this.Cpt.Store.getFilterValues(name),
|
||||
var flts_values = this.Cpt.store.getFilterValues(name),
|
||||
slcFltsIndex = this.GetFiltersByType(this.fltTypeSlc, true),
|
||||
multiFltsIndex = this.GetFiltersByType(this.fltTypeMulti, true);
|
||||
|
||||
|
@ -4282,7 +4287,8 @@ TableFilter.prototype = {
|
|||
|
||||
// removes keyword highlighting
|
||||
if(this.highlightKeywords){
|
||||
this.UnhighlightAll();
|
||||
// this.UnhighlightAll();
|
||||
this.Cpt.highlightKeyword.unhighlightAll();
|
||||
}
|
||||
//removes popup filters active icons
|
||||
if(this.popUpFilters){
|
||||
|
@ -4324,7 +4330,8 @@ TableFilter.prototype = {
|
|||
w = dom.getText(cell);
|
||||
}
|
||||
if(w!==''){
|
||||
o.HighlightWord(cell,w,o.highlightCssClass);
|
||||
o.Cpt.highlightKeyword.highlight(
|
||||
cell, w, o.Cpt.highlightKeyword.highlightCssClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4624,7 +4631,7 @@ TableFilter.prototype = {
|
|||
|
||||
if(this.rememberGridValues){
|
||||
// this.RememberFiltersValue(this.fltsValuesCookie);
|
||||
this.Cpt.Store.saveFilterValues(this.fltsValuesCookie);
|
||||
this.Cpt.store.saveFilterValues(this.fltsValuesCookie);
|
||||
}
|
||||
//applies filter props after filtering process
|
||||
if(!this.paging){
|
||||
|
@ -5242,98 +5249,6 @@ TableFilter.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/*====================================================
|
||||
- removes keyword highlighting
|
||||
=====================================================*/
|
||||
UnhighlightAll: function(){
|
||||
if( this.highlightKeywords && this.searchArgs){
|
||||
for(var y=0; y<this.searchArgs.length; y++){
|
||||
this.UnhighlightWord(
|
||||
this.searchArgs[y], this.highlightCssClass);
|
||||
}
|
||||
this.highlightedNodes = [];
|
||||
}
|
||||
},
|
||||
|
||||
/*====================================================
|
||||
- highlights keyword found in passed node
|
||||
- accepts the following params:
|
||||
- node
|
||||
- word to search
|
||||
- css class name for highlighting
|
||||
=====================================================*/
|
||||
HighlightWord: function(node, word, cssClass){
|
||||
// Iterate into this nodes childNodes
|
||||
if(node.hasChildNodes){
|
||||
for(var i=0; i<node.childNodes.length; i++){
|
||||
this.HighlightWord(node.childNodes[i], word, cssClass);
|
||||
}
|
||||
}
|
||||
|
||||
// And do this node itself
|
||||
// text node
|
||||
if(node.nodeType === 3){
|
||||
var tempNodeVal = str.lower(node.nodeValue);
|
||||
var tempWordVal = str.lower(word);
|
||||
if(tempNodeVal.indexOf(tempWordVal) != -1){
|
||||
var pn = node.parentNode;
|
||||
if(pn && pn.className != cssClass){
|
||||
// word has not already been highlighted!
|
||||
var nv = node.nodeValue,
|
||||
ni = tempNodeVal.indexOf(tempWordVal),
|
||||
// Create a load of replacement nodes
|
||||
before = dom.text(nv.substr(0,ni)),
|
||||
docWordVal = nv.substr(ni,word.length),
|
||||
after = dom.text(nv.substr(ni+word.length)),
|
||||
hiwordtext = dom.text(docWordVal),
|
||||
hiword = dom.create('span');
|
||||
hiword.className = cssClass;
|
||||
hiword.appendChild(hiwordtext);
|
||||
pn.insertBefore(before,node);
|
||||
pn.insertBefore(hiword,node);
|
||||
pn.insertBefore(after,node);
|
||||
pn.removeChild(node);
|
||||
this.highlightedNodes.push(hiword.firstChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/*====================================================
|
||||
- removes highlights found in passed node
|
||||
- accepts the following params:
|
||||
- node
|
||||
- word to search
|
||||
- css class name for highlighting
|
||||
=====================================================*/
|
||||
UnhighlightWord: function(word, cssClass){
|
||||
var arrRemove = [];
|
||||
for(var i=0; i<this.highlightedNodes.length; i++){
|
||||
var n = this.highlightedNodes[i];
|
||||
if(!n){
|
||||
continue;
|
||||
}
|
||||
var tempNodeVal = str.lower(n.nodeValue),
|
||||
tempWordVal = str.lower(word);
|
||||
if(tempNodeVal.indexOf(tempWordVal) !== -1){
|
||||
var pn = n.parentNode;
|
||||
if(pn && pn.className === cssClass){
|
||||
var prevSib = pn.previousSibling,
|
||||
nextSib = pn.nextSibling;
|
||||
if(!prevSib || !nextSib){ continue; }
|
||||
nextSib.nodeValue = prevSib.nodeValue + n.nodeValue +
|
||||
nextSib.nodeValue;
|
||||
prevSib.nodeValue = '';
|
||||
n.nodeValue = '';
|
||||
arrRemove.push(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
for(var k=0; k<arrRemove.length; k++){
|
||||
this.highlightedNodes.splice(arrRemove[k], 1);
|
||||
}
|
||||
},
|
||||
|
||||
/*====================================================
|
||||
- Private methods
|
||||
=====================================================*/
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
|
||||
return require('core');
|
||||
|
||||
});
|
|
@ -77,12 +77,12 @@
|
|||
loader: false,
|
||||
rows_counter: true,
|
||||
enable_default_theme: true,
|
||||
paging: true,
|
||||
paging_length: 2,
|
||||
results_per_page: ['Results per page', [2,4,6]],
|
||||
remember_grid_values: true,
|
||||
remember_page_number: true,
|
||||
remember_page_length: true,
|
||||
// paging: true,
|
||||
// paging_length: 2,
|
||||
// results_per_page: ['Results per page', [2,4,6]],
|
||||
// remember_grid_values: true,
|
||||
// remember_page_number: true,
|
||||
// remember_page_length: true,
|
||||
alternate_rows: true,
|
||||
highlight_keywords: true,
|
||||
match_case: false,
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
module.exports = factory;
|
||||
} else {
|
||||
root.TableFilter = factory();
|
||||
}
|
||||
})(this, function() {
|
|
@ -9,22 +9,23 @@ requirejs(['test-config', '../src/core'], function(config, TableFilter){
|
|||
});
|
||||
tf.init();
|
||||
|
||||
var gridLayout = tf.Cpt.gridLayout;
|
||||
module('Sanity checks');
|
||||
test('GridLayout component', function() {
|
||||
deepEqual(tf.Cpt.gridLayout instanceof GridLayout, true, 'GridLayout type');
|
||||
notEqual(tf.Cpt.gridLayout, null, 'GridLayout instanciated');
|
||||
notEqual(tf.Cpt.gridLayout.tblMainCont, null, 'GridLayout main container element');
|
||||
notEqual(tf.Cpt.gridLayout.tblCont, null, 'GridLayout main HTML table container element');
|
||||
notEqual(tf.Cpt.gridLayout.headTblCont, null, 'GridLayout headers container element');
|
||||
notEqual(tf.Cpt.gridLayout.headTbl, null, 'GridLayout headers HTML table');
|
||||
deepEqual(gridLayout instanceof GridLayout, true, 'GridLayout type');
|
||||
notEqual(gridLayout, null, 'GridLayout instanciated');
|
||||
notEqual(gridLayout.tblMainCont, null, 'GridLayout main container element');
|
||||
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');
|
||||
});
|
||||
|
||||
test('Destroy GridLayout component', function() {
|
||||
tf.Cpt.gridLayout.destroy();
|
||||
deepEqual(tf.Cpt.gridLayout.tblMainCont, null, 'Main container element removed');
|
||||
deepEqual(tf.Cpt.gridLayout.tblCont, null, 'Main HTML table container element removed');
|
||||
deepEqual(tf.Cpt.gridLayout.headTblCont, null, 'Headers container element removed');
|
||||
deepEqual(tf.Cpt.gridLayout.headTbl, null, 'Headers HTML table element removed');
|
||||
gridLayout.destroy();
|
||||
deepEqual(gridLayout.tblMainCont, null, 'Main container element removed');
|
||||
deepEqual(gridLayout.tblCont, null, 'Main HTML table container element removed');
|
||||
deepEqual(gridLayout.headTblCont, null, 'Headers container element removed');
|
||||
deepEqual(gridLayout.headTbl, null, 'Headers HTML table element removed');
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -23,9 +23,9 @@ requirejs(['test-config', '../src/core'], function(config, TableFilter){
|
|||
|
||||
module('Sanity checks');
|
||||
test('Store module', function() {
|
||||
deepEqual(tf.Cpt.Store instanceof Store, true, 'Store type');
|
||||
notEqual(tf.Cpt.Store, null, 'Store instanciated');
|
||||
deepEqual(tf.Cpt.Store.duration, 100000, 'Store duration');
|
||||
deepEqual(tf.Cpt.store instanceof Store, true, 'Store type');
|
||||
notEqual(tf.Cpt.store, null, 'Store instanciated');
|
||||
deepEqual(tf.Cpt.store.duration, 100000, 'Store duration');
|
||||
});
|
||||
|
||||
module('Check page number persistence');
|
||||
|
@ -34,7 +34,7 @@ requirejs(['test-config', '../src/core'], function(config, TableFilter){
|
|||
tf._Filter();
|
||||
tf._ChangePage(1);
|
||||
var cookieName = tf.pgNbCookie;
|
||||
deepEqual(tf.Cpt.Store.getPageNb(cookieName), '2', 'Page number value');
|
||||
deepEqual(tf.Cpt.store.getPageNb(cookieName), '2', 'Page number value');
|
||||
tf._ClearFilters();
|
||||
tf._Filter();
|
||||
});
|
||||
|
@ -44,7 +44,7 @@ requirejs(['test-config', '../src/core'], function(config, TableFilter){
|
|||
tf.resultsPerPageSlc.options[2].selected = true;
|
||||
tf._ChangeResultsPerPage();
|
||||
var cookieName = tf.pgLenCookie;
|
||||
deepEqual(tf.Cpt.Store.getPageLength(cookieName), '2', 'Page length value');
|
||||
deepEqual(tf.Cpt.store.getPageLength(cookieName), '2', 'Page length value');
|
||||
tf._ClearFilters();
|
||||
tf._Filter();
|
||||
});
|
||||
|
@ -55,8 +55,8 @@ requirejs(['test-config', '../src/core'], function(config, TableFilter){
|
|||
tf.SetFilterValue(3, '1.5');
|
||||
tf._Filter();
|
||||
var cookieName = tf.fltsValuesCookie;
|
||||
deepEqual(tf.Cpt.Store.getFilterValues(cookieName)[0], 'Sydney', 'Filter 0 value');
|
||||
deepEqual(tf.Cpt.Store.getFilterValues(cookieName)[3], '1.5', 'Filter 3 value');
|
||||
deepEqual(tf.Cpt.store.getFilterValues(cookieName)[0], 'Sydney', 'Filter 0 value');
|
||||
deepEqual(tf.Cpt.store.getFilterValues(cookieName)[3], '1.5', 'Filter 3 value');
|
||||
tf._ClearFilters();
|
||||
tf._Filter();
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue