1
0
Fork 0
mirror of https://github.com/koalyptus/TableFilter.git synced 2024-05-15 12:57:03 +02:00
TableFilter/src/modules/highlightKeywords.js

181 lines
5.2 KiB
JavaScript
Raw Normal View History

2016-05-24 10:42:11 +02:00
import {createText, createElm, getText} from '../dom';
2018-09-12 17:23:20 +02:00
import {isNull} from '../types';
import {rgxEsc} from '../string';
2017-07-09 07:11:51 +02:00
import {defaultsStr} from '../settings';
/**
* Highlight matched keywords upon filtering
*
* @export
* @class HighlightKeyword
*/
2016-03-23 09:02:48 +01:00
export class HighlightKeyword {
/**
* Creates an instance of HighlightKeyword
* @param {TableFilter} tf TableFilter instance
*/
constructor(tf) {
2016-03-23 09:02:48 +01:00
let f = tf.config();
/**
* Css class for highlighted term
* @type {String}
*/
2017-07-09 07:11:51 +02:00
this.highlightCssClass = defaultsStr(f.highlight_css_class, 'keyword');
/**
* TableFilter instance
* @type {TableFilter}
*/
this.tf = tf;
/**
* TableFilter's emitter instance
* @type {Emitter}
*/
2015-12-29 07:13:08 +01:00
this.emitter = tf.emitter;
}
/**
* Initializes HighlightKeyword instance
*/
2016-03-23 09:02:48 +01:00
init() {
this.emitter.on(
['before-filtering', 'destroy'],
2016-03-23 09:02:48 +01:00
() => this.unhighlightAll()
);
2016-01-18 07:36:10 +01:00
this.emitter.on(
['highlight-keyword'],
(tf, cell, term) => this._processTerm(cell, term)
2016-01-18 07:36:10 +01:00
);
}
/**
* Highlight occurences of searched term in passed node
* @param {Node} node
2016-10-12 05:15:19 +02:00
* @param {String} term Searched term
* @param {String} cssClass Css class name
2016-03-24 02:07:32 +01:00
*
* TODO: refactor this method
*/
2016-10-12 05:15:19 +02:00
highlight(node, term, cssClass) {
// Iterate into this nodes childNodes
2016-03-23 09:02:48 +01:00
if (node.hasChildNodes) {
let children = node.childNodes;
for (let i = 0; i < children.length; i++) {
2016-10-12 05:15:19 +02:00
this.highlight(children[i], term, cssClass);
}
}
2016-03-23 09:02:48 +01:00
if (node.nodeType === 3) {
2016-10-12 05:15:19 +02:00
let nodeVal = node.nodeValue.toLowerCase();
let termIdx = nodeVal.indexOf(term.toLowerCase());
2016-10-10 09:16:39 +02:00
2016-10-12 05:15:19 +02:00
if (termIdx !== -1) {
2016-03-23 09:02:48 +01:00
let pn = node.parentNode;
if (pn && pn.className !== cssClass) {
2016-10-12 05:15:19 +02:00
// term not highlighted yet
2016-03-23 09:02:48 +01:00
let nv = node.nodeValue,
// Create a load of replacement nodes
2016-10-12 05:15:19 +02:00
before = createText(nv.substr(0, termIdx)),
value = nv.substr(termIdx, term.length),
after = createText(nv.substr(termIdx + term.length)),
text = createText(value),
container = createElm('span');
container.className = cssClass;
container.appendChild(text);
2016-03-23 09:02:48 +01:00
pn.insertBefore(before, node);
2016-10-12 05:15:19 +02:00
pn.insertBefore(container, node);
2016-03-23 09:02:48 +01:00
pn.insertBefore(after, node);
pn.removeChild(node);
}
}
}
}
/**
* Removes highlight to nodes matching passed string
2016-10-12 05:15:19 +02:00
* @param {String} term
* @param {String} cssClass Css class to remove
*/
2016-10-12 05:15:19 +02:00
unhighlight(term, cssClass) {
let highlightedNodes = this.tf.dom().querySelectorAll(`.${cssClass}`);
2016-03-23 09:02:48 +01:00
for (let i = 0; i < highlightedNodes.length; i++) {
let n = highlightedNodes[i];
2016-10-12 05:15:19 +02:00
let nodeVal = getText(n);
2016-03-23 09:02:48 +01:00
2018-09-12 17:23:20 +02:00
if (isNull(term) ||
nodeVal.toLowerCase().indexOf(term.toLowerCase()) !== -1) {
2016-10-10 09:16:39 +02:00
let parentNode = n.parentNode;
parentNode.replaceChild(createText(nodeVal), n);
parentNode.normalize();
}
}
}
/**
* Clear all occurrences of highlighted nodes
*/
2016-03-23 09:02:48 +01:00
unhighlightAll() {
if (!this.tf.highlightKeywords) {
return;
}
2018-09-12 17:23:20 +02:00
this.unhighlight(null, this.highlightCssClass);
}
2015-12-29 07:13:08 +01:00
/** Remove feature */
2016-03-23 09:02:48 +01:00
destroy() {
this.emitter.off(
['before-filtering', 'destroy'],
2016-03-23 09:02:48 +01:00
() => this.unhighlightAll()
);
2016-01-18 07:36:10 +01:00
this.emitter.off(
['highlight-keyword'],
(tf, cell, term) => this._processTerm(cell, term)
2016-01-18 07:36:10 +01:00
);
2015-12-29 07:13:08 +01:00
}
/**
* Ensure filtering operators are handled before highlighting any match
* @param {any} Table cell to look searched term into
* @param {any} Searched termIdx
*/
_processTerm(cell, term) {
let tf = this.tf;
let reLk = new RegExp(rgxEsc(tf.lkOperator));
let reEq = new RegExp(tf.eqOperator);
let reSt = new RegExp(tf.stOperator);
let reEn = new RegExp(tf.enOperator);
let reLe = new RegExp(tf.leOperator);
let reGe = new RegExp(tf.geOperator);
let reL = new RegExp(tf.lwOperator);
let reG = new RegExp(tf.grOperator);
let reD = new RegExp(tf.dfOperator);
term = term
.replace(reLk, '')
.replace(reEq, '')
.replace(reSt, '')
.replace(reEn, '');
if (reLe.test(term) || reGe.test(term) || reL.test(term) ||
reG.test(term) || reD.test(term)) {
term = getText(cell);
}
if (term === '') {
return;
}
this.highlight(cell, term, this.highlightCssClass);
}
2016-03-23 09:02:48 +01:00
}
2019-01-15 13:29:13 +01:00
// TODO: remove as soon as feature name is fixed
2019-02-10 13:14:46 +01:00
HighlightKeyword.meta = {
name: 'highlightKeyword',
altName: 'highlightKeywords'
};