Assign Ajax controller call's result to select2 using pagination - javascript

I am having an issue with assigning large set of data to jQuery select2 dropdown. I have an Ajax controller call which returns customer data (id & name) and assign it to a select2 dropdown box inside success call of Ajax. The problem is I have around 77k customer records and because of that select2 is not handling it well and browser hangs after few seconds.
As a solution I came across pagination in select2 and tried quite a few examples but none of them are working in my scenario. I am loading all customer data at once because I don't want to make frequent queries to search for customer record.
I have a javascript function which gets the data from controller (Ruby) and assign it to select dropdown using select2.
function updateCustomerList(teamId, customerSelectInput) {
if(teamId !== undefined) {
$.ajax({
dataType: "json",
url: "/team/customers",
data: {team_id: teamId},
success: function(data) {
$(customerSelectInput).select2({
createSearchChoice: createSearchChoiceFunction,
placeholder: "Search for customer"],
data: data
});
},
error: function(jqXHR, textStatus, errorThrown) {
displayError(jqXHR.responseText)
}
});
}
var createSearchChoiceFunction = function(term, data) {
if ( $(data).filter( function() {
return this.text.localeCompare(term)===0;
}).length===0) {
return {id:term, text:term};
}
}
}
FYI Team controller method "customers" is just making a query to customer collection and gets all customer by team id and return the result as json object.
Any kind of help/guidance would be appreciated!

I have around 77k customer records and because of that select2 is not handling it well and browser hangs after few seconds.
Well, that happened because all data is loading in memory, you will see that all your RAM go off. In the DOM, many <options> are created, and chrome it will be happy eating all your memory.
I think you can get better results with Algolia API and Autocomplete.js which is
a JavaScript library that adds a fast and fully-featured auto-completion menu to your search box displaying results "as you type".
https://github.com/algolia/autocomplete.js

Related

Datatables colReorder saving WITHOUT statesave

I am using datatables and am using colReorder and need to save the state of the columns without using statesave(I am not allowed to use localcache). I do however have a preference table in my database for storing this kind of information in JSON format.
I have looked at colReorder.order() which looks like what I need to get the order.
What I'm thinking so far is on a column change, call colReorder.order() and place that returned array in my preferences table and then on re-initialization use that to re-order the table.
So my question/what I need help on is this: On a change of the colOrder, I need to save the order they're in and update my preferences. How do I do this? I can't seem to find "where" to place the colReorder.order(). I haven't seen an onChange() for datatables or even sure if that would be the best way to approach this
EDIT: David's answer is the ideal solution, however not applicable in my situation due to code already existing and laziness.
My solution/work-around that I found was to stringify and save details.mapping from within this function to my preferences and on initialization of my table I use colReorder.order(savedArray[],true).
Leaving it in case anyone finds themselves in the situation I was in.
Actually DataTables provide methods for storing and retrieving state to and from an alternative location. Look at stateSaveCallback and stateLoadCallback.
I do however have a preference table in my database for storing this
kind of information in JSON format
Then you just need to fill out the "blanks". Lets assume you have a serverside script called statesave that can store and retrieve the state by 'set' and 'get' using an unique userId. The skeleton would look like this:
$('#example').DataTable({
stateSave: true,
stateSaveCallback: function(settings, data) {
$.ajax( {
url: 'statesave',
dataType: 'json',
data: {
action: 'set',
userId: aUserId,
state: data
}
})
},
stateLoadCallback: function(settings) {
var state;
$.ajax( {
url: 'statesave',
dataType: 'json',
async: false,
data: {
action: 'get',
userId: aUserId
},
success: function(data) {
state = data
})
})
return state
}
})
It sounds like you are using the server-side processing option. If that's the case, you can add the column reorder array to the sent parameters object and save it that way.

How to use PHP variable in Jquery Ajax success request

