Last active
August 29, 2015 14:21
-
-
Save groovenectar/17153f0da7ac2b29c981 to your computer and use it in GitHub Desktop.
jquery.searchify.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<title>jquery.searchify.js</title> | |
<link rel="stylesheet" href="style.css"> | |
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.min.js"></script> | |
<script type="text/javascript" src="jquery.searchify.js"></script> | |
<style type="text/css"> | |
body { | |
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | |
} | |
</style> | |
<script type="text/javascript"> | |
jQuery(function($) { | |
$('.example').searchify(); | |
$('.example2').hide(); | |
}); | |
</script> | |
</html> | |
<body> | |
<div class="nav"></div> | |
<ul class="example"> | |
<li>Lorem</li> | |
<li>ipsum</li> | |
<li>dolor</li> | |
<li>amet</li> | |
<li>consectetur</li> | |
<li>adipiscing</li> | |
<li>elit</li> | |
<li>consequat</li> | |
<li>consectetur</li> | |
<li>sollicitudin</li> | |
<li class="test">fermentum</li> | |
<li>auctor</li> | |
<li>elementum</li> | |
<li class="test">Integer</li> | |
<li>neque</li> | |
<li class="test">enim</li> | |
<li>fermentum</li> | |
<li>commodo</li> | |
<li>tincidunt</li> | |
<li>ligula</li> | |
<li class="test">dapibus</li> | |
<li>luctus</li> | |
<li>quam</li> | |
<li class="test">vitae</li> | |
<li>feugiat</li> | |
<li>sagittis</li> | |
<li class="test">Aliquam</li> | |
<li>ante</li> | |
<li>enim</li> | |
<li>elementum</li> | |
<li>scelerisque</li> | |
<li class="test">Cras</li> | |
<li>hendrerit</li> | |
<li>massa</li> | |
<li class="test">imperdiet</li> | |
<li>Fusce</li> | |
<li>cursus</li> | |
<li>vitae</li> | |
<li class="test">interdum</li> | |
<li>magna</li> | |
<li>Quisque</li> | |
<li>sagittis</li> | |
<li>lobortis</li> | |
<li>fringilla</li> | |
<li>Proin</li> | |
<li class="test">venenatis</li> | |
<li>ligula</li> | |
<li>Vestibulum</li> | |
<li>ante</li> | |
<li>vestibulum</li> | |
<li>sollicitudin</li> | |
<li class="test">sapien</li> | |
<li>suscipit</li> | |
<li>elit</li> | |
<li class="test">sapien</li> | |
<li>ante</li> | |
<li>cursus</li> | |
<li>condimentum</li> | |
<li>dapibus</li> | |
</ul> | |
<div class="nav"></div> | |
<ul class="example2"> | |
<li>Lorem</li> | |
<li>ipsum</li> | |
<li>dolor</li> | |
<li>amet</li> | |
<li>consectetur</li> | |
<li>adipiscing</li> | |
<li>elit</li> | |
<li>consequat</li> | |
<li>consectetur</li> | |
<li>sollicitudin</li> | |
<li class="test">fermentum</li> | |
<li>auctor</li> | |
<li>elementum</li> | |
<li class="test">Integer</li> | |
<li>neque</li> | |
<li class="test">enim</li> | |
<li>fermentum</li> | |
<li>commodo</li> | |
<li>tincidunt</li> | |
<li>ligula</li> | |
<li class="test">dapibus</li> | |
<li>luctus</li> | |
<li>quam</li> | |
<li class="test">vitae</li> | |
<li>feugiat</li> | |
<li>sagittis</li> | |
<li class="test">Aliquam</li> | |
<li>ante</li> | |
<li>enim</li> | |
<li>elementum</li> | |
<li>scelerisque</li> | |
<li class="test">Cras</li> | |
<li>hendrerit</li> | |
<li>massa</li> | |
<li class="test">imperdiet</li> | |
<li>Fusce</li> | |
<li>cursus</li> | |
<li>vitae</li> | |
<li class="test">interdum</li> | |
<li>magna</li> | |
<li>Quisque</li> | |
<li>sagittis</li> | |
<li>lobortis</li> | |
<li>fringilla</li> | |
<li>Proin</li> | |
<li class="test">venenatis</li> | |
<li>ligula</li> | |
<li>Vestibulum</li> | |
<li>ante</li> | |
<li>vestibulum</li> | |
<li>sollicitudin</li> | |
<li class="test">sapien</li> | |
<li>suscipit</li> | |
<li>elit</li> | |
<li class="test">sapien</li> | |
<li>ante</li> | |
<li>cursus</li> | |
<li>condimentum</li> | |
<li>dapibus</li> | |
</ul> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Based on https://github.com/jlafitte/jquery-quick-pagination | |
;(function ($, window, document, undefined) { | |
"use strict"; | |
var defaults = { | |
label: 'Search:', // Inserted before input | |
typing_threshold: 500, // Delay in milliseconds to determine whether user is finished typing | |
min_chars: 3, // Must have typed at least this many characters to initiate search | |
match_class: 'search-match', // Matched items gets this class | |
search_location: 'before', // Possible values are "before,after,both,[jQuery Object]" | |
search_class: 'search-filter-form', // Class name of the search container | |
label_template: '<label>', // HTML or jQuery object. Any special attributes/classes can be added | |
input_template: '<input type="search">', // HTML or jQuery object. Any special attributes/classes can be added | |
wrap_label: true, // If false, give the input template an "id" attribute and label template a "for" attribute | |
item_filter: '*', // .filter() to run on items to determine what is included (E.g. ":visible") | |
form_input: null, // String selector or jQuery object. If specified, will only use existing input for search | |
item_text: function() { // Item text to match against. "this" context is the item element. | |
return this.text(); | |
}, | |
search_start: function(search_terms) { // "this" context is the plugin instance | |
this._debug('options.search_start called'); | |
this.items.hide(); | |
}, | |
clear: function() { // "this" context is the plugin instance | |
this._debug('options.clear called'); | |
this.element.prev('.no-matches').remove(); | |
this.items.show(); | |
}, | |
matches: function(matches, search_terms) { // Called when there are search results. "this" context is the plugin instance | |
this._debug('options.matches called'); | |
matches.show(); | |
}, | |
no_matches: function(search_terms) { // Called when there are no search results. "this" context is the plugin instance | |
this._debug('options.no_matches called'); | |
this.element.before($('<p>').addClass('no-matches').text('No results for "' + search_terms + '"')); | |
}, | |
complete: function() { // Called whether or not there are search results. "this" context is the plugin instance | |
this._debug('options.complete called'); | |
} | |
}; | |
function Plugin(element, options) { | |
this.element = $(element); | |
this.options = $.extend({}, defaults, options); | |
this._defaults = defaults; | |
this.init(); | |
} | |
$.extend(Plugin.prototype, { | |
init: function () { | |
this.debug = true; | |
this._debug('init called'); | |
this._loaditems(); | |
this._render(); | |
this.options.search_applied_class = this.options.match_class + '-applied'; | |
this.search_terms = ''; | |
this.typing_timer = null; | |
this.num_results = 0; | |
this.matches = null; | |
return this; | |
}, | |
_render: function() { | |
this._debug('_render called'); | |
// We don't need to build a search form if using external | |
if (this.options.form_input !== null) { | |
this.input = $(this.options.form_input); | |
return this; | |
} | |
this.search_form = $(); | |
this.input = $(); | |
this._insert_search_form(); | |
return this; | |
}, | |
_loaditems: function(filter) { | |
this._debug('_loaditems called'); | |
filter = filter ? filter : this.options.item_filter; | |
this.items = this.element.children().filter(filter); | |
return this; | |
}, | |
filter: function(filter) { | |
this._debug('filter called'); | |
this._loaditems(filter); | |
this.reload(); | |
return this; | |
}, | |
_search_applied: function() { | |
this._debug('_search_applied called'); | |
return this.element.hasClass(this.options.search_applied_class); | |
}, | |
search: function(val) { | |
this._debug('search called'); | |
if (this._search_applied()) { | |
this.clear(); | |
} | |
this.search_terms = val; | |
if (this.search_terms.length < this.options.min_chars) { | |
return this; | |
} | |
this.options.search_start.call(this, this.search_terms); | |
this.element.addClass(this.options.search_applied_class); | |
var regex = new RegExp(this.search_terms, 'i'); | |
var $plugin = this; | |
$plugin.items.filter(function() { | |
var text = $plugin.options.item_text.call($(this)); | |
if (regex.test(text)) { | |
$(this).addClass($plugin.options.match_class); | |
$plugin.num_results++; | |
} | |
}); | |
if (this.num_results > 0) { | |
this.matches = this.items.filter('.' + this.options.match_class); | |
this.options.matches.call(this, this.matches, this.search_terms); | |
} else { | |
this.matches = null; | |
this.options.no_matches.call(this, this.search_terms); | |
} | |
this.options.complete.call(this); | |
return this; | |
}, | |
clear: function() { | |
this._debug('clear called'); | |
this.matches = null; | |
this.search_terms = ''; | |
this.num_results = 0; | |
this.element.removeClass(this.options.search_applied_class); | |
this.items.removeClass(this.options.match_class); | |
this.options.clear.call(this); | |
return this; | |
}, | |
_sync_inputs: function(val) { | |
this._debug('_sync_inputs called'); | |
this.input.val(val); | |
return this; | |
}, | |
_build_input: function() { | |
this._debug('_build_input called'); | |
var input = $(this.options.input_template); | |
var $plugin = this; | |
input.on('keyup', function(e) { | |
clearTimeout($plugin.typing_timer); | |
var input = $(this); | |
$plugin.typing_timer = setTimeout(function() { | |
input.trigger('search'); | |
}, $plugin.options.typing_threshold); | |
}); | |
input.on('keydown', function(e) { | |
clearTimeout($plugin.typing_timer); | |
}); | |
// input.on('click', function(e) { }); | |
// input.on('input', function(e) { }); | |
input.on('search', function(e) { | |
$plugin._sync_inputs($(this).val()); | |
$plugin.search($(this).val()); | |
}); | |
return input; | |
}, | |
_build_search_form: function() { | |
this._debug('_build_search_form called'); | |
var search_form = $('<form>').addClass(this.options.search_class); | |
search_form.on('submit', function(e) { | |
e.preventDefault(); | |
}); | |
var label = $(this.options.label_template).text(this.options.label); | |
search_form.append(label); | |
var input = this._build_input(); | |
if (this.options.wrap_label) { | |
label.append(input); | |
} else { | |
search_form.append(input); | |
} | |
this.input = this.input.add(input); | |
this.search_form = this.search_form.add(search_form); | |
return search_form; | |
}, | |
_insert_search_form: function(search_location) { | |
this._debug('_insert_search_form called'); | |
search_location = search_location ? search_location : this.options.search_location; | |
if (search_location instanceof jQuery) { | |
this.search_form = search_location.append(this._build_search_form()).find('.' + this.options.search_class); | |
} else { | |
var search_form; | |
switch (search_location) { | |
case 'before': | |
search_form = this._build_search_form().addClass(this.options.search_class + '-before'); | |
this.element.before(search_form); | |
break; | |
case 'after': | |
search_form = this._build_search_form().addClass(this.options.search_class + '-after'); | |
this.element.after(search_form); | |
break; | |
case 'both': | |
this._insert_search_form('before'); | |
this._insert_search_form('after'); | |
return this; | |
break; | |
default: | |
return this; | |
break; | |
} | |
} | |
return this; | |
}, | |
reload: function() { | |
this._debug('reload called'); | |
this.remove(); | |
this._render(); | |
return this; | |
}, | |
_remove_search_form: function() { | |
this._debug('_remove_search_form called'); | |
this.search_form.remove(); | |
return this; | |
}, | |
remove: function() { | |
this._debug('remove called'); | |
this.clear(); | |
this._remove_search_form(); | |
return this; | |
}, | |
// Also removes plugin reference from this.element | |
// Additional functionality below | |
destroy: function() { | |
this._debug('destroy called'); | |
this.remove(); | |
}, | |
_debug: function(string) { | |
if (!this.debug) { | |
return this; | |
} | |
if (new RegExp(' called$').test(string)) { | |
return this; | |
} | |
console.log(string); | |
} | |
}); | |
var plugin_name = 'searchify'; | |
$.fn[plugin_name] = function(options) { | |
var args = arguments; | |
if (options === undefined || typeof options === 'object') { | |
return this.each(function () { | |
if (!$.data(this, 'plugin_' + plugin_name)) { | |
$.data(this, 'plugin_' + plugin_name, new Plugin(this, options)); | |
} | |
}); | |
} else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') { | |
var returns; | |
this.each(function() { | |
var instance = $.data(this, 'plugin_' + plugin_name); | |
if (instance instanceof Plugin && typeof instance[options] === 'function') { | |
returns = instance[options].apply( instance, Array.prototype.slice.call(args, 1)); | |
} | |
if (options === 'destroy') { | |
$.data(this, 'plugin_' + plugin_name, null); | |
} | |
}); | |
return returns !== undefined ? returns : this; | |
} | |
}; | |
}(jQuery, window, document)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.search-filter-form { | |
display: inline-block; | |
} | |
.search-filter-form label { | |
font-size: .8rem; | |
display: inline-block; | |
} | |
.search-filter-form input { | |
vertical-align: bottom; | |
display: block; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment