Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Small bugfixes & improvements! #14

Closed
wants to merge 1 commit into from

2 participants

@pehrlich
  • esc now acts as enter, allowing the menu to be closed -- this probably needs further tweaking to work when forceSelect is true
  • made it so that forceSelect==false works, allowing any input
  • a filter can return false, canceling the request
@laktek laktek closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 4, 2012
  1. @pehrlich

    fix forceSelect==false to allow any value, bind esc key to close the …

    pehrlich authored
    …ul, allow filter to return false to cancel
This page is out of date. Refresh to see the latest.
Showing with 66 additions and 61 deletions.
  1. +66 −61 jquery.smart_autocomplete.js
View
127 jquery.smart_autocomplete.js
@@ -1,9 +1,9 @@
/**
- * Smart Auto Complete plugin
- *
+ * Smart Auto Complete plugin
+ *
* Copyright (c) 2011 Lakshan Perera (laktek.com)
* Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
- *
+ *
*/
/*
@@ -21,18 +21,18 @@
Better to enable this option, if you want autocomplete field to behave similar to a HTML select field. (Check Example 2 in the demo)
(default: false)
typeAhead: (boolean) If set to true, it will offer the best matching result in grey within the field; that can be auto-completed by pressing the right arrow-key or enter.
- This is similar to behaviour in Google Instant Search's query field (Check Example 3 in the demo)
+ This is similar to behaviour in Google Instant Search's query field (Check Example 3 in the demo)
(default: false)
source: (string/array) you can supply an array with items or a string containing a URL to fetch items for the source
- this is optional if you prefer to have your own filter method
+ this is optional if you prefer to have your own filter method
filter: (function) define a custom function that would return matching items to the entered text (this will override the default filtering algorithm)
should return an array or a Deferred object (ajax call)
- parameters available: term, source
+ parameters available: term, source
resultFormatter: (function) the function you supply here will be called to format the output of an individual result.
should return a string
- parameters available: result
+ parameters available: result
resultsContainer: (selector) to which element(s) the result should be appended.
- resultElement: (selector) references to the result elements collection (e.g. li, div.result)
+ resultElement: (selector) references to the result elements collection (e.g. li, div.result)
Events:
keyIn: fires when user types into the field (parameters: query)
@@ -48,10 +48,10 @@
*/
(function($){
- $.fn.smartAutoComplete = function(){
+ $.fn.smartAutoComplete = function(){
if(arguments.length < 1){
- // get the smart autocomplete object of the first element and return
+ // get the smart autocomplete object of the first element and return
var first_element = this[0];
return $(first_element).data("smart-autocomplete")
}
@@ -66,7 +66,7 @@
}
var default_options = {
- minCharLimit: 1,
+ minCharLimit: 1,
maxResults: null,
delay: 0,
disabled: false,
@@ -76,32 +76,32 @@
resultFormatter: function(r){ return ("<li>" + r + "</li>"); },
- filter: function(term, source){
+ filter: function(term, source){
var context = this;
var options = $(context).data('smart-autocomplete');
-
+
//when source is an array
if($.type(source) === "array") {
// directly map
var results = default_filter_matcher(term, source, context);
- return results;
+ return results;
}
//when source is a string
else if($.type(source) === "string"){
// treat the string as a URL endpoint
// pass the query as 'term'
-
- return $.Deferred(function(dfd){
+
+ return $.Deferred(function(dfd){
$.ajax({
url: source,
data: {"term": term},
dataType: "json"
}).success( function(data){
- dfd.resolve( default_filter_matcher(term, data, context) );
- });
+ dfd.resolve( default_filter_matcher(term, data, context) );
+ });
}).promise();
-
+
}
},
@@ -113,7 +113,7 @@
var type_ahead_field = $(this.context).prev(".smart_autocomplete_type_ahead_field");
$(this.context).css({ background: type_ahead_field.css("background") });
type_ahead_field.remove();
-
+
//clear results div
$(this.resultsContainer).html("");
},
@@ -131,7 +131,7 @@
//define the default events
$.event.special.keyIn = {
- setup: function(){ return false; },
+ setup: function(){ return false; },
_default: function(ev){
var context = ev.target;
@@ -151,6 +151,9 @@
//call the filter function with delay
setTimeout(function(){
$.when( filter.apply(options, [query, options.source]) ).done(function( results ){
+ if(results == false){
+ return $(context);
+ }
//do the trimming
var trimmed_results = (options.maxResults > 0 ? results.splice(0, options.maxResults) : results);
@@ -174,7 +177,7 @@
if(options.disabled)
return false;
- //clear all previous results
+ //clear all previous results
$(context).smartAutoComplete().clearResults();
//save the raw results
@@ -199,24 +202,24 @@
//trigger results ready event
$(context).trigger('showResults', [results]);
- }
+ }
};
$.event.special.showResults = {
setup: function(){ return false },
- _default: function(ev){
+ _default: function(ev){
var context = ev.target;
var options = $(context).data("smart-autocomplete");
var results_container = $(options.resultsContainer);
//event specific data
- var raw_results = ev.smartAutocompleteData.results;
+ var raw_results = ev.smartAutocompleteData.results;
//type ahead
if(options.typeAhead && (raw_results[0].substr(0, $(context).val().length) == $(context).val()) ){
- var suggestion = raw_results[0]; //options.typeAheadExtractor($(context).val(), raw_results[0]);
-
+ var suggestion = raw_results[0]; //options.typeAheadExtractor($(context).val(), raw_results[0]);
+
//add new typeAhead field
$(context).before("<input class='smart_autocomplete_type_ahead_field' type='text' autocomplete='off' disabled='disabled' value='" + suggestion + "'/>");
@@ -243,17 +246,17 @@
$(context).trigger('itemFocus', results_container.children()[options.currentSelection]);
}
- //show the results container after aligning it with the field
+ //show the results container after aligning it with the field
if(results_container){
if(options.alignResultsContainer){
- results_container.css({
+ results_container.css({
position: "absolute",
- top: function(){ return $(context).offset().top + $(context).height(); },
- left: function(){ return $(context).offset().left; },
- width: function(){ return $(context).width(); },
+ top: function(){ return $(context).offset().top + $(context).height(); },
+ left: function(){ return $(context).offset().left; },
+ width: function(){ return $(context).width(); },
zIndex: 1000
})
- }
+ }
results_container.show();
}
@@ -263,23 +266,23 @@
$.event.special.noResults = {
setup: function(){ return false },
- _default: function(ev){
+ _default: function(ev){
var context = ev.target;
var options = $(context).data("smart-autocomplete");
var result_container = $(options.resultsContainer);
if(result_container){
//clear previous results
- options.clearResults();
+ options.clearResults();
}
}
};
- $.event.special.itemSelect = {
+ $.event.special.itemSelect = {
setup: function(){ return false },
- _default: function(ev){
+ _default: function(ev){
var context = ev.target;
var options = $(context).data("smart-autocomplete");
@@ -289,14 +292,14 @@
//get the text from selected item
var selected_value = $(selected_item).text() || $(selected_item).val();
//set it as the value of the autocomplete field
- $(context).val(selected_value);
+ // if selected_value is undefined, forceSelect will blank the field
+ if (options.forceSelect || selected_value) {
+ $(context).val(selected_value);
+ }
//set item selected property
options.setItemSelected(true);
- //set number of current chars in field
- options.originalCharCount = $(context).val().length;
-
//trigger lost focus
$(context).trigger('lostFocus');
}
@@ -305,7 +308,7 @@
$.event.special.itemFocus = {
setup: function(){ return false },
- _default: function(ev){
+ _default: function(ev){
//event specific data
var item = ev.smartAutocompleteData.item;
@@ -314,10 +317,10 @@
}
};
- $.event.special.itemUnfocus = {
+ $.event.special.itemUnfocus = {
setup: function(){ return false },
- _default: function(ev){
+ _default: function(ev){
//event specific data
var item = ev.smartAutocompleteData.item;
@@ -329,16 +332,16 @@
$.event.special.lostFocus = {
setup: function(){ return false },
- _default: function(ev){
+ _default: function(ev){
var context = ev.target;
var options = $(context).data("smart-autocomplete");
- //if force select is selected and no item is selected, clear currently entered text
+ //if force select is selected and no item is selected, clear currently entered text
if(options.forceSelect && !options.itemSelected)
$(options.context).val("");
//clear results
- options.clearResults();
+ options.clearResults();
//hide the results container
if(options.resultsContainer)
@@ -351,7 +354,7 @@
var passed_options = arguments[0];
- return this.each(function(i) {
+ return this.each(function(i) {
//set the options
var options = $.extend(default_options, $(this).data("smart-autocomplete"), passed_options);
//set the context
@@ -410,11 +413,11 @@
$(options.context).trigger('itemFocus', [ result_suggestions[current_selection] ] );
}
-
+
}
//right arrow & enter key
- else if(ev.keyCode == '39' || ev.keyCode == '13'){
+ else if(ev.keyCode == '39' || ev.keyCode == '13' || ev.keyCode == '27'){
var type_ahead_field = $(options.context).prev('.smart_autocomplete_type_ahead_field');
if(options.resultsContainer && $(options.resultsContainer).is(':visible')){
var current_selection = options.currentSelection;
@@ -431,15 +434,18 @@
else {
var current_char_count = $(options.context).val().length;
//check whether the string has modified
- if(options.originalCharCount == current_char_count)
+ if(options.originalCharCount == current_char_count){
return;
+ }else{
+ options.originalCharCount = current_char_count;
+ }
//check minimum number of characters are typed
if(current_char_count >= options.minCharLimit){
- $(options.context).trigger('keyIn', [$(this).val()]);
+ $(options.context).trigger('keyIn', [$(this).val()]);
}
else{
- if($(options.resultsContainer).is(':visible')){
+ if($(options.resultsContainer).is(':visible')){
options.currentSelection = null;
$(options.context).trigger('lostFocus');
}
@@ -449,14 +455,13 @@
});
$(this).focus(function(){
- //if the field is in a form capture the return key event
+ //if the field is in a form capture the return key event
$(this).closest("form").bind("keydown.block_for_smart_autocomplete", function(ev){
var type_ahead_field = $(options.context).prev('.smart_autocomplete_type_ahead_field');
- if(ev.keyCode == '13'){
+ if(ev.keyCode == '13' || ev.keyCode == '27'){ //enter, esc keys
if(options.resultsContainer && $(options.resultsContainer).is(':visible')){
var current_selection = options.currentSelection;
var result_suggestions = $(options.resultsContainer).children();
-
$(options.context).trigger('itemSelect', [ result_suggestions[current_selection] ] );
return false;
}
@@ -468,7 +473,7 @@
});
if(options.forceSelect){
- $(this).select();
+ $(this).select();
}
});
@@ -491,7 +496,7 @@
options['currentSelection'] = $(this).prevAll().length;
$(options.context).trigger('itemFocus', [this] );
-
+
});
$(options.resultsContainer).delegate(options.resultElement, 'mouseleave.smart_autocomplete', function(){
@@ -506,7 +511,7 @@
//bind plugin specific events
$(this).bind({
keyIn: function(ev, query){ ev.smartAutocompleteData = {'query': query }; },
- resultsReady: function(ev, results){ ev.smartAutocompleteData = {'results': results }; },
+ resultsReady: function(ev, results){ ev.smartAutocompleteData = {'results': results }; },
showResults: function(ev, results){ ev.smartAutocompleteData = {'results': results } },
noResults: function(){},
lostFocus: function(){},
@@ -515,6 +520,6 @@
itemUnfocus: function(ev, item){ ev.smartAutocompleteData = {'item': item }; }
});
});
-
+
}
-})(jQuery);
+})(jQuery);
Something went wrong with that request. Please try again.