How to make casperJS wait until .change() event is finished? - javascript

I am triggering a change event in my casperJS script which triggers an AJAX request like such:
casper.evaluate(function(i) {
$("form:eq(2) select option:eq(" + i + ")").attr("selected", "selected").change();
},i);
How can I make casperJS wait until the underlying AJAX request has been finished? Already tried to look at the docs but I am more or less stuck. Can anyone guide me into the right direction?

You can always do this in a static way using casper.wait.
casper.thenEvaluate(function(i) {
// change()
},i).wait(5000).then(function(){
// further processing
});
And hope that the request is done in 5 seconds, but maybe you lose some time waiting when the request is done much sooner than 5 seconds. The problem is that as soon as the request is finished doesn't mean that the page is ready/changed.
Another possibility would be to wait for the request to finish, but for this to work you will need to register for the success event of the request somehow. Most of the time you don't have access to this from the global scope. If you do then you can use
casper.thenEvaluate(function(i) {
window._someUniqueVariable = false;
registerSuccessEvent(function(data){
window._someUniqueVariable = true;
});
},i).waitFor(function check(){
return this.evaluate(function(){
window._someUniqueVariable = true;
});
}, function(){
// further processing
});
A more Casper-way of doing that would be to use casper.waitForResource, but then you would need to know the url beforehand or at least able to deduce it from the page.
In the general case, when the request comes back it does something to your page. So you should be able to waitForSelector with a new element or waitForSelectorTextChange or waitUntilVisible etc.

you probably missed waitForResource
from the docs: http://casperjs.readthedocs.org/en/latest/modules/casper.html#waitforresource
casper.waitForResource("you url here", function()
{
// place your code here
});

Related

Waiting with page load until method finished

The Javascript of my webpage is executing the code shown below when a webpage is loading. The call to get can take a couple of seconds, thus I would like to wait with loading the page until the call is finished.
Is it possible to postpone the loading of the page until the call to get finished? Or even a better way would be to show some spinning wheel (instead of a white page), so that the user is aware that some process is going on. Is this possible?
document.addEventListener("DOMContentLoaded", function(){
if (!sessionStorage.getItem("userID")) {
// Get new userID
$.get("/new_user").done(function (data) {
sessionStorage.setItem("userID", data);
});
}
});
I'm not sure if your implementation with the event listener "DOMContentLoaded" is right, I think we are missing some context here and you may be able to check session storage before this, but I will assume that part is correct and address your question about a loading spinner.
Also I wont go into detail about how to make a load spinner as there are a lot of examples out there.. but as far as having your page be a load spinner while your ajax call is running I would make the function async and set the html of the page to the loading spinner right before the call, and then after you await the call, set the data and then set the html to what you want it to be after it's done loading
document.addEventListener('DOMContentLoaded', async (event) => {
if (!sessionStorage.getItem("userID")) {
document.getElementById('container').innerHTML = '<div>loadspinnerhtml</div>';
var data = await $.get("/new_user")
sessionStorage.setItem("userID", data);
document.getElementById('container').innerHTML = '<div>theloadedhtml</div>'
}
});

How to handle multiple requests being sent in JavaScript?

