loop ajax call, to complete lenghtly operations on server - ajax

I have a function, that uses ajax, that takes really long to complete.
The thing is that I have a lot of files on server, that need to be processed, and the page I'm trying to make is like a status page.
It has a link to start processing, and file counts. It looks like this:
Click here to start process
files 0/500
When I click the link, it runs this function:
function generate_book_link_clicked(){
$.getJSON("/generate_book", function(data){
if (data['last'] == 'true'){
$('#done').fadeIn(200);
}else{
$('#current_count').html(parseInt($('#current_count').text())+1);
$('#generate_book_link').click();
}
});
}
This is the link code:
click me
and this is the code for the counter html (the "<%= #isbn_count.to_s %>" just returns the count):
<span id="current_count">0</span>/<span id="total_count"><%= #isbn_count.to_s %></span>
But what happens is, when ajax completes, it doesn't start the process over again, but the count just starts rapidly adding without ajax calls.
It's like, the first finishes successfully, but then it just starts rapidly adding values to "current_count", and it goes like that forever even over the original count (1000/500)..
I can't figure how to start the process again, currently.
I hope I made everything clear and that someone will be able to help me.

Instead of
$('#generate_book_link').click();
just call your function directly:
generate_book_link_clicked();

Related

watir/ruby waiting for iframe to exist

I have a problem waiting for an iframe to exist on page after entering a date range and I would rather not use sleep. I am using ruby/watir
I have tried solutions like this -
wait_until(10, "iFrame has not loaded") do
#browser.iframe(id: "dtl00_DP1_content").exists?
end
but this simply returns this error - Selenium::WebDriver::Error::NoSuchWindowError: no such window
So how do I wait for an iframe that does not yet exist please?
I am not sure whether you only want to wait for an Iframe, If you want to perform any operation on an element which is present in the iframe, then you could do as I mentioned in my comment.
#browser.iframe(name: "something").text_field(name: "username").set 'raja'
Or If you still wait for an iframe to appear, then write the following code
#browser.wait_until { #browser.iframe(id: "dtl00_DP1_content").exists? }
The above code waits for 30 seconds, but If you want to increase the time to wait, then write the following code, the following code would wait fo 50 seconds.
#browser.wait_until(timeout: 50) { #browser.iframe(id: "dtl00_DP1_content").exists? }

ajax calls not executing

I am throwing an ajax call that downloads a few images.
At the same time, I need another loop that has to check if all the images have been downloaded (I know how many will be downloaded). I do it this way:
function check_download(){
ajax_call...
success: function(amount){if(amount < 40) check_download()}
}
call download_images(); // this starts the process of downloading images
call check_download();
So I launch the download and I send an ajax call to check if it has downloaded the 40 images. If not, then I want to launch another ajax call to check again, and so on.
But it only throws 2 ajax calls. The second one gets frozen and it does not return any value, so no loop is being done and I cannot check the progress of the download.
Any idea on how to launch several ajax calls to achieve this?

How to wait until the embedded ajax call is completed when injecting my script?

It's Google Chrome extension development. I'm using content script to inject into webpages. However some webpages have their own ajax scripts that change the content dynamically. How do I wait until such scripts are completed, since before their completion my script cannot obtain the correct content?
For example,
1- on Google search result page,
2- I want to append "text" to title of every search result item, which could be easily done by calling,
$('h3').append("text");
3- then listen to the search query change, done by
$('input[name="q"]').change( function(eventObj){
console.log("query changed");
// DOESN'T work
$('h3').append("text");
});
The last line doesn't work probably because at the time it's executed the page is still refreshing and $('h3') is not available. Google uses ajax to refresh the search result when the query is changed on the page.
So the question is how to capture this change and still be able to append "text" every time successfully?
EDIT:
Have tried and didn't work either:
$('h3[class="r"]').delay(1000).append("text");
and using .delay() is not really preferred.
EDIT:
.delay() is simply not designed to solve pause the execution of scripts other than UI effects. An workaround is
$('input[name="q"]').change(function(eventObj) {
setTimeout(function() {
$('h3[class="r"]').append(" text");
}, 1000);
});
But as I argued before, setTimeout() is connection-speed dependent, not preferred because I have to manually balance the time of waiting and the speed of response (of my script).
Although this post is down-voted for god-knows-why I'll still be waiting for an elegant answer.
Maybe with jQuery 1.7+ (or with older version using "live" or "delegate")
$('form').on( "change", 'input[name="q"]', function(eventObj){
console.log("query changed");
$('h3').append("text");
});
If form is another element, change it accordingly.

How to know when a web page is loaded when using QtWebKit?

