can't change location of webpage using "window.onbeforeunload" - javascript

Can anybody pls tell me, how can i make a AJAX request and send user to some other page when he performs following actions ?
Clicks on next, prev btns of browser.
refresh page by any way(f5,ctrl+r,refresh btn).
try to close browser's window(Here i don't want to redirect him, just AJAX request).
i thought window.onbeforeunload could make it,
window.onbeforeunload = function () {
makeAjaxCall();
------
------
}
// Ajax Call is successful
function makeAjaxCall_SuccessHandler() {
window.location.href = 'Home.html';
}
but it is not working at all........
after searching on this topic i found that this is a kind of rule made for browser's security.
so pls tell me how to do this or any alternate way to achieve this.

You're not describing the actual behavior you're getting so I'm kinda guessing here, but I think your problem here is with the Asynchronous part of AJAX.
You see, when your onbeforeunload handler executes it may very well initiate the AJAX call BUT it won't block waiting for its results to return. Instead the execution will continue and onbeforeunload will complete before you ever get any result from your AJAX request (if any call is made at all).
First of all add some debug traces to validate your handler is actually executed. If it is, add an idle loop to keep it busy (preventing it from returning) and see if the AJAX call comes through (I'd check the server side for that).
If that's indeed the case I guess you'll have to modify the idle loop to consult some kind of flag. Or even better, if the libraries you use allow it, make the server call synchronous.

I think no.
Browsers can stop execution at any time after action. Ajax call is very long operation for this.
With onbeforeunload you can asking user questions like "Are use sure?". You must return string or assign it to event.returnValue
You can read about it here https://developer.mozilla.org/en/DOM/window.onbeforeunload
I think with your problem you can try to make synchroness call or try to open iframe with some GET parameter or send form data in iframe in body of this function. But i don't sure about time.

Related

Is an AJAX request killed when a link gets clicked?

I have a website with an AJAX cart. The concept is pretty simple: you end up on a page with a product and can click the Buy Now button. When you do so, the JavaScript code adds the product to the cart, changes the cart visual with the new count, and sends an AJAX request to the server to report the change.
What I'm wondering about, since the client and the server may take a while to process the AJAX request, is... will the client clicking a link to move to another page (i.e. "next product") before the AJAX is reported as successful stop the AJAX request at all?
// prepare request...
...snip...
// send request (usually a POST)
jQuery.ajax(uri, ajax_options);
// return to user
// will a click on a link cancel the AJAX call after this point?
Further, I have timed AJAX requests. If the user clicks on a link before those timed requests happen, they will be lost for sure. Assuming that the click does not cancel an AJAX request, would starting one in the unload event work? Would using a cookie be better/safer than attempting another AJAX request? (although if the user clicks an external link, the unload is really the only solution I can think of to save that data...)
As a side note: I do not want to darken the screen when the user adds an item to the cart so that way the user can continue to do things... but if the AJAX needs to be confirmed before a link can be clicked, I'd have to make sure clicks cannot be used until then.
Update:
I thinks that some of you are missing the point. I do not care about the done() or completed() functions getting called on the client side. What I do care about is making sure that in the end I get all the data on the server.
I understand that's asynchronous, but what I want to make sure of is avoiding loss of data, especially if the link goes to another website (to the same website, I am really thinking to make use of a cookie to make sure that the data of delayed AJAX requests get to the server no matter what.)
Also, the idea of timed data requests is to avoid heavy loads on the server. With a properly timed set of AJAX requests, the client and server both work a lot better!
#meagar summed this up pretty well in the comments
Any pending AJAX requests will be aborted when the browser navigates away from the page.
So depending on how you define "killing" an AJAX request, that means the request may be started, but it also might not have finished. If it's a short request, most likely it won't be aborted by the time it finishes. But if it's a long request (lots of data processing, takes a second or two to complete), then most likely it's going to be aborted somewhere in the middle.
Of course, this all depends on the browser. The issue typically is that the request makes it to the server, but the browser aborts the request before the response comes through. This all depends on the server and how it processes the data.
Some servers will interrupt the execution of your view, where the requests data is being processed and the response is being generated. Many servers will just let the code run and trigger an error when you try to write output to the response. This is because there is nobody on the other end, so you're writing the response to a closed connection.
although if the user clicks an external link, the unload is really the only solution I can think of to save that data
From my own experience, most browsers will allow you to send out a request during the beforeunload event. This is not always true for unload though, as by that time the page change cannot typically be stopped.
One way to get around this, especially when the response matters, is to halt the page change after the user clicks the link. This can be as simple as calling evt.preventDefault() on the click event for the link, and then later redirecting the user to where they wanted to go when the request is finished. You should make sure to indicate to the user that their request has not just been ignored, but that they're waiting on something to finish first. Users don't want to be left in the dark, so make sure to give them some feedback (like changing the button text, disabling it, etc.).

Event when call ends / JavaScript

We want to log the JavaScript on our Website. For that I am overwriting the log functionality with my own implementation.
On the server side we are using Log4Net for our logging. My idea now is to capture the log on the client side and send it to the server with ajax. How ever I don't want to send the Ajax request every time someone types log. So my idea was to catch all the logs and send ONE request after the call-stack ended up where it has began.
Is there an event or a way to detect when call-stack has "ended" ?
You can try to use javascript beforeunload event to send your log when user leave a page.
If you use jQuery, the code look like:
$(window).bind("beforeunload",function(event) {
//... put your ajax code here ...
return "The log has sent to server.";
});
however beforeunload event will show a message box on your screen.
Also if you want to run a function after another function run, you can use jQuery $.when() method as below:
$.when(functionOne(), functionTwo()).then(functionThree()).done(functionFour());
functionOne(), functionTwo(), functionThree(), and functionFour() must be a deferred object.
This blog give a simple explanation how to implement deferred object.

OpenGraph watch action - less than 50% watched

I'm using the Javascript SDK to contact the API.
Using Built-in Watch action:
When a user watches less than 50% of a video, or if a user removes a watch activity from your app/site, you should also remove the corresponding action instance that was published to Open Graph by invoking the following call
DELETE https://graph.facebook.com/[watch action instance id]
My problem is with when the user navigates away from the page.
I've tried to use the jquery unload method to make the delete call to the API but it fails to. I've also tried using ajax to make the call synchronously but this holds/freezes the browser for at least 5 seconds on average.
Any ideas?
I've tried to use the jquery unload method to make the delete call to the API but it fails to.
Well, that’s a problem with the call being asynchronous. Your unload handler fires, starts the request, and then the browser navigates away from the page. Wait, what, there’s a request still running? Let’s terminate that, since I’m about to load and display another page anyway …
I've also tried using ajax to make the call synchronously but this holds/freezes the browser for at least 5 seconds on average.
If that’s how long your call takes, then I see no realistic way of shortening that.
You could try setting up a script that terminates straight away, without giving a return value (or a yeah OK, go on with your stuff, browser response) – and finishes the rest (making the actual API call) afterwards, server-side.

how to silently guarantee executing an ASP.NET MVC3 action on page unload

I need to execute an action of a controller when a user leave a page (close, refresh, go to link, etc.). The action code is like:
public ActionResult WindowUnload(int token)
{
MyObjects[token].Dispose();
return Content("Disposed");
}
On window download I do Ajax request to the action:
$(window).unload(function ()
{
$.ajax({
type: "POST",
url: "#Url.Action("WindowUnload")",
data: {token: "#ViewData["Token"]"},
cache: false,
async: true
});
//alert("Disposing.");
})
The above ajax request does not come to my controller, i.e., the action is not executed.
To make the code above to work I have to uncomment the alert line, but I don't want to fire alert on a user.
If I change async option to false (alert is commented), then it sometimes works. For example, if I refresh the page several times too fast then the action will not be executed for every unload.
Any suggestions how to execute the action on every unload without alert?
Note, I don't need to return anything from action to the page.
Updated: answers summary
It is not possible reliably to do request on unload, since it is not proper or expected behavior on unload. So it is better to redesign the application and avoid doing HTTP request on window unload.
If it is not avoidable, then there are common solutions (described in the question):
Call ajax synchronously, i.e., async: false.
Pros: works in most cases.
Pros: silent
Cons: does not work in some cases, e.g, when a user refreshes the windows several times too fast (observed in Firefox)
Use alert on success or after ajax call
Pros: seems to work in all cases.
Cons: is not silent and fires pop up alert.
According to unload documentation, with async: false it should work as expected. However, this will always be a bit shaky - for example, user can leave your page by killing/crashing the browser and you will not receive any callback. Also, browser implementations vary. I fear you won't get any failproof even.
HTTP is stateless and you can never get a reliable way to detect that the user has left your page.
Suggested events:
Session timeout (if you are using sessions)
The application is going down
A timer (need to be combined with the previous suggestion)
Remove the previous token when a new page is visited.
Why does this need to happen at all?
From the code snippet you posted you are attempting to use this to dispose of objects server side? You are supposed to call Dispose to free up any un-managed resources your objects are using (such as Database connections).
This should be done during the processing of each request. There shouldn't be any un-managed resources awaiting a dispose when the client closes the browser window.
If this is the way you are attempting this in the manner noted above the code needs to be reworked.
Have you tried onbeforeunload()?
$(window).bind('beforeunload', function()
{
alert('unloading!');
}
);
or
window.onbeforeunload = function() {
alert('unloading!');
}
From the comment you made to #Frazzell's answer it sounds like you are trying to manage concurrency. So on the chance that this is the case here are two common method for managing it.
Optimistic concurrency
Optimistic concurrency adds a timestamp to the table. When the client edits the record the timestamp is included in the form. When they post their update the timestamp is also sent and the value is checked to make sure it is the most recent in the table. If it is, the update succeeds. If it is not then someone else got in sooner with an update so it is discarded. How you handle this is then up to you.
Pessimistic concurrency
If you often experience concurrency clashes then pessimistic concurrency may be better. Here when the client edits the record a flag is set on that row to lock it. This will remain until the client completes the edit and no other user can edit that row. This method avoids users loosing changes but add an administration over head to the application. Now you need a way to release unwanted locks. You also have to inform the user through the UI that a row is locked for edit.
In my experience it is best to start with optimistic concurrency. If I have lots of people reporting problems I will try to find out why people are having these conflicts. It maybe that I have to break down some entities in to smaller types as they have become responsible for doing too many jobs.
This wont work and even if you are able to somehow make it work it will give you lots of headaches later on, because this is not how the browser/HTTP is supposed to be used. When the page is unloading (in browser) the browser will call the unload event and then unload the page (you cannot make it wait, not even my making sync ajax calls) and in case the call was going on and the browser after executing the code unload the page, the call will also get cancelled and thats why you see the call on server sometimes and sometimes it doesn't work. If you could tell use why you want to do this we could suggest you a better approach.
You can't. The only thing you can do is prompt the user to stay and hope for the best. There are a whole host of security concerns here.

JQUERY or JS is there a way to detect anytime the Window is loading? Basically any network activity?

Is there a way with JQUERY or Javascript, to detect anytime the browser window is loading something, making an ajax call, loading an image, etc... Basically any network activity?
Something along the lines of this jQuery (put in the HEAD) should work.
var loading = true;
$(window).load(function () {
loading = false;
}).ajaxStart(function () {
loading = true;
}).ajaxComplete(function () {
loading = false;
});
Read up on ajaxStart for more details.
My answer below and the previous users' answers are only attempting to check if the browser is currently making an XmlHttpRequest (i.e. ajaxy) request.
You asked if you could tell if the browser was making any network request (i.e. downloading images/css or perhaps a long running 'comet' request). I don't know of any javascript API that would tell you this - they may exist but I suspect that if they do then they would be browser specific [if anyone out there knows the answer to this please chip in]. Obviously tools like Firebug and dynaTrace can detect network activity but I think these tool "hook in" to the browser a lot deeper down than javascript code.
Having said all that, if you want to count XHRs spawned by jQuery then dave1010's answer seems like a good one.
However I think it is prone to some race condition problems : -
According to the docs (http://api.jquery.com/ajaxStart/)
Whenever an Ajax request is about to be sent, jQuery checks whether there are any other outstanding Ajax requests. If none are in progress, jQuery triggers the ajaxStart event. Any and all handlers that have been registered with the .ajaxStart() method are executed at this time.
So if a long running XHR was started and another one was started before the first had completed, the ajaxStart handler would only be called once. The 2nd XHR could complete before the first one and set loading = false, even though the first request is still in progress.
Looking at the jQuery 1.4 source seems to confirm this. Interestingly, jQuery 1.4 has a count of active XHRs (jQuery.active) but this is not mentioned in the docs and so it is probably best not to use it (which is a pity because it would make life a bit easier).
See http://gist.github.com/277432#LID5052 for the code that checks to see that $.active is 0 before invoking ajaxStart handlers.
[I think] The 'ajaxSend' global event handlers are called before each and every XHR. Using this in preference to 'ajaxStart' should help but we will still need to keep a count of active requests as opposed to a simple "loading" flag.
Perhaps something like the following will work?
var activeXhrCount = 0;
$(document).ajaxSend(function() {activeXhrCount++;}).ajaxComplete(function(){activeXhrCount--;});
Be aware that this will give incorrect answers if any code calls $.ajax with the global option set to false and so is hardly bullet proof;
Also keep in mind that activeXhrCount only counts XHRs spawned by jQuery - those from other libraries that you may utilize will not be counted.
i think you have to build some think by your self,
i did something like this before [ like when gmail shows loading upper there ]
the idea is about making an array then add/remove from it and keep checking it for know if there is an open connection
the code should look like this
var liveAjax = [];
//making ajax call
liveAjax[liveAjax.length] = true;
$.ajax({
url: 'ajax/test.html',
success: function(data) {
liveAjax[liveAjax.length] = false;
or delete liveAjax[liveAjax.length]
}
});
then checking the alive calls by
setInterval(function(){
//looping in liveAjax and check if there any true value, then there is ajax call elese nothing happens
},200);

Categories

Resources