$(window).on('unload', ... prevents url change - javascript

I am trying to execute a function when the user tries to change url, close tab etc. The issue is that when user refreshes/clicks on hyperlink/changes url, the url is updated but the page remains exactly the same.
The problem is especially severe with latest Firefox (did not notice it before for some reason). Chromium on the other hand will wait a few seconds before closing the tab, giving it an awkward, laggy feeling.
The code as it is:
$(window).on('unload', function() {
$.ajax({
type: 'POST',
url: 'ajax/whattodo.php',
async: false,
data: {
method: 'iquit',
exitdata1: exitdata1,
exitdata2: exitdata2
}
});
});
If I remove "async:false" the problem is no longer there. But neither are functions executed. What to do?
The page not redirecting is especially annoying, and confusing for the user.

Related

Ajax call on onbeforeunload event doesn't work (Firefox only)

I need to make an Ajax call when a user leaves my page.
I don't need to wait for the end of the call, I just need to notify my server with a kindly "hey, user XXX is leaving the page", without notifying the client.
Here is what I've done so far :
window.onbeforeunload = function () {
$.ajax({
type: "POST",
url: myURL,
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ xxx: xxx, yyy: yyy })
});
}
This perfectly works with Chrome and Edge, but this event is not raised on Firefox.
What I've done so far :
I tried this SO answer, as the author claims it works and has a good score, but once again, my ajax call is not fired.
Add async: false without any success
Also tried to use beforeunload instead of onbeforeunload
Can anyone explain me how to fire my Ajax call when an user leaves a page, no matter he uses Chrome, Edge or Firefox ?
Thanks in advance ?

window.open doesn't work in http post angular

