AJAX progress bar on array iteration? - javascript

I am not too familiar with AJAX but I'm sure what I am trying to do is possible.
Basically I have a form with a text area, when the form is submitted the text area is made into an array with each new line being a value. Simple stuff, now my php then performs a database query on each array value. Also simple.
Now as the operation takes a while I want to make it into an AJAX call using jquery, and for every iteration on the array I want it to display the result back on my main page as well as displaying a progress bar.
So if my text area contains a list of 20,000 names and the query is to fetch the ages of these people, the ajax call would split the textarea into an array and iterate the array. For each iteration it should perform the query and send the result to my main page. So on my main page I will see a list that grows over time.
I hope I have explained this well enough, I just need advice on where to start/what to research. Any examples would be greatly appreciated.
Thanks!

As ajax is simply a request for data you cannot create a reliable loading bar easily.
However if you are doing loads of requests as you suggest in your question, "Which by the way is not the best idea".
You could do something like the code below. Again its pretty basic but will give your user a rough idea. I stuck it in a fidddle here for you http://jsfiddle.net/6dgAF/ its a basic example but should give you a jump off point.
function Status(data)
{
this.data = data;
this.size = this.data.length;
this.current = 0;
this.bar = $("#bar");
//Get width of each step of load
this.step = (this.bar.width() / this.size) ;
for(var i =0; i < this.size; i++){
this.getData(this.data[i]);
}
}
Status.prototype.getData = function(string){
//run your ajax here on each string and on success do this
//$.get( "ajax/test.html", function( string ) {
//this.current++;
//this.updateBar();
//});
this.current++;
this.updateBar();
}
Status.prototype.updateBar = function(){
//updates the bar with the current count * step width;
$("span",this.bar).width(this.step*this.current);
}
//Init object and put in dummy data
var status = new Status(new Array("string1","string2","string3","string4","string5","string6","string7","string8","string9","string10"));

An AJAX request is nothing else than requesting data from your server, just like any HTML page. The only difference is that you use Javascript, and don't feed the data to your browser as an HTML page, but use the data some way on your page.
One possible way to do the thing you want is the following:
Set an interval with the refresh rate, which calls a function getData
In getData you perform an AJAX request, which requests a piece of data from the server, which represents the current state. You might want to make sure the server only returns incremental updates, to avoid sending large amounts of data
Use the data on your front page, by displaying it in a friendly way to the user.
The main thing to keep in mind is that the server must save it's current state (the data which it has gathered with its queries), which it must return in the event of an AJAX request.

What you want is called XHR2 - personally I am using dojo
(dojo/request/xhr here)
However it should be possible with jQuery as well, search for jQuery XHR2 progress ...

Related

search items that load data from DB in Knockout JS

In my application, I have an observableArray that loads data from DB. This observableArray fills first 25 items from DB and from scrolled down it loads another 25 and it goes on.
Now, I want to implement search, that should display the result searching the whole data from DB and not just from the displayed 25 items.
I tried to get the search result by sending the whole searching text to DB on clicking search button and there is lot of datas in DB which takes much time to load data.
Please let me know how I can get the desired result from DB within ms. Thanks in advance.
To get a well behaving search with Knockout, you should extend your searchText observable that is bound to the input with a rate-limiter
this.searchText = ko.observable('').extend({ rateLimit: { timeout: 500, method: "notifyWhenChangesStop" } })
This will call any subscribers after the input has remained unchanged for 500ms (i.e. when the user stops typing). You could also use the default method notifyAtFixedRate to call the API at least once every X seconds.
And to top it off, a fiddle!
Note: with this being said, if your query is taking 40 seconds, that sounds like a problem with your database query. It's possible that it's taking that long because you're flooding the server with requests, but that still seems awfully slow. This is the strategy we use and it works excellent, but our API response time is <200ms.

JSON vs multiple connections

