Created
August 9, 2012 21:04
-
-
Save ksafranski/3308065 to your computer and use it in GitHub Desktop.
Simple jQuery Autocomplete plugin
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
/* | |
* | |
* Simple Autocomplete Plugin | |
* @author - Kent Safranski - http://www.fluidbyte.net | |
* | |
* HTML: | |
* -------------------------------------------------------------------- | |
* <input class="autocomplete" data-src="path/to/processor.php" /> | |
* | |
* CSS: | |
* -------------------------------------------------------------------- | |
* .autocomplete-reveal { background: #f5f5f5; border: 1px solid #ccc; border-top: none; } | |
* .autocomplete-reveal li { padding: 3px 10px; cursor: pointer; } | |
* .autocomplete-reveal li:hover, .autocomplete-reveal li.selected { background: #dadced; } | |
* | |
* JAVASCRIPT: | |
* -------------------------------------------------------------------- | |
* | |
* $('.autocomplete').autocomplete({ dataformat: "item.city+', '+item.state" }); | |
* | |
* | |
* HOW IT WORKS - THE DATA: | |
* -------------------------------------------------------------------- | |
* The concept is simple - the 'data-src' attribute on the input field | |
* is what tells the script where to grab the data. It works best with | |
* JSON in the JSend Format <http://labs.omniti.com/labs/jsend> : | |
* | |
* { | |
* "status":"success", | |
* "data":[ | |
* {"city":"Little Rock","state":"AK"}, | |
* {"city":"Denver","state":"CO"}, | |
* {"city":"Baton Rouge","state":"LA"}, | |
* ... | |
* ] | |
* } | |
* | |
* the 'dataformat' parameter represents the individual entity items so | |
* compare the JAVASCRIPT to the JSON and it's pretty simple to follow, | |
* where 'item' is the array returned. | |
* | |
*/ | |
(function ($) { | |
$.fn.autocomplete = function (o) { | |
var o = jQuery.extend({ | |
city: "item.city", | |
state: "item.state_prefix", | |
zip: "item.zip_code" | |
//dataformat: "item.city+', '+item.state_prefix" | |
}, o); | |
$(this) | |
.each(function () { | |
// Set the field | |
acfield = $(this); | |
// Get the data source | |
var acdatasrc = acfield.attr('data-src'); | |
// Disable default autocomplete | |
acfield.attr('autocomplete', 'off'); | |
// Wrap yo stuff! | |
acfield.wrap('<div class="autocomplete-wrapper" />'); | |
acfield.parent('.autocomplete-wrapper') | |
.append('<ul class="autocomplete-reveal"></ul>'); | |
// Just some definition | |
acchosen = null; | |
var acwrapper = $('.autocomplete-wrapper'); | |
var acreveal = $('.autocomplete-reveal'); | |
var acitem = $('.autocomplete-reveal li'); | |
// Apply control styles | |
acwrapper.css({ | |
'position': 'relative' | |
}); | |
acreveal.css({ | |
'display': 'none', | |
'position': 'absolute', | |
'margin': '0', | |
'padding': '0', | |
'width': $(this) | |
.outerWidth() - 2 + 'px', | |
'top': $(this) | |
.outerHeight() + 'px' | |
}); | |
acitem.css({ | |
'list-style': 'none' | |
}); | |
// Process | |
acfield.on('keyup', function (e) { | |
if (e.which !== 40 && e.which !== 38) { // Not arrow keys, right? | |
if (acfield.val() != "") { // There's text in the field, right? | |
$.get(acdatasrc + '?ac=' + acfield.val(), function (data) { | |
// Clean slate | |
acreveal.html(''); // Clean drop-down | |
acchosen = null; // Reset and chosen selections | |
// Process response | |
var output = $.parseJSON(data); | |
// Success? | |
if (output.status == 'success') { | |
var list = output.data; | |
// No results | |
if (list.length == 0) { | |
acreveal.hide(); | |
} | |
// Loop it out! | |
else { | |
$.each(list, function (i, item) { | |
acreveal.append('<li value="' + eval(o.zip) + '">' + eval(o.city) + ', ' + eval(o.state) + '</li>'); | |
}); | |
acreveal.show(); | |
} | |
} | |
}); | |
} else { | |
acreveal.hide(); // Nope, no text in the field... | |
} | |
} | |
}); | |
// What do we do on enter or tab key? | |
acfield.on('keydown', function (e) { // 13-enter | |
if (e.keyCode == 13 || e.keyCode == 9) { | |
if (acchosen !== null) { // Something's been selected from the autocomplete | |
var acsuggest = acreveal.children('li.selected') | |
.text(); | |
acfield.val(acsuggest); | |
acreveal.hide(); | |
e.preventDefault(); | |
//return false; | |
} | |
} | |
}); | |
// Arrow key navigation? Why not! | |
acfield.on('keyup', function (e) { // 38-up, 40-down | |
if (e.keyCode == 40) { | |
if (acchosen === null) { | |
acchosen = 0; | |
} else if ((acchosen + 1) < $('li') | |
.length) { | |
acchosen++; | |
} | |
acreveal.children('li') | |
.removeClass('selected'); | |
acreveal.children('li:eq(' + acchosen + ')') | |
.addClass('selected'); | |
return false; | |
} | |
if (e.keyCode == 38) { | |
if (acchosen === "") { | |
acchosen = 0; | |
} else if (acchosen > 0) { | |
acchosen--; | |
} | |
acreveal.children('li') | |
.removeClass('selected'); | |
acreveal.children('li:eq(' + acchosen + ')') | |
.addClass('selected'); | |
return false; | |
} | |
}); | |
// Hover over arrow-selected reveal | |
acreveal.on('hover', function () { | |
acreveal.children('li') | |
.removeClass('selected'); | |
}); | |
// Click on item | |
acreveal.on('click', 'li', function () { | |
acfield.val($(this) | |
.text()); | |
acchosen = null; | |
}); | |
// Hide on blur (pause for click) | |
acfield.on('blur', function () { | |
setTimeout(function () { | |
acreveal.hide(); | |
}, 200); | |
acchosen = null; | |
}); | |
}); | |
}; | |
})(jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment