I am looking to check if a page has been refreshed or closed with jQuery or javascript.
What I have currently is I have some database values that I want to delete if the user either navigates away or refreshes the page.
I am using AJAX calls to delete the values.
Right now, I have the following code:
The handler:
window.beforeunload = cleanUp;
The cleanUp() method:
function cleanUp() {
// Check to see if it's an actual page change.
if(myActualLeave) {
$.ajax({
type: "POST",
url: "/api/cleanup",
data: { id: myLocalId },
success: function (data) {
console.log(myLocalId + " got removed from the database.");
}
});
}
// Reset the flag, so it can be checked again.
myActualLeave = true;
}
Where myActualLeave is a flag that I set to false when AJAX calls are made, so they don't trigger the beforeunload handler.
The problem I am running into is that when I click a link on my page, so for instance a link to Google, the window.beforeunload doesn't trigger. I may have a misunderstanding of this, but I have tried using jQuery's $(window).unload(...); and the onbeforeunload trigger as well.
What should I use to call javascript when:
the user refreshes the page,
when the user navigates away from the page, or
when the user closes the page?
Edit: It came up in a comment that I could use a click() jQuery handler to detect navigating away. I should have made it more specific that I don't mean when the user clicks a link only then I want it to proc. I want it to trigger when they change pages in any way. So if the address bar gets typed in, for instance.
You should try "onbeforeunload" :
window.onbeforeunload
But i think you can't put "active" (ajax call) code in this callback function. All you can do is defining a confirm modal window that will be displayed to the user before leaving like :
Are you sure you want to leave because...
So you should do as #Leeish said : put a code in the .on('click') of the link so it can launch the ajax call before sending to another page.
But for the "refresh" or "close" scenario, you can consider marking your database row as "draft" (or whatever) and if not saved when on the next page, delete the draft line.
Related
I am working on a site that has multiple links to other sites. What I want is to send an ajax call to report that the user is going away when someone clicks and navigates away from the page. I put an alert on click of the links, which works but for some reason the controller never gets the ping.
Any assistance will be appreciated on how to achieve it.
Can't be done.
When you go to navigate away, there is only one event that can catch that, the onbeforeunload event, and that is quite limited in what it can do.
Not to mention there are other ways of leaving the page without navigating away:
Losing network connection
Closing the browser.
Losing power.
The only thing you can do is to set up a heartbeat kind of thing that pings the server every so many milliseconds and says 'I'm Alive.'
Depending on what you are trying to do, there is usually a better option, however.
You can try to simply set click event handler which will check the href attribute of every link before navigating. If it goes to another website, the handler sends AJAX request and then (after server responding) redirects to the page.
var redirect = '';
$('a').click(function() {
if (this.href.host != document.location.host) {
if (redirect) return false; // means redirect is about to start, clicking other links has no effect
redirect = this.href;
$.ajax({
url: '/away',
success: function(){document.location.href = redirect;}
});
return false;
});
However it can't work properly, if user has opened your page in multiple tabs.
The only reliable way to do this these days is by hooking (i.e. add event listener) your code in so called sendBeacon method from Beacon API on beforeunload event (i.e. when user tries to navigate away from page).
The navigator.sendBeacon() method asynchronously sends a small amount of data over HTTP to a web server. It’s intended to be used for sending analytics data to a web server, and avoids some of the problems with legacy techniques for sending analytics, such as the use of XMLHttpRequest:
<script>
var URL = 'https://your.domain/your-page.php';
// on 'beforeunload'
window.addEventListener('beforeunload', function (event) {
navigator.sendBeacon(URL);
// more safely is to wait a bit
var wait_until = new Date().getTime() + 500;
while (new Date().getTime() <= wait_until);
});
</script>
You can try:
$(window).on('beforeunload', function(){
return "This should create a pop-up";
});
You can achieve it by capturing clicks on all the links on the page (or all the relevant links) and then call ev.preventDefault() on it to prevent the browser from navigating directly to that page.
Instead, you can make an AJAX call to your server and when that call returns, you can set window.location to the URL the user was trying to navigate to.
Here is a workaround you could try.
At the loading of the page, use jquery to move all href attributes to tempHref attribute. Then, attach a method to catch the click event.
This way, clicking on the links will not automatically move to the intended destination.
When the click occurs, simply perform the ajax call, and then using javascript, move to the other page.
$('a').each(function () {
var link = $(this);
link.attr('tempHref', link.attr('href'));
link.removeAttr('href');
});
$(document).on('click', 'a', function ()
{
//perform ajax call;
location.href = $(location).attr('tempHref');
});
I use such code to catch users clicks:
Event.observe(document, 'click',function(e){
var x = Event.pointerX(e);
var y = Event.pointerY(e);
//exec data storage over ajax
}
The problem is when the user click some link, the next function don't have time to execute entirely and I can't save the click data before redirect to the clicked link.
I saw some jquery implementation, but I don't use jquery.
If you must execute a function before the redirect you need to override the default action of the link, once your function finishes executing then call the redirect manually.
Im guessing its the ajax that needs to complete before redirecting? If so then you need to add the redirect in the callback function of your ajax.
I have a single page application written in MVC4 that uses pjax() to push html into various s in my page. I have one sub-form that allows the user to edit the data and it if the user changes the data an isDirty flag gets set in javascript to trigger an alert at the bottom of the page that there are un-saved updates. I would also like to implement an additional warning when the user tries to leave the page without saving. If I use a traditional onbeforeunload function like this
window.onbeforeunload = function() {
if (isDirty) {
return 'You have unsaved changes!';
}
return null;
};
it calls the alert if I try to close the page or navigate away from the site entirely but if the user clicks on one of my links that re-populates the with some different information it does not trigger because you are not actually leaving the page. How can I architect it so that one of these pjax() links causes an alert similar to if I close the page?
You could subscribe to a global event that fires before a pjax request:
$(document).on('pjax:beforeSend', function() {
if (isDirty) {
return confirm('You have unsaved changes! Are you sure you want to continue?');
}
return true;
});
You could add a delegated event handler onto the links in the page. You just have to make sure the handler is bound to links that may load a "new page".
I'm looking for a way to automatically set the user status as "offline" and to do this I need to execute a JavaScript function, unless there are any better ideas out there. How can I run a function when the user tries to navigate away from the page? I know there is a way to have a message box appear so there should be a way to do this.
Use the unload method to call an ajax method. Note the important async attribute which says to the browser that it needs to wait the HTTP response before closing the window (to ensure that your server received the "offline" status).
$(window).unload(function() {
$.ajax({
url: "setoffline.php",
async: false
});
});
Try using this one.
<body onbeforeunload="return RunOnClose()">
function HandleOnClose() {
//do your magic here
return true;
}
The follow event fires when the window "unloads":
window.onbeforeunload
I have paired that with an onload event handler in a similar scenario, where I had a row in my DB tracking the user Last Login Session. It had an "entered" date when they login / come to the site and I would set the "Last seen" DateTime on the onunload event, but I was also clearing the "Last seen" date time on the "onload" of the page.
So, the last time they close any page, the "Last Seen" Date is set and it persists
I have a "Save" button on a FormView with the CommandName="Update" set. This button updates an EntityDataSource that is bound to the FormView.
After the EDS is updated, I want to close this (child, popup) window and refresh my parent window (so it will reflect the changes just made to the data).
For reference, I have a similar "Cancel" button on this page that simply calls a Javascript function "OnClientClick":
function done() {
if (window.opener.closed) {
self.close();
} else {
window.opener.focus();
window.opener.location.href = opener.location;
self.close();
}
}
Now, how can I let the FormView and EDS do its thing (process the Update command) and then call this javascript function (or code to accomplish the equivalent)???
After doing some more digging, I solved it. The problem had to do with the FormView being inside an Update Panel. I had to use the following:
ScriptManager.RegisterClientScriptBlock(this.UpdatePanel1, typeof(string), "done", "done();", true);
As soon as your update is finished, it should return a page that you can just register your function with. In your Update command handler (assuming this is happening server side), just add the following:
Page.RegisterStartupScript("AfterUpdate", "done();");
It will cause the done() javascript function to run as soon as the windows refreshes from the postback caused by the update command. If you done function isn't already in the page, make sure you add it's definition before you call it to the RegisterStartupScript call.