107 lines
3.2 KiB
JavaScript
107 lines
3.2 KiB
JavaScript
|
/**
|
||
|
* jQuery plugin for an instant searching.
|
||
|
*
|
||
|
* @author Oleg Voronkovich <oleg-voronkovich@yandex.ru>
|
||
|
* @author Yonel Ceruto <yonelceruto@gmail.com>
|
||
|
*/
|
||
|
(function ($) {
|
||
|
'use strict';
|
||
|
|
||
|
String.prototype.render = function (parameters) {
|
||
|
return this.replace(/({{ (\w+) }})/g, function (match, pattern, name) {
|
||
|
return parameters[name];
|
||
|
})
|
||
|
};
|
||
|
|
||
|
// INSTANTS SEARCH PUBLIC CLASS DEFINITION
|
||
|
// =======================================
|
||
|
|
||
|
var InstantSearch = function (element, options) {
|
||
|
this.$input = $(element);
|
||
|
this.$form = this.$input.closest('form');
|
||
|
this.$preview = $('<ul class="search-preview list-group">').appendTo(this.$form);
|
||
|
this.options = $.extend({}, InstantSearch.DEFAULTS, this.$input.data(), options);
|
||
|
|
||
|
this.$input.keyup(this.debounce());
|
||
|
};
|
||
|
|
||
|
InstantSearch.DEFAULTS = {
|
||
|
minQueryLength: 2,
|
||
|
limit: 10,
|
||
|
delay: 500,
|
||
|
noResultsMessage: 'No results found',
|
||
|
itemTemplate: '\
|
||
|
<article class="post">\
|
||
|
<h2><a href="{{ url }}">{{ title }}</a></h2>\
|
||
|
<p class="post-metadata">\
|
||
|
<span class="metadata"><i class="fa fa-calendar"></i> {{ date }}</span>\
|
||
|
<span class="metadata"><i class="fa fa-user"></i> {{ author }}</span>\
|
||
|
</p>\
|
||
|
<p>{{ summary }}</p>\
|
||
|
</article>'
|
||
|
};
|
||
|
|
||
|
InstantSearch.prototype.debounce = function () {
|
||
|
var delay = this.options.delay;
|
||
|
var search = this.search;
|
||
|
var timer = null;
|
||
|
var self = this;
|
||
|
|
||
|
return function () {
|
||
|
clearTimeout(timer);
|
||
|
timer = setTimeout(function () {
|
||
|
search.apply(self);
|
||
|
}, delay);
|
||
|
};
|
||
|
};
|
||
|
|
||
|
InstantSearch.prototype.search = function () {
|
||
|
var query = $.trim(this.$input.val()).replace(/\s{2,}/g, ' ');
|
||
|
if (query.length < this.options.minQueryLength) {
|
||
|
this.$preview.empty();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var self = this;
|
||
|
var data = this.$form.serializeArray();
|
||
|
data['l'] = this.limit;
|
||
|
|
||
|
$.getJSON(this.$form.attr('action'), data, function (items) {
|
||
|
self.show(items);
|
||
|
});
|
||
|
};
|
||
|
|
||
|
InstantSearch.prototype.show = function (items) {
|
||
|
var $preview = this.$preview;
|
||
|
var itemTemplate = this.options.itemTemplate;
|
||
|
|
||
|
if (0 === items.length) {
|
||
|
$preview.html(this.options.noResultsMessage);
|
||
|
} else {
|
||
|
$preview.empty();
|
||
|
$.each(items, function (index, item) {
|
||
|
$preview.append(itemTemplate.render(item));
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// INSTANTS SEARCH PLUGIN DEFINITION
|
||
|
// =================================
|
||
|
|
||
|
function Plugin(option) {
|
||
|
return this.each(function () {
|
||
|
var $this = $(this);
|
||
|
var instance = $this.data('instantSearch');
|
||
|
var options = typeof option === 'object' && option;
|
||
|
|
||
|
if (!instance) $this.data('instantSearch', (instance = new InstantSearch(this, options)));
|
||
|
|
||
|
if (option === 'search') instance.search();
|
||
|
})
|
||
|
}
|
||
|
|
||
|
$.fn.instantSearch = Plugin;
|
||
|
$.fn.instantSearch.Constructor = InstantSearch;
|
||
|
|
||
|
})(window.jQuery);
|