Incorrect operation of the jquery-ui autocomplete - javascript

Immediately after reloading the page when you enter a single character in the input, nothing happens. when you enter the following characters begins to complement.
Get data
`function getData(data, callback) {
$.ajax({
url: "myUrl" + encodeURIComponent(data),
method: "GET",
dataType: "JSON",
success: callback
})
}`
Callback function
`function autocompleteInput () {
var dataInput = $("#myInput").val();
function success(data) {
var dataArr = [];
for (var i = 0; i < data.data.length; i++) {
dataArr.push(data.data[i].name);
}
$("#myInput").autocomplete({
source: brokersNameArr,
delay: 500,
minLength: 1
})
getData(dataInput, success);
}`
Use in html
$("#myInput").keyup($.throttle(200, autocompleteInput));

Would suggest the following:
var dataArr = [];
$("#myInput").autocomplete({
source: function(req, resp){
$.getJSON("myurl?" + req.term, function(results){
$.each(results.data, function(k, r){
dataArr.push(r.name);
});
resp(results);
});
},
delay: 500,
minLength: 1
});
You might also want to review: http://jqueryui.com/autocomplete/#multiple-remote
Using a Function for source will give you the ability to manage how the data is sent and received.
Function: The third variation, a callback, provides the most flexibility and can be used to connect any data source to Autocomplete, including JSONP. The callback gets two arguments:
A request object, with a single term property, which refers to the value currently in the text input. For example, if the user enters "new yo" in a city field, the Autocomplete term will equal "new yo".
A response callback, which expects a single argument: the data to suggest to the user. This data should be filtered based on the provided term, and can be in any of the formats described above for simple local data. It's important when providing a custom source callback to handle errors during the request. You must always call the response callback even if you encounter an error. This ensures that the widget always has the correct state.
Hope this helps.

Related

Autocomplete search taking too long to retrieve data from server