Here's my code:
$rootScope.http({
url: myUrl,
method: "POST",
data: "",
}).success(function (data) {
alert(data.uri); //for test, and I see correct uri shows up here.
window.open(data.uri, ''); return false; //window doesn't open.
});
The window.open doesn't work inside the .success, but it does work outside the http post method. Something is wrong when comes to callback function. I met very same issue in $.ajax and fixed it. But same solution doesn't work here for angular.
We faced the similar problem before and the reason is simple; in the most of the modern browsers, browsers will not allow the window.open() call which are not the direct result of user activity.
Here, your window.open() is being triggered in an asynchronous call which is not being called by a user action, for example: clicking on a link or a button.
You can fix this problem by disabling the popup blocker but we have to notify the user that their popup blocker is enabled. For that, you can do something like this:
$rootScope.http({
url: myUrl,
method: "POST",
data: "",
}).success(function (data) {
$rootScope.popupWindow = window.open(data.uri, '');
$timeout(function() {
// Check if popup blocker is enabled by verifying the height of the new poup
if (!$rootScope.popupWindow || $rootScope.popupWindow.outerHeight === 0) {
alert("Please disable the popup blocker");
}
}, 1000);
});
(Note: I've tested this is a browser, not sure in the mobile but this should work)

Is javascript not executed on mobile devices if the page is not currently shown?

I'm tracking the time users spend reading contents on my website. To consider the user is actually reading, I do a first ajax request after 10 seconds the page has been loaded. Then, I set the beforeunload event to trigger another ajax request to notice the user has finished reading.
There is a problem when the user opens another page in a different tab, but the page I'm tracking is not closed, so I set I timer after 10 min to trigger the end reading ajax and unset the beforeunload. This makes browsers to send the signal when the page is open, but the tab hasn't been closed.
However, I've noticed that on mobile devices (Android, iPhone and iPad), the timer set to automatically notice finish reading after 10 min doesn't get executed. So, I'm wondering if: do mobile devices stop executing javascript when the page is not shown on the screen to save battery? If so, how could I run the timer and trigger the ajax request even though the page is not shown (but still open)?
function endReading(id) {
$.ajax({
url: "{% url 'end_read_content' %}",
type: "post",
data: {"id": id},
async: false,
});
}
setTimeout(function() {
$.ajax({
url: "{% url 'new_read_content' %}",
type: "post",
data: {"content_slug": "{{ content.slug }}"},
success: function(data) {
$(window).on('beforeunload', function() {endReading(data)});
setTimeout(function() {
endReading(data);
$(window).off('beforeunload');
}, 600000);
}
});
}, 10000);
Instead of setTimeout use requestAnimationFrame
https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame
By specification this function will not call when the window is not in focus.
http://caniuse.com/requestanimationframe
More details here:
http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
It is passed an int of the current running time, so your function should check that and only send an ajax request every so many seconds.
In response to the 'can I use this for not animations' question:
Absolutely you can use it for whatever you want. Another option
var lastUsageTime = 0;
var lastSentTime = 0;
window.requestAnimationFrame(function(t){
lastUsageTime = t;
});
setTimeout(function(){
if(lastUsageTime - lastSentTime > 10000){
//do ajax
lastSentTime = lastUsageTime
}
});

Could it be, that Chrome cancels pending Ajax requests, once the browser is being redirected to another URL?

I have this function to unlock a list the user is currently editing:
function unsetLock(id) {
$.ajax({
type: "POST",
url: "/ajax.php?action=unsetLock",
dataType: 'json',
data: "id="+ id
});
return true;
}
When the user navigates away from the list, I have to cancel the lock:
unsetLock(lockID);
document.location.href='/page/to/navigate/back/to.php';
However this unlock sometimes works and sometimes doesn't. I think it is because document.location.href is executed, before the ajax call has actually been sent to the server.
How can I force to send the unlock before navigating the user to the next page?
Actually I don't need to wait for the Ajax-Reply, since I want to redirect the user, whether it succeeds, or not. I just want to make sure, it is being transferred to the server.
If I place the document.location.href inside the Ajax function, it will wait for the reply.
A really bad-mannered way to do it is to add: async: false, which will lock the browser up until the AJAX call is complete.
Of course, if there is a problem and the AJAX call never completes...
It's the quickest and easiest solution to your problem, but probably not the best.
I, personally, would have the lock only last for twenty seconds (using a timestamp in the database), and send an ajax call every ten seconds to re-lock the page (if that makes sense) using setInterval().
That way the lock will unset itself a few seconds after someone leaves the page, and is good no matter what the situation (a power failure for the client wouldn't leave the page locked forever, for example).
Perhaps I'm missing something, but why not use the success option in the Ajax call? This will execute whatever the outcome and makes sure it reaches the server.
function unsetLock(id) {
$.ajax({
type: "POST",
url: "/ajax.php?action=unsetLock",
dataType: 'json',
data: "id="+ id,
success: function(){
document.location.href='/page/to/navigate/back/to.php';
}
});
return true;
}

process a page on UnLoad?

I need for a php file to process when the user click a link/go back/exits a page. Its part of a saving user info process. if i do a jquery unload how would I fire the php file to load and process.
jQuery(window).bind("unload", function() {
// what should i add?
});
$(document).ready(function() {
$(':input',document.myForm).bind("change", function() {
setConfirmUnload(true);
}); // Prevent accidental navigation away
});
function setConfirmUnload(on) {
// To avoid IE7 and prior jQuery version issues
// we are directly using window.onbeforeunload event
window.onbeforeunload = (on) ? unloadMessage : null;
}
function unloadMessage() {
if(Confirm('You have entered new data on this page. If you navigate away from this page without first saving your data, the changes will be lost.')) {
$.ajax({
type: "POST",
url: "some.php",
data: "name=John&location=Boston",
success: function(msg){
alert( "Data Saved: " + msg );
}
});
}
}
Make sure you have upgraded version of jQuery. jQuery version 1.3.2 had a bug:
Ticket #4418: beforeunload doenst work correctly
Or use native function:
window.onbeforeunload = function() {....}
I'm guessing a synchronous AJAX call might work.
$.ajax({
async: true,
url: '/foo/',
success: function(data) {
// Finished.
}
});
Of course, keep in mind there's no guarantee any of this will ever happen. My browser may crash. My computer may even power down. And of course I may disable JavaScript. So you'll definitely need a server-side way of handling this in case the convenient JavaScript technique doesn't actually work.
You should use the beforeunload event. You can fire a synchronised ajax request in there.
$(window).bind('beforeunload', function() {
$.ajax({
url: 'foo',
async: false,
// ...
});
});
Be aware that onbeforeunload is not supported by some older browsers. Even if this technique works, I'm not sure how long you can (should?) block this event. Would be a pretty bad user experience if that request would block a few seconds.
A good trade-off is probably to tell the user that something has changed what was not saved yet. Do this with a few boolean checks and finally return a string value in the onbeforeunload request. The browser will then gracefully ask the user if he really wants to leave your site, also showing the string you provided.

Categories