Working on a platform, to enable auto-ticketing functionality. For which a REST API request is used for ticket creation. Unfortunately, there are 2 requests popping simultaneously, which results in creating duplicated tickets.
How to handle such case and send only one of these requests?
Tried adding the 2nd request in the response callback of the first, though this does not seem to work.
if (flag == 1){
logger.debug("Node-down alarm-Request raised - +sitn_id);
clearTimeout(mouseoverTimer);
mouseoverTimer = setTimeout(function(){
logger.debug("Inside Call back function - ");
//function call for ticket creation
incidentRequest(sitn_id,confUtil.config.mule_url);
}, 10);
You really should show more of the code that makes the request, though it seems as if you are doing some ajax inside your 'incidentRequest', so I will presume that (if that isn't what you are doing, then please, show your code....) - and since you tags say javascript and jquery - well, here goes...
To stop the 'double send' in an AJAX call, it is simple:
function incidentRequest(sitn_id,confUtil.config.mule_url){
// stop the double by clearing the cache
$.ajaxSetup({cache: false});
// continue on with the AJAX call
// presuming the url you want is confUtil.config.mule_url
// and the data you want to send is sitn_id
$.post(confUtil.config.mule_url, 'sitn_id=' + sitn_id, function (data) {
// do cool stuff
});
}
Hopefully that will help you get moving. If not, then we will need more code of what is going on around all this.

Sending jQuery ajax request on keyboard input

I'm sending an ajax request to the server on user's input to an <input> element, like this:
$('#my-input').bind("input", function(event){
// here's the ajax request
});
What bothers me is that it send unnecessarily many requests on every user's keyup, meaning that if the user types very fast, there are many unnecessary requests. So I get the idea that there should be a certain delay/timeout, which waits a certain time (50 miliseconds?) for the user to stop typing before sending the ajax request. That would be one problem solved.
But what about cases when the first ajax request haven't been completed before sending another request? (Typing 60 ms / char while ajax request taking 300 ms).
What is the best way to solve this problem (both idea- and code-based)?
You can use throttle function in underscore library. As its documentation says:
Creates and returns a new, throttled version of the passed function, that, when invoked repeatedly, will only actually call the original function at most once per every wait milliseconds. Useful for rate-limiting events that occur faster than you can keep up with.
Even if you don't want to introduce a new library, you can still get idea about how this function works from its source code. In fact, a simple version of throttle function could be:
function throttle(func, delay) {
var timeout = null;
return function() {
var that = this, args = arguments;
clearTimeout(timer);
timeout = setTimeout(function() {
func.apply(that, args);
}, delay);
};
}
This jQuery throttle-debounce plugin is also helpful. Especially, the debounce function seems more suitable to your needs than throttle function according to its author:
Debouncing can be especially useful for rate limiting execution of handlers on events that will trigger AJAX requests
You could just use the setTimeout function. Every so often, see if the text hasn't changed, and if it hasn't, then process accordingly.
setTimeout(function() {
// Do something after 1 second
}, 1000);
You can set async: false in your ajax request so it will process second ajax call only after completion of first ajax request.
I'd go with #HuiZeng's answer, but just in case you want a slightly modified version.
Steps
Listen to keydown using a setTimeout that you can clear.
When it fires, check if you have a previous request in queue, if so abort it and fire a new one
Example:
var inputTimer = 0, req;
function onInput(e){
clearTimeout(inputTImer);
inputTimer = setTimeout( function(){
// You have access to e here
// Cancel any previous requests
req && req.abort();
req = $.ajax({/*...Do your magic here :)*/})
}, 100)
}

How to change window.location.href in JavaScript and then execute more JS?

I have code snippent which is executed on click of a link which is as below
cj_redirecturl="/HomeWork/main/load_course";
utility.xhttprw.data(cj_redirecturl,{data:courseid},function(response){
if(response){
window.location.href=base_url+"main";
///next
utility.xhttprw.data(redirecturl,{data:""},function(response){
if(response){
id=ent;
document.getElementById('content').innerHTML=response;
// Assignemnt module
//Call function from javascript/assignment.js file to display particular assignment (ent:means assignment_id) //
if(con==5)
{
get_assignment_id(ent);
}
if(con==9)
{
get_content_details(ent);
}
} //end of response
},false,false,false,'POST','html',true);
}
},false,false,false,'POST','html');
in above code window.location.href=base_url+"main";redirects the page to its respective page but this stops the execution of the code written just next to it. Now I want this code to be executed as it is been written i.e. firstly the code should take me to the respective "main" page and then code writte after that must execute and give me a required output.
Can someone guide me to achieve this?
window.location.href = base_url + "main"; <- when you load this page, call your code defined at ///next
you will have to add some parameters:
window.location.href=base_url+"main?parameter=true";
The other way would be to load the page with ajax into a div in the html.
Have a look at $.ajax() from jQuery.
please try to write
window.location.href = base_url + "main";
just before the end of if condition or use
setTimeout('window.location.href=base_url+"main"', 2000);
As already been noticed, you cant execute code after you went to another page
What you can do is to create redirector function, that will pass your function in cookie and ,redirect and then eval it on next page. (with another call to that redirector on next page)
But you should be aware of number of issues
1) Packing. It is upon you to decide how you pack cookie.
2) Encription. If you pass non-packed OR non-encrypted cookie the "bad user" can pass some malware code inside that cookie.
3) You should have VERY, VERY good reasons to do it.
This way is too complicated, hard to code, hard to maintain
Much better if you do additional server-side controls, save it somewhere and reload on next page with one more request.
You'll need to wrap the rest of the JS code inside a window.onbeforeunload callback.
See here: Intercept page exit event
You need to use the onBlur event to continue to execute js code before exit from the page.
Example:
function downloadExcel()
{
// Your code...
$('#download_excel_button').hide();
$('#download_spinner').show();
window.location.href = download_page;
window.onblur = function(event)
{
// other event code...
$('#download_spinner').hide();
$('#download_excel_button').show();
}
}

How do I send an AJAX request upon page unload / leaving?

window.onbeforeunload = function() {
return $j.ajax({
url: "/view/action?&recent_tracking_id=" + $recent_tracking_id + "&time_on_page=" + getSeconds()
});
}
this what I have, but it returns an alert with [object Object]
how do I just execute the AJAX?
note: when I just don't return anything, the server doesn't show that it is receiving the ajax request.
You don't need to return anything, just fire the ajax call.
window.onbeforeunload = function(e) {
e.preventDefault();
$j.ajax({ url: "/view/action?&recent_tracking_id=" + $recent_tracking_id + &time_on_page=" + getSeconds()
});
}
If you are using jQuery, you can try binding to the .unload() event instead.
onbeforeunload allows you to return a string, which is shown in the 'Do you want to leave' confirmation. If you return nothing, the page is exited as normal. In your case, you return the jqXHR object that is returned by the JQuery ajax method.
You should just execute the Ajax call and return nothing.
Why are you returning the reference of function to global pool? It should be like this:
window.onbeforeunload = function() {
$j.ajax({
url: "/view/action?&recent_tracking_id=" + $recent_tracking_id + "&time_on_page=" + getSeconds()
});
}
To the best of my understanding, the onbeforeunload function will only return an alert. This was done to prevent the annoying popups of a few years back.
I was building a chat client a while back and the only way i could figure out to do something like this is to do a setInterval function that updated a timestamp, then checked for timed out users and removed them. That way users that didnt "check in" within a certain interval would be removed from the room by other users still logged in.
Not pretty, or ideal, but did the trick.
Doing standard ajax calls in a page unload handler is being actively disabled by browsers, because waiting for it to complete delays the next thing happening in the window (for instance, loading a new page).
In the rare case when you need to send information as the user is navigating away from the page (as Aaron says, avoid this where possibl), you can do it with sendBeacon. sendBeacon lets you send data to your server without holding up the page you're doing it in:
window.addEventListener("unload", function() {
navigator.sendBeacon("/log", yourDataHere);
});
The browser will send the data without preventing / delaying whatever is happening in the window (closing it, moving to a new paeg, etc.).
Note that the unload event may not be reliable, particularly on mobile devices. You might combine the above with sending a beacon on visibilitychange as well.

Categories

Resources