I have an AJAX autocomplete search in user control page, which gets called on document.ready. In that we makes an AJAX call to web service which takes the data (which is approx. 90,000) from the database, insert data into cache, returns the data to JavaScript and added to the array.
At first it takes the data from the database and after inserting the data into cache, every time it takes the data from cache. When we type something on textbox it matches the text of textbox with array and displays the list. To get 90,000 items from a stored procedure, it takes 2 sec in local server.
But on live server it takes approx 40 secs to take data from a stored procedure. Also for taking data from cache it takes the same time. How can I reduce the time and increase the performance?
AJAX call:
var locationSearchListData = [];
var termTemplate = "<span class='ui-autocomplete-term'>%s</span>";
var postData = '{cultureId : "DE"}';
// Ajax call to run webservice's methods.
$.ajax({
url: "/asmx/SearchLocations.asmx/GetAutoCompleteSearchLocations",
type: "POST",
data: postData,
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (responseData) {
if (responseData != undefined && responseData != null && responseData.d.length > 0) {
for (i = 0; i < responseData.d.length; i++) {
// Add resopnse data in location search lis, this list is used as a source for autocomplete textbox.
locationSearchListData.push({
label: responseData.d[i].locationData,
latitude: responseData.d[i].latitude,
longitude: responseData.d[i].longitude
});
}
}
Web-service:
[ScriptMethod]
[WebMethod(Description = "Provides instant search suggestions")]
public List<GeoLocationObject> GetAutoCompleteSearchLocations(string cultureId)
{
SqlDatabase database = new SqlDatabase(WebConfigurationManager.ConnectionStrings["MasterDB"].ConnectionString);
string databaseName = WebConfigurationManager.AppSettings["databaseName"];
// Key to identify location search data in cache
string cacheKey = "auto_complete_result";
// List to store locations
List<GeoLocationObject> lstGeolocationObject = new List<GeoLocationObject>();
// If location data is present in cache then return data from cache.
if (Context.Cache[cacheKey] is List<GeoLocationObject>)
{
return Context.Cache[cacheKey] as List<GeoLocationObject>;
}
else // If data is not present in cache, get data from db and add into cache.
{
// Call method GetAutoCompleteSearchLocations of LocationManager to get list of geo location object.
lstGeolocationObject = LocationManager.GetAutoCompleteSearchLocations(database, cultureId);
// Checking if lstGeolocationObject is not null
// If its not null then adding the lstGeolocationObject in the cache
if (lstGeolocationObject.Count > 0)
{
// Add locationdata in cache.
// Removed sqlcache dependency.
Context.Cache.Insert(cacheKey,
lstGeolocationObject,
null,
Cache.NoAbsoluteExpiration,
Cache.NoSlidingExpiration,
CacheItemPriority.NotRemovable,
null);
}
// Return geolocation data list
return lstGeolocationObject;
}
} // GetAutoCompleteSearchLocations
The main intention of autocomplete facility is to narrow down the search and bring to front only the nearly matching records to ease the user to select the exact record he wants. Try adding a debounceTime() if possible.
Other options are to fine tune the sql query, implementing the server side paging and checking the page render time in browser.
Sorry for my late reply.
Thanks all for helping me to find out the solution.
We have solved the issue by doing some changes in ajax call. We send the search text as:
// set auto complete textbox
$("#<%= txtOrtOderPlz.ClientID%>").autocomplete({
// Set required minimum length to display autocomplete list.
minLength: 3,
// Set source for textbox, this source is used in autocomplete search.
source: function (request, response) {
// Ajax call to run webservice's methods.
$.ajax({
url: "/asmx/SearchLocations.asmx/GetAutoCompleteSearchLocations",
type: "POST",
data: '{ searchText :\'' + request.term + '\' }',
dataType: "json",
contentType: "application/json; charset=utf-8",
Success: function (responseData) {
response(responseData.d);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
}
});
},
Every time we search anything, it takes the search text and call web services, send the search text to SP, get the data from SP and show in autocomplete search.

Multiple ajax calls fired simultaneously not working properly

I created a site which load every few seconds data from multiple sources via AJAX. However I experience some strange behavior. Here is the code:
function worker1() {
var currentUrl = 'aaa.php?var=1';
$.ajax({
cache: false,
url: currentUrl,
success: function(data) {
alert(data)
},
complete: function() {
setTimeout(worker1, 2000);
}
});
}
function worker2() {
var currentUrl = 'aaa.php?var=2';
$.ajax({
cache: false,
url: currentUrl,
success: function(data) {
alert(data)
},
complete: function() {
setTimeout(worker2, 2000);
}
});
}
The problem is that many times, one of the workers returns NaN. If I change the frequency of calls for, lets say, 2000 and 1900, then everything is working ok and I got almost no NaN results. When those frequencies are same, I get over 80% NaN results for one of the calls. It seems like the browser cannot handle two requests called at exact same time. I use only those two workers, so the browser shouldn't be overloaded by AJAX requests. Where is the problem?
Note that the aaa.php works with the mySql database and do some simple queries base on parameters in url.
All you need is $.each and the two parameter form of $.ajax
var urls = ['/url/one','/url/two', ....];
$.each(urls, function(i,u){
$.ajax(u,
{ type: 'POST',
data: {
answer_service: answer,
expertise_service: expertise,
email_service: email,
},
success: function (data) {
$(".anydivclass").text(data);
}
}
);
});
Note: The messages generated by the success callback will overwrite
each other as shown. You'll probably want to use
$('#divid').append() or similar in the success function.
Maybe, don't use these workers and use promises instead like below? Can't say anything about the errors being returned though without looking at the server code. Below is working code for what it looks like you are trying to do.
This is a simple example but you could use different resolvers for each url with an object ({url:resolverFunc}) and then iterate using Object.keys.
var urls = [
'http://jsonplaceholder.typicode.com/users/1',
'http://jsonplaceholder.typicode.com/users/2',
'http://jsonplaceholder.typicode.com/users/3',
'http://jsonplaceholder.typicode.com/users/4',
'http://jsonplaceholder.typicode.com/users/5',
'http://jsonplaceholder.typicode.com/users/6',
'http://jsonplaceholder.typicode.com/users/7'
]
function multiGet(arr) {
var promises = [];
for (var i = 0, len = arr.length; i < len; i++) {
promises.push($.get(arr[i])
.then(function(res) {
// Do something with each response
console.log(res);
})
);
}
return $.when(promises);
}
multiGet(urls);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

JavaScript: search user input in number of arrays

I am working with D3js library. On the web page, there is a search box which user can input their parameter. I receive arrays of data via Ajax post to my database. Following is the code:
..........
var aa;
var bb;
$(function(){
$.ajax({
type: "POST",
url: "http://localhost:7474/db/data/transaction/commit",
accepts: {json: "application/json"},
dataType: "json",
contentType: "application/json",
data: JSON.stringify(query), //query is somewhere above the code
//pass a callback to success to do something with the data
success: function (data) {
aa = data.results[0].data;
aa.forEach(function (entry) {
passVar(entry.row[0].name)
});}}
);
});
function passVar(smth){
bb =[smth];
console.log (bb);
//Should search the user input..........
}
//if the user input matches, filter function should run.........
function filterData() {
var value = d3.select("#constraint")[0][0].value;
inputValue = value;
............
}
As the result of console.log(bb)I receive the following on console:
["Direct Digital Control System"]
["Fire Protection"]
["HVAC Cooling- Waterside"]
["HVAC Heating- Waterside"]
["HVAC System"]
["HVAC-01"]
["HVAC-02"]
What I want to do:
If the user input match with one of the results in var bb, then program should run function filterdata() {....for querying. If not, don't do anything.
How should I write the code to make the search and run the other function? Thanks for the any help/suggestion.
You can loop through the array and find whether the user input is equals to the current index value of the array. if equals you can call your function and break the loop since no need to loop further more.
for(int i=0; i<bb.length; i++){
if(bb[i] == userInput){
filterdata();
break;
}
}

multiple ajax async not in order and need synchronous behavior

Sorry, My first language is not English. I am not sure that if I explain my question properly.
My code is like a main function have two ajax functions (Use ajax function to get foursquare API)
main(){
ajax1();
ajax2();
all other codes
}
the ajax2() function has to get result from ajax1() as input and then return result(actually result was pushed in to global array).
all other codes should be processed after two ajax functions are finished. I tried the asyn: false but it is not working. My html file include newest jquery like this
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js" ></script>
I try the jquery function $.when().done() function and the first ajax works. However, the second ajax() function was in the for loop. The for loop will destroy the mechanism of $.when().done() function:
first ajax: in firstjson function
Second ajax: in transfer function
function firstjson(tmpName,tmpLoc,PhotoJson,foursq){
return $.ajax({
type: 'GET',
url: foursq,
dataType: 'jsonp',
success: function(json) {
for (i = 0; i < 3; i++) {
var resultname = json['response']['venues'][i].name;
var resultlocation = json['response']['venues'][i].location;
var resultlat = resultlocation.lat;
var resultlng = resultlocation.lng;
var tmpmarker = new google.maps.LatLng(resultlat,resultlng)
tmpName.push(resultname);
tmpLoc.push(tmpmarker);
var resultid = json['response']['venues'][i].id;
var tmpPhotoJason = 'https://api.foursquare.com/v2/venues/'+ resultid +'/photos?';
PhotoJson.push(tmpPhotoJason);
}
}
});
}
function transfer(PhotoJson,PhotoURL){
for (i = 0; i < 3; i++) {
return $.ajax({
type: 'GET',
url: PhotoJson[i],
dataType: 'jsonp',
success: function(json) {
resultphoto = json['response']['photos']['items'];
photoprefix = resultphoto[i].prefix;
photopresuffix = resultphoto[i].suffix;
photourl = photoprefix+"150x150" + photopresuffix;
PhotoURL.push(photourl);
}
});
}
}
$.when(firstjson(tmpName,tmpLoc,PhotoJson,foursq)).done(function(){
alert("test1");
$.when(transfer(PhotoJson,PhotoURL).done(function(){
console.log(PhotoURL);
all other codes!!!!
});
});
//PhotoURL is global array
So the first "when" function work properly. alert("test1") work after the firstjson was done. However the for loop inside transfer function will break the when function. How can I fix the problem. Please help me. I will appreciate you can give me any related information. Thanks!!!
This will execute ajax2 after ajax1
function anotherMethod(){
//Here you do all that you want to do after the last $ajax call
}
main(){
firstjson(tmpName,tmpLoc,PhotoJson,foursq)
.then(transfer(PhotoJson,PhotoURL))
.then(anotherMethod);
}
As you are returning a promise from the first with the "return $ajax..."
So you organice your code like this:
in methods with ajax calls you return the call as you are doing now
return $.ajax();
that returns a promise that you chain.
And you put what you want to do in another method so you call it in the last "then".
Non-Blocking Example
You should use non-blocking code. You can turn async off (async: false) but this can easily be done in a non-blocking manor using callback functions.
function main(){
$.ajax({ // First ajax call (ajax1)
url: "first/ajax/url",
type: "GET", // POST or GET
data: {}, // POST or GET data being passed to first URL
success: function(x){ // Callback when request is successfully returned
// x is your returned data
$.ajax({ // Second ajax call (ajax2)
url: "second/ajax/url",
type: "GET", // POST or GET
data: {
thatThing: x
}, // POST or GET data passed to second URL
success: function(y){
// y is your second returned data
// all other codes that use y should be here
}
});
}
})
}
This would be the non-blocking approach, nest your function within "success" callback functions. Nest ajax2 within ajax1's "success" callback to ensure that ajax2 is not executed before ajax1 has returned and nest your "all other codes" inside the "success" callback of ajax2 to ensure they are not executed until ajax2 has returned.
Blocking Example
If you absolutely must (please avoid at all cost) you can disable async which will block all JavaScript code from executing until the ajax has returned. This may cause your browser to temporarily freeze until the ajax request has returned (depending on the browser).
function main(){
var x = ajax1();
var y = ajax2(x);
window["y"] = y; // push to global as you requested but why?
// All other codes that can now use y
}
function ajax1(){
var x;
$.ajax({
url: "first/ajax/url",
async: false,
type: "GET", // POST or GET,
data: {}, // POST or GET data being passed to first URL
success: function(r){x=r}
});
return x;
}
function ajax2(x){
var y;
$.ajax({
url: "second/ajax/url",
async: false,
type: "GET", // POST or GET,
data: {
thatThing: x
}, // POST or GET data being passed to second URL
success: function(r){y=r}
});
return y;
}
Once again I stress, try not to disable async that will cause your code to block and is BAD code. If you absolutely 100% have to for some reason than than it can be done but you should attempt to learn how to write non-blocking code using callbacks as the first example does.
Social Network Example
Now I'll do an example of an ajax call to get an array of your friends IDs, and then a series of ajax calls to get each of your friends profiles. The first ajax will get the list, the second will get their profiles and store then, and then when all profiles have been retrieved some other code can be ran.
For this example, the url https://api.site.com/{userID}/friends/ retrieves an Object with a list of friends IDs for a particular user, and https://api.site.com/{userID}/profile/ gets any users profile.
Obviously this is a simplified api as you will probably need to first establish a connection with a apikey and get a token for this connection and the token would likely need to be passed to the api uris but I think it should still illustrate the point.
function getFriends(userID, callback){
$.ajax({
url: "https://api.site.com/"+userID+"/friends/",
success: function(x){
var counter = 0;
var profiles = [];
for(var i=0;i<x.friendIDs.length;i++){
$.ajax({
url: "https://api.site.com/"+x.friendIDs[i]+"/profile/",
success: function(profile){
profiles.push(profile);
counter++;
if(counter == x.friendIDs.length) callback(profiles);
}
});
}
}
});
}
getFreinds("dustinpoissant", function(friends){
// Do stuff with the 'friends' array here
})
This example is "Non-blocking", if this example were done in a "blocking" way then we would ask for 1 friends profile, then wait for its response, then request the next and wait and so on. If we had hundreds of friends you can see how this would take a very long time for all ajax calls to complete. In this example, which is non-blocking, all requests for profiles are made at the same time (within 1ms) and then can all be returned at almost exactly the same time and a counter is used to see if we have gotten responses from all the requests. This is way way way faster than using the blocking method especially if you have lots of friends.

Wait for AJAX before continuing through separate function

Alright... at 2am, this is where I draw the line. Help... before my laptop ends up going out the window. :)
I've tried using setTimer, callbacks, and everything else I can think of (along with a few other Stackoverflow hints of course). I've stripped out everything so I'm leaving just the base code.
What I'm looking to do is call parseRow() and before it saves the record at the end, I need to grab the associated Category (via AJAX); however, it blows right past it so category is always "undefined".
function parseRow(row){
var rowArray = row.trim().split(",");
var date = rowArray[0];
var checknum = rowArray[1];
var payee = rowArray[2];
var memo = rowArray[3];
var amount = rowArray[4];
//ERROR: blows right past this one and sets the category variable BEFORE ajax returns
var category = autoSelectCategory(payee);
saveRecord(date, checkNum, payee, memo, category, payment, deposit);
}
function autoSelectCategory(payee) {
var data;
$.ajax({
async: false,
url: "autoselectcategory",
dataType: "json",
data: {
string: payee
},
success: function (returnedData) {
data = returnedData;
}
});
return data;
}
AJAX stands for asynchronous. That means that in your original code, saveRecord will be executed before the client will receive the response from the server (and, depending on the $.ajax implementation, it might be before the client will send the request to the server).
Additionally, you seem to misunderstand how functions work in JS. var category = autoSelectCategory(payee); will set the category to the return value of autoSelectCategory; but the autoSelectCategory function in your code returns nothing.
From the other side, the data return value of your anonymous function could only be used by $.ajax function (and $.ajax likely ignores the success parameter return value).
Here is the code that should work:
function parseRow(row){
var rowArray = row.trim().split(",");
var date = rowArray[0];
var checknum = rowArray[1];
var payee = rowArray[2];
var memo = rowArray[3];
var amount = rowArray[4];
autoSelectCategory(payee, function (category) {
saveRecord(date, checkNum, payee, memo, category, payment, deposit);
});
}
function autoSelectCategory(payee, callback) {
$.ajax({
async: false,
url: "autoselectcategory",
dataType: "json",
data: {
string: payee
},
success: callback
});
}
Do not use async: false option. It's a pure evil (blocks all scripts in browser and even other tabs!) and it's deprecated since jQuery 1.8. You should use callbacks as it was always meant to be.
function parseRow(row) {
/* the other code */
autoSelectCategory(payee, function() {
saveRecord(date, checkNum, payee, memo, category, payment, deposit);
});
}
function autoSelectCategory(payee, callback) { // <---- note the additional arg
$.ajax({
url: "autoselectcategory",
dataType: "json",
data: {
string: payee
},
success: function(res) {
/* the other code */
callback();
}
});
}

Categories

Resources