I have stolen/found/used/written and edited the following widget of jQuery for a auto-completing dropdown.
(function($) {
$.widget("ui.comboboxGemeenten", {
_create: function() {
var focushelper = false;
var lastTerm;
var self = this;
var select = this.element.hide();
var input = $("<input>")
.insertAfter(select)
.width(300)
.autocomplete({
source: function(request, response) {
var jsonbox = { gem_query: request.term };
lastTerm = request.term;
$.post("/" + $.trim(window.location.pathname.substr(1, 9)) + "/Gemeenten/FilterInstGem/", jsonbox, function donedit(data) {
//alert("iets");
if (data.succes == true && data.lastTerm == lastTerm) {
//alert(textlength);
//alert(data.lesplaatsen);
response($.map(data.gemeenten, function(item) {
return {
id: item,
// label: (item.Lpl_Gemeente == null ? "" : item.Lpl_Gemeente) + " - " + item.Lpl_Instelling,
value: item
}
}));
} else {
// alert("slecht");
}
}, "json");
},
delay: 0,
change: function(event, ui) {
if (!ui.item) {
// remove invalid value, as it didn't match anything
$(this).val("");
return false;
}
//alert(ui.item.id);
select.val(ui.item.id);
self._trigger("selected", event, {
item: select.find("[value='" + ui.item.id + "']")
});
},
focus: function() {
focushelper = true;
},
minLength: 2
})
.addClass("ui-widget ui-widget-content ui-corner-left")
.focus(function() { //if it is default value, remove it.
if (select.val() == "" && !focushelper) {
//alert(select.val());
$(input).val("");
}
})
.val(select.find("option:selected").text()); //return selected value for editing
}
});
})(jQuery);
The problem was that I return a long list of items, and when I write inside the input field to filter, like
"gen" it would do a post for "g" for "ge" and for "gen" because it posts on every change. The problem was that the last return of the list was not always for "gen" but sometimes for "ge" so, my result was not correct.
using a delay
did not change anything.
using minlength
does not matter, once it's more than the minlength
the problem occurs again.
so what did I do? I used var lastTerm
to check on receiving my list, if this result is for the last term written, and not for one in the middle.
this does fix my problem, but it's not the nicest thing.
Is there a way to just halt the post, so I don't waste a load of server resources since the results for not the last term, are discarded anyway.
the MVC part:
[HttpPost]
public ActionResult FilterInstGem(string gem_query) {
List<string> lpls = _db.InstellingAdressens.Where(l => l.GEMEENTE.Contains(gem_query)).Select(q => q.GEMEENTE).Distinct().OrderBy(q => q).ToList();
return Json(new { succes = true, lastTerm = gem_query, gemeenten = lpls });
}
the total thing looks like: http://jqueryui.com/demos/autocomplete/#combobox