Jean O.P. Jean O.P. - 5 months ago 17
JSON Question

jQuery autocomplete - Fill input regardless if JSON result is not yet ready

I have got a large database of products that i search through with an input that uses jQuery

.autocomplete()
function. The products are being searched by name or ID. When the list with items appear, the user can select a product from the list to populate the input with the product-ID and some of the other fields with known predefined values like 'taxes' or 'productName'. Layout is like this:

HTML Code

<input type="text" id="productID" />
<input type="text" id="productName" />
<input type="text" id="quantity" />
<input type="text" id="taxes" />

... and more relative inputs

<input type="text" id="price" />
<!-- add product to cart -->
<input type="submit" value="Add to cart" />


The meaning of the form is to insert products to a certain shopcart while manually filling unknown or alternating known fields.

Now the thing is that I know many product-ID's by memory and can type them straight away, so I can quickly adjust the necessary fields and hit 'ENTER' to insert the product in the cart. The problem is that when I leave the
.autocomplete()
field, the list with results disappears and doesn't select a product.

My jQuery

var cache = {};
$("#productID").autocomplete({
minLength: 1,
autoFocus: true,
source: function (request, response) {
var term = request.term; // search-term
// check if the term is already cached
if (term in cache) {
response(cache[ term ]); // return cached result
return;
}
// get results from remote script
$.getJSON("/autocomplete.php", request, function (data) {
cache[ term ] = data; // cache the result for this term
response(data);
});
},
select: function (event, ui) {
// pre-populate fields of the product
$("#productName").val(ui.item.name);
$("#taxes").val(ui.item.taxes);
$("#price").val(ui.item.price);
}
};


Here, I need to wait for the response to show and then press 'TAB' to select the product.

Is there any way to let the JSON response continue when I 'TAB' out off the field, and that it selects the first item in the list? As this is pretty straight-forward work, I don't like waiting for the response to show everytime to select a product.

EDIT



Found the solution thanks to @raduation! Here is what I did:

// first altered the autocomplete-select to point to a Js-function
var cache = {};
$("#productID").autocomplete({
minLength: 1,
autoFocus: true,
source: function (request, response) {
var term = request.term; // search-term
// check if the term is already cached
if (term in cache) {
response(cache[ term ]); // return cached result
return;
}
// get results from remote script
$.getJSON("/autocomplete.php", request, function (data) {
cache[ term ] = data; // cache the result for this term
response(data);
});
},
select: function (event, ui) {
// pre-populate fields of the product
selectValueAutocomplete(ui.item, $(this));
}
};

// function to insert item's values in the fields
function selectValueAutocomplete(item, input)
{
input.val(item.value);
$("#productName").val(item.name);
$("#taxes").val(item.taxes);
$("#price").val(item.price);
}


And I added Eventlisteners to check what to do when focussed or not:

$(document)
.on("focusout", "#productID", function() {
$(this).addClass("selectFirst");
})
.on("focus", "#productID", function() {
$(this).removeClass("selectFirst");
}) // Here I invoke the jQuery.autocomplete()'s response method
.on("autocompleteresponse", "#productID", function( event, ui ) {
if($(this).hasClass("selectFirst"))
{ // select first item from response
selectValueAutocomplete(ui.content[0], $(this));
}
});

Answer

Add a key event listener on the text input field, that listens for a Tab key. Once the Tab key is pressed, set a property on the text input that means "populate with first product match". For example: $('#productId').prop('populateFirst',true);

Then, in your getJSON callback function, check for the presence of this property, and populate the first product. After this is done (or if there is an ajax error), delete the property, so it doesn't interfere with the next use of the autocomplete.