I have page which shows number of routes. User click one and it sends an ajax request and save the selected route in database.
On the same page in different tab, I am running query which gets related information of the selected route. So i have Where clause in my query.
The problem is how I can feed in the ID of selected route to Where clause in my query in different tab
Here is code.
JQuery - When user click/select the route
$(document).ready(function () {
// capture the ID of clicked route
$(".collection-routeselection").click( function(){
route_id = $(this).attr("value");
jQuery.ajax({
url: '../data/collecting.php?action=route-selection?routeid='+route_id,
type: 'POST',
dataType: 'text',
data: {'routeid':route_id},
success: function(data, textStatus, jqXHR) {
$("#tab1").removeClass("active");
$("#tab2").addClass("active");
},
error: function(jqXHR, textStatus, errorThrown){
//Display error message to user
alert("An error occured when saving the data");
}
});
});
So i send the selected route using ajax to update database table.
$insert_web1 = $mysqli_scs->prepare("INSERT INTO collectiontracking_ctr (idrou_ctr,tab_ctr,created_ctr,modified_ctr) VALUES (?,'tab1',CURRENT_TIMESTAMP,CURRENT_TIMESTAMP)");
//bind paramaters
$rouid = "";
if (isset($_POST['routeid'])) {
$rouid = $_POST['routeid'];
}
$insert_web1->bind_param("i",$rouid);
$insert_web1->execute();
All working perfect so far..now I have another query on the same page (in different tab) which should have a where clause of selected route.
My question is how can i bind the selected route id to the where clause on second query.
$select_stmt = mysqli_prepare($mysqli_scs, "SELECT id_rou,idjtp_job
FROM routes_rou
WHere id_rou =?");
I want to populate ? with selected route ID.
Thanks
Assuming the value you are interested in is route_id, you should be able to store that in a variable that is accessible to tab #2 if it isn't already. Since it's on the same page this should be trivial especially since you're using jquery.
I apologize if I'm misunderstanding the question. If so please elaborate.

Retrieve extra info from one option from autocomplete

I finally managed to retrieve a list from the available options related to the name searched from a field. Now, my goal is to retrieve some extra info when the user selects a specific option from the list. The JSON returns only the last name of the person and the user id which is an auto-increment field in the database. So I thought that I could send another JSON request to the server to actually return all the information available from the person specified from the user id. Is this considered bad practice ? Is there something alternative I am maybe missing ?
All in all, my code is here:
<script>
$(function() {
$( "#search" ).autocomplete({
delay: 0,
minLength: 2,
source: function(request, response) {
$.ajax({
url: 'search.php',
data: { term: request.term },
success: function(data) {
data = JSON.parse(data);
response($.map(data, function(item) {
return {
label: item.firstName,
value: item.firstName};
}));
}
});
}
})
});
</script>
So, how am I supposed to achieve this ?
I searched similar threads and read the doc in the official site but couldn't find a way to start. I think that somehow the results returned from the first call should be appended to DOM with anchor links, this code should be placed to the select property if I am not mistaken. But, I am very new to jquery and these web stuff and can't figure out the way.
Any help will be much appreciated. Thank you in advance.
It all depends on how much extra data you need returned.
If it's not much, then it makes sense to return the data as extra properties in a list of objects you are returning for the autocomplete results.
If you think you need too much extra data to make that viable, then in the autocomplete's select callback, you can just use the ID value to fetch all the additional info in an additional AJAX call to a second web service that returns the persons details for the passed in ID value.

search autocomplete performance with many records

I'm developing an application that is essentially a search bar. The source is a SQL table that has about 300,000 records.
Ideally, I would like to have some sort of autocomplete feature attached to this search bar. I've been looking into several ones like jquery autocomplete.
However, as one can imagine, loading all of these records as the source for the autocomplete is impossible. The performance would be abysmal.
So my question is, what is an efficient way to implement a search autocomplete feature for a source that contains thousands and thousands of records?
I thought of something like this. Essentially I'm querying the database each time they type something to get a list of results. However, querying a database via ajax doesn't seem optimal.
$( "#search" ).keyup(function( event ) {
$.ajax({
//query the database when the user begins typing, get first 1000 records
//set the source of the autocomplete control to the returned result set
});
});
You should not start querying the db on very first keyup, (not even in three-four) keyup.
For example, User is typing Albatross. When He hit 'A', if you do a Query search it will send you almost 300,000 results right away, cause every set of data must have the letter "A".
So, should ignore first few (3-5) letters. it will be better, if you can store the search keywords. Cache the top results, when 1-3 keyup you show the top search keywords. Auto complete might not be good feature for searching in a that big DB,
Last Tips for the problem, Your users use google and facebook everyday. They are more then 300,000 result for each of search in any of the applications above. Google or facebook does not show 1000 result at once. It is not good for UI Design or your Servers bandwidth. Just think, how can you categorizes and present the data to user, so that they get what they want and you keep your servers bandwidth and processing cost optimal.
always, remember the context.
Do not bind any events yourself. jQuery Autocomplete already performs bindings.
The proper way to implement this is to set the source: object to a an AJAX callback:
source: function (request, response) {
$.ajax({
url: 'yourQueryUrl.php', // <- this script/URL should limit the number of records returned
async: true,
cache: false,
type: 'GET',
data: {q: $('#searchBox').val()},
dataType: 'json',
success: function (data) {
response(data);
}
});
}
I am assuming you have added indexes to your table, if not that would be your first step, then if performance is insufficient and if your queries often repeat, you might want to look at this.
http://memcached.org/
or some other caching mechanism.
Upon request of some key you would return that key and add it to the cache, opon subsequent request for same key data would be read from cache instead of hitting database. That would reduce the load and increase the speed.
source: function (request, response) {
$.ajax({
url: 'yourQueryUrl.php', // <- this script/URL should limit the number of records returned
async: true,
cache: false,
type: 'GET',
data: {q: $('#searchBox').val()},
dataType: 'json',
success: function (data) {
response(data);
}
});

Will reinitializing a JavaScript object at global scope cause a memory leak?

I have links in a JQuery DataTable that use JQuery UI's tooltip feature. Each link has a tooltip that is populated by an Ajax call. I would like to limit the number of Ajax calls to as few as possible. The DataTable uses server-side processing, and the results are paginated, so there will never be more than ten links on the page at any one time.
The data that is returned by the Ajax call will never change and thus can be safely cached. In my testing, I have seen that the browser does cache the result of each Ajax call, so that it only makes one call per link, and then uses the cache thereafter. My concern is that some user might have their browser configured in such a way that it doesn't use the cache for some reason, and they will be firing off one Ajax call after another, every time they mouse over a link.
Here is the JavaScript for the tooltip:
$('.jobId').tooltip({
content: function(callback) {
var jobId = $(this).text();
$.ajax({
url: 'myUrl',
data: {jobId: jobId},
dataType: 'json',
success: function(data) {
var html = formatResults(data);
callback(html);
},
error: function() {
callback('An error has occurred.');
}
});
}
});
I considered storing the result of each Ajax call in a JavaScript object declared at global scope, and then checking that before making the Ajax call, but I have the vague sense that this might cause a memory leak somehow.
var gJobs = new Object();
$('.jobId').tooltip({
content: function(callback) {
var jobId = $(this).text();
if (gJobs[jobId]) {
callback(gJobs[jobId]);
} else {
$.ajax({
url: 'myUrl',
data: {jobId: jobId},
dataType: 'json',
success: function(data) {
var html = formatResults(data);
gJobs[jobId] = html;
callback(html);
},
error: function() {
callback('An error has occurred.');
}
});
}
}
});
I am also concerned that if the table has a large number of rows, the gJobs object could end up using a lot of memory. To prevent the gJobs object from growing indefinitely, every time the user goes to the next or previous page of results in the DataTable, I use the fnDrawCallback function to reinitialize gJobs:
$('#jobsTable').dataTable({
...
"fnDrawCallback": function() {
gJobs = new Object();
}
});
I should mention that since the data returned by each Ajax call doesn't change, I could also just store the data in the JSP as static text, and populate the tooltips that way instead of using Ajax. However, I have to make a separate web service call to get the data for each link, and rather than make ten web service calls every time the user pages forward or back, I would rather load the data on demand via Ajax.
Is there anything wrong with this approach? Is there any way this can cause a memory leak? Should I explicitly delete all the properties of gJobs before reinitializing it? Thanks for your help.

Categories

Resources