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');
});
Related
Hello I'm trying to scroll into the div only when the submit finishes with promisses
function submitForm(form) {
console.log("submitForm: ", form);
return Promise.resolve(() => form.submit());
}
async function submitFm (form) {
console.log("submitFm: ", form);
await submitForm(form);
};
submitButton.addEventListener("click", () => {
submitFm(form).then(() => {
console.log("should display after submit is done!");
});
});
The promise is suppose to work like this, does anyone knows what's missing ?
Thanks in advance
The submit() method on a form triggers form submission (and navigation to the result).
As soon as that is triggered, the submit() function finishes.
Then the promise resolves.
Then the then function executes.
Then the browser navigates to the new page.
There is no way for JavaScript running in a web page to directly cause JavaScript to run in the next page the viewport navigates to.
Unloading the current page will kill any JavaScript running in it. The next page, whether it be on the other end of a link, or a form submission or a call to location.reload(), etc. is a blank slate. Any JS in that page runs from scratch.
If you want to cause an effect in it you need to do so by passing a message through something that will persist between page loads.
Examples include a query string on the URL or the Session Storage API.
Then you need JavaScript in the next page to check for that message, act on it, and possibly clean it up so it doesn't effect the next page load.
If you submit a form base on form action, you need to pass the state to the next page. The simpler way is that use an anchor in the URL, URL with a hashtag will scroll to the element that id is the hashtag.
e.g.
<form action="/post/data#id" method="post"></form>
If you submit based on ajax or fetch, you redirect the URL when submitted, you also use hashtags. or you can persistence your data by Storage API, and control the scroll action on the next page.
If you use SPA frameworks like Vue React or others. You can use the router API to handle URL changes on submit. or handle scroll directly when form submits success.
I have some links on the page and when user click on link, page is reloaded.
All links have some ID and all have the one same class.
I need to click on some other link after page is reloaded, but only if user click on some of the link with particular class (not anywhere, like menu link).
How I can do something like this using JS or jQuery?
It sounds like you are attempting to build a single page application, ie the application is mostly run by JavaScript instead of server side rendering. In this case page reloads are you enemy. A page reload is basically a restart of your page, and while you can keep state using cookies or localStorage, this will provide you with a rather poor user experience.
In this case, you would just add event handlers to any actions your user would take, and simply handle them in javascript without reloading the page from the server. If you need to get more data in response to the user's actions, you can use AJAX to pull that data from the server.
If you have to use links with urls (still unclear to me why that would be necessary), I would recommend using hash urls like so '#some-action' which will not reload the page when clicked. You can then attach an event handler to the link, or even listen for the url hash to change using the hashchange event. In this way you can know what link the user pressed.
If you are not trying to build a single page application, you will need to add code on the server to store the information you need in the page.
I did it.
So, I created function:
/**
* Click on delivery link after page reload
*
* #return {boolean} [loacalStorage is available]
*/
$.fn.openDelivery = function(){
if (localStorage) {
var addedToCart = localStorage["addCart"];
if (addedToCart) {
setTimeout(function() {
$('#showRight').trigger('click');
}, 1500);
localStorage.removeItem("addCart");
}
$(this).click(function(e) {
localStorage["addCart"] = true;
});
return true;
}
return false;
};
And then called that function:
$(document).ready(function () {
// Trigger delivery click
$('.class-of-my-link').openDelivery();
});
In my case, page reloads after user add some item in shopping cart. With this function I click on link (with 1.5s delay) that opens cart of the user that is shown on the right side of the screen.
I have research this topic through the community, although I cannot find an answer. I am using Bronto's direct add feature (attempting to use it), The documentation isn't that great.
In summary, the href link subscribes the user on the email list. The only problem is that this link opens a new page. When I want the user to stay on the same page. I though about doing a redirect, when clicking the link, though I am not sure if that would work.
I have tried this:
//Html
<a id="subscription" href="http://example.com">Subscribe</a>
// Jquery
$("#emailsubscribe").click(function(e){
e.preventDefault();//this will prevent the link trying to navigate to another page
//do the update
var href = "http://example.com";
//when update has finished, navigate to the other page
window.location = "href";
});
The goal is that I am trying to make it where the user clicks on the link, it subscribes them to the email list, but immediately redirects them back, without opening another window.
You're looking for AJAX. This allows you to make requests without actually navigating to a page. Since you're using jQuery
$("#emailSubscribe").click(function (e) {
e.preventDefault();
$.get("http://www.myurl.com", function (data) {
//All done!
});
});
You have 3 options:
Do an AJAX request to subscribe the user
$('#emailsubscribe').on('click', function () {
$.get('/email-subscribe/' + USER_ID, function () {
// redirect goes here
window.location = 'REDIRECT_URL';
});
});
Use an iframe and when the iframe has loaded close the iframe (ugly, hacky, not recommended)
Have the subscribe page redirect the user back. Aka do the common messages of "You have been subscribed. Redirecting back in 5seconds...". You would need to pass the redirect link to the subscribe page, aka
window.location = '/subscribe/USER_ID?redirect_to=/my-redirect-page'
You need to refer the var, instead of typing another string to redirect.
//Html
<a id="subscription" href="http://example.com">Subscribe</a>
// Jquery
$("#emailsubscribe").click(function(e){
e.preventDefault();//this will prevent the link trying to navigate to another page
//do the update
var href = "http://example.com";
//when update has finished, navigate to the other page
window.location = href; //<<<< change this.
});
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.
Here is the situation :
If I am in page-1 now I am clicking a link from page-1 to navigate to page-2. Before page-2 is loaded I am hitting escape so that still I am staying in page-1.
At that point I want to track that event.
Is there any JavaScript event so that I can track the above scenario?
More Info :
To avoid concurrent request to the "page-2", when the user clicks a link from page-1 I am redirecting to page-2 and disabling the link (to avoid multiple request to "page-2). At this point when we hit Esc and abort loading page-2, I need to enable the link again in page-1.
I tried using this code:
<html>
<head>
<script>
document.onkeypress = KeyPressed;
function KeyPressed(e)
{
if (!e) e = window.event; //IE Compatibility
alert(e.keyCode);
}
</script>
</head>
<body>
Stack Overflow
</body>
</html>
It detects any key pressed while you're on the page. Once you click on the SO link and hit escape, nothing happens. The browser is already receiving a response from the SO server and is starting to process it, this page has already been "left", despite appearances when you see "Waiting for http://stackoverflow.com" in your browser's status bar.
Your idea of handling this event is plain wrong. Blocking the button is required to make the user unable to do double post data. However, the request is sent instantaneously(!) after the click on the link.
So, if you click the link once, stop the page, then click second time - it will submit it twice, and that is not what is intended to happen.
Two events are triggered when the page unloads.
window.onUnload
window.onBeforeUnload
You can use these events to cancel the unload of the page, however after that, there page is considered done.
What you can do is make the page wait 5 secs or so before going to the new page:
eg:
window.onunload = (function() {
var time = new Date();
var cancel = false;
window.onkeypress = function (e) {
if ((e || window.event).keyCode == 27) cancel = true;
};
while(time > new Date() - 5000) {
if (cancel) return false;
}
});
In fact that may cause some browsers to hang since you're taking up all process time given to the JS script. ie: in the while block.
You could probably avoid that by doing a blocking function call, that isn't so process intensive, like one that is bound by network latency. eg: XMLHttpRequest() etc. I don't think calls that are queued such as setTimeout() will work here, as they don't block.
Since the <a href> tag tells the browser to move to another page, it's up to it to decide if it will still have your script running. If I were it, I wouldn't listen.
If you want to override that, I guess you should tell the browser not to listen to that particular onClick event, and put a callback in place that loads the target page in the background. This assures your page is still active. After the target page has loaded (by your script), you could kindly ask the browser to update itself with the received content.
So that's the theory. I have no idea if the DOM lets you just override the content of a loaded page, but I guess it does.