i'm currently building a website which searches an external database and brings up records which match the given search string. The search is live, so results are brought up as the user types.
now the first (and current) approach i took, is that the page actually connects to the mySQL server and retrieves content via AJAX, with EVERY letter the user types in the search box.
now i am starting to look at JSON objects (i only very recently started building websites), and was wondering if it would be a good idea, to load the entire database into a JSON object in the beginning and then look through that when searching.
is this a good idea? would it be faster? thanks in advance
It totally depends on the size of the data and the complexity of the query. If you can reasonably send the data to the client in advance and then search it locally, then sure, that's useful because it's all local and you don't have the latency of querying the server. But if you have a large amount of data, or the query is complex, it may well make more sense to do the query on the server.
There's no one-size-fits-all solution, it's data-dependent.
...and retrieves content via AJAX, with EVERY letter the user types in the search box.
That's usually overkill. Normally, you want to wait until there's a pause in the user's typing before firing off the ajax call, so that if they type "james" in rapid succession, you search for "james" rather than searching for "j", then "ja", then "jam", then "jame", and then "james".
For instance, let's say your search trigger is a keypress event. This would be a fairly common approach:
var keypressTimer = 0;
function handleKeypress() {
if (keypressTimer) {
cancelTimeout(keypressTimer);
}
keypressTimer = setTimeout(doSearch, 100); // 100ms = 1/10th of a second
}
function doSearch() {
var searchValue;
keypressTimer = 0;
searchValue = /*...get the search value...*/;
doAjaxCallUsing(searchValue);
}
This is called "debouncing" the input (from hardware engineering, related to the mechanical and electrical "bouncing" of a key as it's pressed).

Google Visualization Query - Abort Request

I am working on an interface that contains several high-intensity SQL queries, then renders multiple Google charts which are currently being called via AJAX using the google.visualization.Query object:
var query = new google.visualization.Query('/report.ashx');
query.send(callbackMethod);
//....
function callbackMethod(rs){
var data = rs.getDataTable();
var graph = new google.visualization.AreaChart(target_div);
graph.draw(data);
}
As the interface can be filtered dynamically I have encountered a scenario whereby a query can be running, whilst the user could potentially choose to re-filter and hence re-query the data source. If the first query is still running and the second query begins and returns before the first query then the chart will be drawn just fine. However, when the first query finally completes it could completely overwrite the chart with the old data, ignoring the current filters.
I have read that there is the ability to pass a jQuery AJAX object in, which exposes an XHR object allowing me to call .abort() on the XHR which would cancel the request (albeit this would still process on the server, but that's a hit I'm willing to take). Unfortunately I can find no examples of this and the Google documentation is less than helpful in this respect. Has anybody encountered the same, and if so - have they solved the problem?
Cheers,
Chris.
You can wrap callbackMethod in a higher order function to keep track of the request time, and use query.send(callback()) instead of query.send(callbackMethod).
var mostRecentReqTime;
var callback = function() {
var reqTime = Date();
return function() {
if (reqTime < mostRecentReqTime) return;
var data = rs.getDataTable();
var graph = new google.visualization.AreaChart(target_div);
graph.draw(data);
mostRecentReqTime = reqTime;
};
};

Load another HTML page to create an JavaScript array using .get and .each

So I've banged my head on this all day. I'm updating the code.
I'm trying to pull an array based off of an HTML page (we'll call this switcher1.html) where there is a list.
Based on this array, the javascript will randomly load one item of the array onto the page where the javascript is called (we'll call this index.html).
//
// Random Profile
//
function randomProfile() {
var profilePages = [];
$.get( "/js/switcher1.html #featured-faculty", function() {
$("ul li").each(function( index ) {
profilePages.push($(this).text())
});
});
var randomPage = Math.floor(Math.random() * profilePages.length);
$('#featured-profile').load(profilePages[randomPage]);
}
// Run these functions as soon as this script is loaded,
// instead of waiting for the DOM to finish loading
randomProfile();
Hopefully you can see that the goal is to pull in a list from another source so I won't have to type it in to the JavaScript doc manually. My array is turning up blank no matter what I try.
FYI - I can use JQuery but not other code libraries. Also, I'm doing it this way due to a (slightly annoying & convoluted) CMS. The CMS can output an HTML list, so this is the best solution I was able to come up with.
Thanks in advance for your help!

YUI Datatable - call arbitrary function *once* on sort

We're using a lot of YUI data tables to display data, and rather than using the built-in pagination we've done our own so we can paginate on the server side using AJAX without downloading the whole data set (which is often huge).
Whenever we use the data table's sorting funcionality, though, it will only sort the one page because from YUI's point of view that's the entire data set.
I need to be able to call an arbitrary function to reload the page data whenever the user tries to sort the data. I've looked into DataTable's sortFunction parameter and it's not ideal because it gets called multiple times (once for each row combination it needs) and I need to do it just once.
There are probably plenty of hacky ways I could do this, but what's the "nicest" way of going about this?
Ideally, you would sort on the server side.
when create the datatable, one of the config options is generateRequest (see this example: http://developer.yahoo.com/yui/examples/datatable/dt_bhm.html )
generateRequest is a meant to be a function which generates a URL which returns the correct data set with which to fill the table. You probably have this.
For me, whenever I click on the column header (to sort), it makes a new request to the server, getting the correct page of sorted data.
Why not write a custom function and close over a variable that tracks whether it's been called?
var hasBeenCalled = false;
function mySortFunction(){
if(!hasBeenCalled){
// do something
hasBeenCalled = true;
}
}
Then replace the sortFunction with that.

Categories

Resources