(function IIFE() { "use strict"; function factory($) { var pluginName = "searcher", dataKey = "plugin_" + pluginName, defaults = { // selector for the item element itemSelector: "tbody > tr", // selector for the text elements textSelector: "td", // selector for the input inputSelector: "", // determines whether the search is case sensitive or not caseSensitive: false, // function to toggle the visibility of the item toggle: function(item, containsText) { $(item).toggle(containsText); } }; function Searcher(element, options) { this.element = element; this.options = $.extend({ }, defaults, options); this._create(); } Searcher.prototype = { dispose: function() { // unbind all events this._$input.unbind("." + pluginName); // toggle all elements with true var options = this.options, toggle = options.toggle || defaults.toggle; this._$element.find(options.itemSelector).each(function() { toggle(this, true); }); }, filter: function(value) { this._lastValue = value; var options = this.options, textSelector = options.textSelector, toggle = options.toggle || defaults.toggle; // build the regular expression for searching var flags = "gm" + (!options.caseSensitive ? "i" : ""); var regex = new RegExp("(" + escapeRegExp(value) + ")", flags); this._$element .find(options.itemSelector) .each(function eachItem() { var $item = $(this), $textElements = textSelector ? $item.find(textSelector) : $item, itemContainsText = false; $textElements = $textElements.each(function eachTextElement() { itemContainsText = itemContainsText || !!$(this).text().match(regex); return !itemContainsText; // stop if at least one text element contains the text }); toggle(this, itemContainsText); }); }, _create: function() { var options = this.options; this._$element = $(this.element); // find the input and bind to various events this._fn = $.proxy(this._onValueChange, this); var eventNames = "input." + pluginName + " change." + pluginName + " keyup." + pluginName; this._$input = $(options.inputSelector).bind(eventNames, this._fn); // remember the last entered value this._lastValue = null; // call the toggle with true for all items on startup var toggle = options.toggle || defaults.toggle; this._$element.find(options.itemSelector).each(function() { toggle(this, true); }); }, _onValueChange: function() { var value = this._$input.val(); if (value === this._lastValue) return; // nothing has changed this.filter(value); } }; function escapeRegExp(text) { // see https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions return text.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"); } $.fn[pluginName] = function pluginHandler(options) { var args = Array.prototype.slice.call(arguments, 1); return this.each(function() { var searcher = $.data(this, dataKey); var t = typeof(options); if (t === "string" && searcher) { searcher[options].apply(searcher, args); if (options === "dispose") $.removeData(this, dataKey); } else if (t === "object") { if (!searcher) // create a new searcher $.data(this, dataKey, new Searcher(this, options)); else // update the options of the existing $.extend(searcher.options, options); } }); }; } // AMD style (register as an anonymous module) if (typeof(define) === "function" && define.amd) define(["jquery"], factory); // node/CommonJS style (for Browserify) else if (typeof(exports) === "object") module.exports = factory; // browser else factory(jQuery); }).call(this);