1
0
Fork 0
mirror of https://github.com/koalyptus/TableFilter.git synced 2024-05-12 19:36:41 +02:00

Added highlight keyword feature + associated tests

This commit is contained in:
Max Guglielmi 2014-12-13 20:04:25 +11:00
parent 06ffffaada
commit 0f4d81b9a5
8 changed files with 161 additions and 151 deletions

2
dist/filtergrid.css vendored
View file

@ -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
------------------------------------------------------------------------*/

View 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 = [];
}
}

View file

@ -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
=====================================================*/

View file

@ -1,4 +0,0 @@
return require('core');
});

View file

@ -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,

View file

@ -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() {

View file

@ -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');
});
});

View file

@ -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();
});