Both QWebFrame and QWebPage have void loadFinished(bool ok) signal which can be used to detect when a web page is completely loaded. The problem is when a web page has some content loaded asynchronously (ajax). How to know when the page is completely loaded in this case?
I haven't actually done this, but I think you may be able to achieve your solution using QNetworkAccessManager.
You can get the QNetworkAccessManager from your QWebPage using the networkAccessManager() function. QNetworkAccessManager has a signal finished ( QNetworkReply * reply ) which is fired whenever a file is requested by the QWebPage instance.
The finished signal gives you a QNetworkReply instance, from which you can get a copy of the original request made, in order to identify the request.
So, create a slot to attach to the finished signal, use the passed-in QNetworkReply's methods to figure out which file has just finished downloading and if it's your Ajax request, do whatever processing you need to do.
My only caveat is that I've never done this before, so I'm not 100% sure that it would work.
Another alternative might be to use QWebFrame's methods to insert objects into the page's object model and also insert some JavaScript which then notifies your object when the Ajax request is complete. This is a slightly hackier way of doing it, but should definitely work.
EDIT:
The second option seems better to me. The workflow is as follows:
Attach a slot to the QWebFrame::javascriptWindowObjectCleared() signal. At this point, call QWebFrame::evaluateJavascript() to add code similar to the following:
window.onload = function() { // page has fully loaded }
Put whatever code you need in that function. You might want to add a QObject to the page via QWebFrame::addToJavaScriptWindowObject() and then call a function on that object. This code will only execute when the page is fully loaded.
Hopefully this answers the question!
To check the load of specific element you can use a QTimer. Something like this in python:
#pyqtSlot()
def on_webView_loadFinished(self):
self.tObject = QTimer()
self.tObject.setInterval(1000)
self.tObject.setSingleShot(True)
self.tObject.timeout.connect(self.on_tObject_timeout)
self.tObject.start()
#pyqtSlot()
def on_tObject_timeout(self):
dElement = self.webView.page().currentFrame().documentElement()
element = dElement.findFirst("css selector")
if element.isNull():
self.tObject.start()
else:
print "Page loaded"
When your initial html/images/etc finishes loading, that's it. It is completely loaded. This fact doesn't change if you then decide to use some javascript to get some extra data, page views or whatever after the fact.
That said, what I suspect you want to do here is expose a QtScript object/interface to your view that you can invoke from your page's script, effectively providing a "callback" into your C++ once you've decided (from the page script) that you've have "completely loaded".
Hope this helps give you a direction to try...
The OP thought it was due to delayed AJAX requests but there also could be another reason that also explains why a very short time delay fixes the problem. There is a bug that causes the described behaviour:
https://bugreports.qt-project.org/browse/QTBUG-37377
To work around this problem the loadingFinished() signal must be connected using queued connection.

How to Track the Online Status of Users of my WebSite?

I want to track users that are online at the moment.
The definition of being online is when they are on the index page of the website which
has the chat function.
So far, all I can think of is setting a cookie for the user and, when the cookie is found on the next visit, an ajax call is made to update a table with their username, their status online and the time.
Now my actual question is, how can I reliably turn their status to off when they leave
the website? The only thing I can think of is to set a predetermined amount of time of no user interaction and then set the status to off.
But what I really want is to keep the status on as long as they are on the site, with or without interaction, and only go to off when they leave the site.
Full Solution. Start-to-finish.
If you only want this working on the index.php page, you could send updates to the server asynchronously (AJAX-style) alerting the server that $_SESSION["userid"] is still online.
setInterval("update()", 10000); // Update every 10 seconds
function update() {
$.post("update.php"); // Sends request to update.php
}
Your update.php file would have a bit of code like this:
session_start();
if ($_SESSION["userid"])
updateUserStatus($_SESSION["userid"]);
This all assumes that you store your userid as a session-variable when users login to your website. The updateUserStatus() function is just a simple query, like the following:
UPDATE users
SET lastActiveTime = NOW()
WHERE userid = $userid
So that takes care of your storage. Now to retrieve the list of users who are "online." For this, you'll want another jQuery-call, and another setInterval() call:
setInterval("getList()", 10000) // Get users-online every 10 seconds
function getList() {
$.post("getList.php", function(list) {
$("listBox").html(list);
});
}
This function requests a bit of HTML form the server every 10 seconds. The getList.php page would look like this:
session_start();
if (!$_SESSION["userid"])
die; // Don't give the list to anybody not logged in
$users = getOnlineUsers(); /* Gets all users with lastActiveTime within the
last 1 minute */
$output = "<ul>";
foreach ($users as $user) {
$output .= "<li>".$user["userName"]."</li>";
}
$output .= "</ul>";
print $output;
That would output the following HTML:
<ul>
<li>Jonathan Sampson</li>
<li>Paolo Bergantino</li>
<li>John Skeet</li>
</ul>
That list is included in your jQuery variable named "list." Look back up into our last jQuery block and you'll see it there.
jQuery will take this list, and place it within a div having the classname of "listBox."
<div class="listBox"></div>
Hope this gets you going.
In the general case, there's no way to know when a user leaves your page.
But you can do things behind the scenes such that they load something from your server frequently while they're on the page, eg. by loading an <iframe> with some content that reloads every minute:
<meta http-equiv="refresh" content="60">
That will cause some small extra server load, but it will do what you want (if not to the second).
Well, how does the chat function work? Is it an ajax-based chat system?
Ajax-based chat systems work by the clients consistently hitting the chat server to see if there are any new messages in queue. If this is the case, you can update the user's online status either in a cookie or a PHP Session (assuming you are using PHP, of course). Then you can set the online timeout to be something slightly longer than the update frequency.
That is, if your chat system typically requests new messages from the server every 5 seconds, then you can assume that any user who hasn't sent a request for 10-15 seconds is no longer on the chat page.
If you are not using an ajax-based chat system (maybe Java or something), then you can still accomplish the same thing by adding an ajax request that goes out to the server periodically to establish whether or not the user is online.
I would not suggest storing this online status information in a database. Querying the database every couple of seconds to see who is online and who isn't is very resource intensive, especially if this is a large site. You should cache this information and operate on the cache (very fast) vs. the database (very slow by comparison).
The question is tagged as "jquery" - what about a javascript solution? Instead of meta/refresh you could use window.setInterval(), perform an ajax-request and provide something "useful" like e.g. an updated "who's online" list (if you consider that useful ;-))
I have not tried this, so take it with a grain of salt: Set an event handler for window.onunload that notifies the server when the user leaves the page. Some problems with this are 1.) the event won't fire if the browser or computer crashes, and 2.) if the user has two instances of the index page open and closes one, they will appear to logout unless you implement reference counting. On its own this is not robust, but combined with Jonathan's polling method, should allow you to have pretty good response time and larger intervals between updates.
The ultimate solution would be implementing something with websockets.

Resources