diff options
Diffstat (limited to 'javascript/live_search.js')
| -rwxr-xr-x[-rw-r--r--] | javascript/live_search.js | 147 |
1 files changed, 77 insertions, 70 deletions
diff --git a/javascript/live_search.js b/javascript/live_search.js index 42ebfbc..70dea50 100644..100755 --- a/javascript/live_search.js +++ b/javascript/live_search.js @@ -1,70 +1,77 @@ -/*
-Written by: Adam Crownoble (adam@bryan.edu)
-Date: April 3 2006
-License: LGPL (http://www.gnu.org/copyleft/lesser.html)
-*/
-
-var LiveSearch = Class.create();
-LiveSearch.prototype = {
- initialize: function(searchBox, results) {
- this.form = searchBox.form;
- this.searchBox = searchBox;
- this.results = results;
- this.url = this.form.action;
- this.method = this.form.method;
- this.stopSubmit = true;
- this.searchString = this.searchBox.value;
- this.starterText = this.searchString;
- this.searchingMessage = 'Searching...';
- this.minLength = 3;
- this.timeoutID = 0;
- this.delay = 500;
-
- Event.observe(this.form, 'submit', this.submit.bind(this));
- Event.observe(this.searchBox, 'keyup', this.update.bind(this));
- Event.observe(this.searchBox, 'focus', this.handleStarterText.bind(this));
- Event.observe(this.searchBox, 'blur', this.handleStarterText.bind(this));
-
- this.form.reset();
- },
-
- handleStarterText: function(event) {
- switch(event.type) {
- case 'focus':
- if(this.searchBox.value == this.starterText) {
- Field.clear(this.searchBox);
- }
- break;
-
- case 'blur':
- if(this.searchBox.value == '') {
- this.searchBox.value = this.starterText;
- }
- break;
- }
- },
-
- update: function() {
- if(this.searchString != this.searchBox.value && this.searchBox.value != this.starterText) {
-
- this.searchString = this.searchBox.value;
- clearTimeout(this.timeoutID);
-
- if(this.searchString.length >= this.minLength) {
- this.results.innerHTML = this.searchingMessage;
- this.timeoutID = setTimeout(this.search.bind(this), this.delay);
- } else {
- this.results.innerHTML = '';
- }
- }
- },
-
- search: function() {
- var parameters = Form.serialize(this.form);
- var ajax = new Ajax.Updater(this.results, this.url, { method: this.method, parameters: parameters });
- },
-
- submit: function(event) {
- if(this.stopSubmit) { Event.stop(event); }
- }
-};
+(function ($) { + 'use strict'; + + /** + * LiveSearch - debounced keyup search with JSON results rendered into a container. + * + * @param {string} inputSel - jQuery selector for the text input + * @param {string} resultsSel - jQuery selector for the results container div + * @param {string} url - endpoint that accepts ?highlight=<term> and returns + * JSON [{title, href, type}, ...] + */ + function LiveSearch(inputSel, resultsSel, url) { + var $input = $(inputSel); + var $results = $(resultsSel); + var lastVal = ''; + var minLen = 3; + var delay = 400; + var timer = 0; + + if (!$input.length || !$results.length) { return; } + + $input + .on('focus', function () { + if (this.value === this.defaultValue) { this.value = ''; } + }) + .on('blur', function () { + if (this.value === '') { this.value = this.defaultValue; } + }) + .on('keyup', function () { + var val = $.trim($input.val()); + if (val === lastVal) { return; } + lastVal = val; + clearTimeout(timer); + if (val.length >= minLen) { + $results.text('Searching…'); + timer = setTimeout(doSearch, delay); + } else { + $results.empty(); + } + }); + + $input.closest('form').on('submit', function (e) { + e.preventDefault(); + doSearch(); + }); + + function esc(s) { + return $('<span>').text(s).html(); + } + + function doSearch() { + var val = $.trim($input.val()); + if (!val || val === $input[0].defaultValue) { return; } + $.getJSON(url, { highlight: val }) + .done(function (items) { + if (!items || !items.length) { + $results.html('<p>No results.</p>'); + return; + } + var html = '<ul>'; + $.each(items, function (i, r) { + html += '<li><a href="' + esc(r.href) + '">' + esc(r.title) + '</a>'; + if (r.type) { html += ' <small>' + esc(r.type) + '</small>'; } + html += '</li>'; + }); + html += '</ul>'; + $results.html(html); + }) + .fail(function () { + $results.html('<p>Search unavailable.</p>'); + }); + } + } + + window.LiveSearch = LiveSearch; + +}(jQuery)); |
