Skip to content

Instantly share code, notes, and snippets.

@KartaviK
Last active October 15, 2019 09:33
Show Gist options
  • Save KartaviK/f6d7d02ad729863ec8171057bded189c to your computer and use it in GitHub Desktop.
Save KartaviK/f6d7d02ad729863ec8171057bded189c to your computer and use it in GitHub Desktop.
Searching substring in sub-nodes of exist collection htmlnode elements
/**
* Simple usage:
* Initing:
* $.search.init(
* '.node' // Selector of elements
* ['.inner_title', 'description', 'comments'], // Colelciton of selectors where is need to search substring,
* 'search-ui', // Name of data attribute to write index of element to search and state
* 'search-highlight' // Name of class for highlighting of find substrings
* );
* Searching:
* $.search.run(
* 'some test substring', // String to search
* true // Do or not to do highlight
* );
*
* $.search.state; // You can get statistic of find elements in simple collection, it will reset with next invoked run()
*/
(function ($) {
$.search = {
target: null,
selectors: [],
dataAttribute: 'search-ui',
highlightClass: 'search-highlight',
state: [],
inited: false,
init: function (target, selectors, dataAttribute = 'search-ui', highlightClass = 'search-highlight') {
this.target = $(target);
this.state = [];
this.selectors = selectors;
this.dataAttribute = dataAttribute;
this.highlightClass = highlightClass;
$(this.target.selector).each((index, node) => {
$(node).attr(`data-${this.dataAttribute}`, index);
$.search.state.push([]);
$.search.selectors.forEach(selector => this.state[index].push({name: selector, count: 0}));
});
this.inited = true;
},
run: function (text, doHighlight = true) {
if (!this.inited) {
console.error('Search plugin was not initialized!');
}
this.clearHighlight();
this.resetState();
$(this.target.selector).each((index, node) => {
this.state[index].forEach(selector => {
let targetSelector = this.state[index].find(item => item.name === selector.name);
$(node).find(selector.name).each((_, node) => {
if (this.regex(text).exec($(node).html().trim())) {
targetSelector.count++;
}
});
});
});
doHighlight && this.highlight(text);
},
hideNegativeResults: function () {
this.state.forEach((selectors, index) => {
if (selectors.reduce((sum, selector) => sum + selector.count, 0) === 0) {
$(`${$.search.target.selector}[data-${this.dataAttribute}=${index}]:visible`).hide();
}
});
},
highlight: function (text, hideNegativeResults = true) {
hideNegativeResults && this.hideNegativeResults();
this.state.forEach((selectors, index) => {
selectors.filter(selector => selector.count > 0).forEach(selector => {
$(`${$.search.target.selector}[data-${this.dataAttribute}=${index}]:visible`)
.find(selector.name)
.html((_, html) => html.replace(
this.regex(text),
`<span class="${this.highlightClass}">$1</span>`
));
})
});
},
resetState: function () {
this.state.forEach(selectors => selectors.forEach(selector => selector.count = 0));
},
clearHighlight: function () {
$(`.${this.highlightClass}`).each((_, node) => $(node).replaceWith(node.childNodes));
},
regex: function (pattern) {
return new RegExp(`(${pattern.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&")})`, 'giu');
},
};
})(jQuery);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment