I have this code:
(function() {
window.onbeforeunload = function () {
alert("hi")
console.log("unloading");
};
})();
I also have this code:
window.addEventListener("beforeunload", function() {
alert("hi")
console.log("unloading")
});
None of them seem to work. All I want to do is log when the user tries to leave the page, but this isn't happening (latest Chrome, latest Firefox, Edge....), can anybody shed some light on why it's not working?
Since 25 May 2011, the HTML5 specification states that calls to
window.alert(), window.confirm(), and window.prompt() methods may be
ignored during this event. See the HTML5 specification for more
details.
Note also that various mobile browsers ignore the result of the event
(that is, they do not ask the user for confirmation). Firefox has a
hidden preference in about:config to do the same. In essence this
means the user always confirms that the document may be unloaded.
Source
Also, use return statement to prompt user before leaving
window.addEventListener("beforeunload", function() {
return "hi";
});
Do it this way:
window.onbeforeunload = function (e) {
console.log("unloading");
return "Hi";
};
That will alert Hi when page unloads and also prints unloading in console
function myFunction() {
return "Write something clever here...";
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body onbeforeunload="return myFunction()">
</body>
You have to return from the onbeforeunload:
(function() {
window.onbeforeunload = function () {
alert("hi")
console.log("unloading");
return null;
};
})();
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is there a way to detect if a browser window is not currently active?
I have a function that is called every second that I only want to run if the current page is in the foreground, i.e. the user hasn't minimized the browser or switched to another tab. It serves no purpose if the user isn't looking at it and is potentially CPU-intensive, so I don't want to just waste cycles in the background.
Does anyone know how to tell this in JavaScript?
Note: I use jQuery, so if your answer uses that, that's fine :).
In addition to Richard Simões answer you can also use the Page Visibility API.
if (!document.hidden) {
// do what you need
}
This specification defines a means for site developers to
programmatically determine the current visibility state of the page in
order to develop power and CPU efficient web applications.
Learn more (2019 update)
All modern browsers are supporting document.hidden
http://davidwalsh.name/page-visibility
https://developers.google.com/chrome/whitepapers/pagevisibility
Example pausing a video when window/tab is hidden https://web.archive.org/web/20170609212707/http://www.samdutton.com/pageVisibility/
You would use the focus and blur events of the window:
var interval_id;
$(window).focus(function() {
if (!interval_id)
interval_id = setInterval(hard_work, 1000);
});
$(window).blur(function() {
clearInterval(interval_id);
interval_id = 0;
});
To Answer the Commented Issue of "Double Fire" and stay within jQuery ease of use:
$(window).on("blur focus", function(e) {
var prevType = $(this).data("prevType");
if (prevType != e.type) { // reduce double fire issues
switch (e.type) {
case "blur":
// do work
break;
case "focus":
// do work
break;
}
}
$(this).data("prevType", e.type);
})
Click to view Example Code Showing it working (JSFiddle)
I would try to set a flag on the window.onfocus and window.onblur events.
The following snippet has been tested on Firefox, Safari and Chrome, open the console and move between tabs back and forth:
var isTabActive;
window.onfocus = function () {
isTabActive = true;
};
window.onblur = function () {
isTabActive = false;
};
// test
setInterval(function () {
console.log(window.isTabActive ? 'active' : 'inactive');
}, 1000);
Try it out here.
Using jQuery:
$(function() {
window.isActive = true;
$(window).focus(function() { this.isActive = true; });
$(window).blur(function() { this.isActive = false; });
showIsActive();
});
function showIsActive()
{
console.log(window.isActive)
window.setTimeout("showIsActive()", 2000);
}
function doWork()
{
if (window.isActive) { /* do CPU-intensive stuff */}
}
All of the examples here (with the exception of rockacola's) require that the user physically click on the window to define focus. This isn't ideal, so .hover() is the better choice:
$(window).hover(function(event) {
if (event.fromElement) {
console.log("inactive");
} else {
console.log("active");
}
});
This'll tell you when the user has their mouse on the screen, though it still won't tell you if it's in the foreground with the user's mouse elsewhere.
If you are trying to do something similar to the Google search page when open in Chrome, (where certain events are triggered when you 'focus' on the page), then the hover() event may help.
$(window).hover(function() {
// code here...
});
I am developing an online testing app and it is required that during the test, users cannot be allowed to refresh page neither go back until the test is ended. I have successfully been able to disable refresh action in jquery through all means possible (to the best of my knowledge) using the following code:
$(window).bind({
beforeunload: function(ev) {
ev.preventDefault();
},
unload: function(ev) {
ev.preventDefault();
}
});
But I have been having troubles disabling the back action on all browsers, the best solution I got on SO conflicts with the code I have above, it is given below:
window.onload = function () {
if (typeof history.pushState === "function") {
history.pushState("jibberish", null, null);
//alert("Reloaded");
window.onpopstate = function () {
history.pushState('newjibberish', null, null);
// Handle the back (or forward) buttons here
// Will NOT handle refresh, use onbeforeunload forthis.
};
}
else {
var ignoreHashChange = true;
window.onhashchange = function () {
if (!ignoreHashChange) {
ignoreHashChange = true;
window.location.hash = Math.random();
// Detect and redirect change here
// Works in older FF and IE9
// * it does mess with your hash symbol (anchor?) pound sign
// delimiter on the end of the URL
}
else {
ignoreHashChange = false;
}
};
}
}
The solution above suits my purpose in disabling the back button but conflicts with the page refresh prevention handler above.
I am out of ideas on what to do and I have also searched a long time for a solution to this but found none yet. Any help would be greatly appreciated, even if it takes a totally different approach to solving the problem, I wouldn't mind at all.
Thanks everyone
UPDATE
I never realized that doing things this way breaks a lot of ethical rules, anyway, I've thought about it and figured out something else to do when if the page is refreshed or back button pressed (either using keyboard or the browser controls). I want to redirect to a url which will end the current exam session. I believe that's possible, hence I think the solution I seek is to get the best way to achieve this. Redirecting to another url if back button or refresh button is pressed (both using the browser controls and the keyboard).
I have tried many options but none worked except this-
//Diable Browser back in all Browsers
if (history.pushState != undefined) {
history.pushState(null, null, location.href);
}
history.back();
history.forward();
window.onpopstate = function () {
history.go(1);
};
With regards to the update I posted in my question, I have been able to solve my problem. Here's what I did (just modifying my existing code a little and removing the window.onload listener I had initially):
$(window).bind({
beforeunload: function(ev) {
window.location.replace("my_url_goes_in_here");
},
unload: function(ev) {
window.location.replace("my_url_goes_in_here");
}
});
This construct works for both page refresh and back actions done in anyway (either using keyboard or browser controls for the any of them).
However, I've not yet tested in any other browser other than firefox 47.0, but I'm glad it's working for now all the same.
Thanks for all your comments, they were extremely helpful
Using javascript if you have two pages page1 and page2 and (page1 redirect to page2) and you want to restrict the user from getting back to page1, just put this code at page1.
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/jquery-ui.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
$(document).ready(function () {
function disableBack() {
window.history.forward()
}
window.onload = disableBack();
window.onpageshow = function (evt) {
if (evt.persisted)
disableBack()
}
});
</script>
In last days I noticed that the confirmation alert that I supposed to see before leaving my website page is no more shown on Chrome and Firefox, but it's displayed on IE.
If I debug with Google Chrome Dev Tools, I can see that function confirm is executed, enters the if statement, but no alert box is displayed. I tried to restart Google Chrome and look for an option to reset alert messages, but I didn't find nothing.
Any ideas?
The code is this:
if (window.addEventListener) {
window.addEventListener('beforeunload', confirm, false);
}
else window.attachEvent("onbeforeunload", confirm);
...
function confirm(e) {
if (changed== true) {
return "You haven't saved your changes!";
}
}
I've found a working solution, but actually I don't understand why the attachEvent isn't working anymore. Anyway, this is the working solution, tested on IE, Chrome and Firefox:
I removed the addEventListener and attachEvent lines:
/* if (window.addEventListener) {
window.addEventListener('beforeunload', confirm, false);
}
else window.attachEvent("onbeforeunload", confirm); */
In the HTML, I add the attribute onbeforeunload to the body tag:
<body onbeforeunload="return confirmEvent()">
I also renamed the onbeforeunload function to avoid confusion with the confirm built-in javascript function:
function confirmEvent(e) {
if (changed== true) {
return "You haven't saved your changes!";
}
}
See https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload
window.addEventListener("beforeunload", function (e) {
var confirmationMessage = "\o/";
e.returnValue = confirmationMessage; // Gecko and Trident
return confirmationMessage; // Gecko and WebKit
});
Worked in every Browser i tested ;)
PS: I know its a little bit late
Problem:
You have a regular set of URL links in a HTML page e.g.:
Foo Bar
You want to create a JavaScript function such that when any HTML links are clicked, instead of the client's browser navigating to that new URL "/foo/bar" a JavaScript function is executed instead (e.g. this may for example make an Ajaxian call and load the HTML data without the need to reload the page).
However if the JavaScript is disabled OR a spider crawls the site, the UTL links are maintained gracefully.
Is this possible? Does it already exist? What's the usual approach?
EDIT 1:
These are some great answers!
Just a follow on question:
If the user clicks on the back button OR forward button, this would naturally break (as in it would go back to the last physical page it was on as opposed to one that was loaded).
Is there any way (cross browser) to maintain the back/forward buttons?
(e.g create an array of links clicked and over ride the browser buttons and use the array to navigate)?
<script type="text/javascript">
function your_function() {
alert('clicked!');
}
</script>
<a onclick="your_function();" href="/foo/bar">Foo Bar</a>
If Javascript is off, the link behaves normally.
In this case, unless your_function() does not return false, the link will be followed when clicked as well.
To prevent this, either make your_function() return false, or add return false; just after the function call in your onclick attribute:
<script type="text/javascript">
function your_function() {
alert('clicked!');
return false;
}
</script>
<a onclick="your_function();" href="/foo/bar">Foo Bar</a>
Or:
<script type="text/javascript">
function your_function() {
alert('clicked!');
}
</script>
<a onclick="your_function(); return false;" href="/foo/bar">Foo Bar</a>
Using element.addEventListener()
With default anchor behaviour following click:
<script type="text/javascript">
document.addEventListener("load", function() {
document.getElementById("your_link").addEventListener("click", function() {
alert('clicked');
}, true);
}, true);
</script>
<a id="your_link" href="/foo/bar">Foo Bar</a>
Without:
<script type="text/javascript">
document.addEventListener("load", function() {
document.getElementById("your_link").addEventListener("click", function(event) {
event.preventDefault();
alert('clicked');
}, true);
}, false);
</script>
<a id="your_link" href="/foo/bar">Foo Bar</a>
Given current HTML and W3C APIs, I would go for:
<script src="linkify.js"> </script>
in the markup, with linkify.js containing something like:
window.onload= function() {
document.addEventListener('click', function(ev) {
ev.preventDefault();
var el = ev.target;
if (el.tagName === 'A') {
// do stuff with el.href
}
}, false);
};
See e.g. http://jsfiddle.net/alnitak/nrC7G/, or http://jsfiddle.net/alnitak/6necb/ for a version which doesn't use window.onload.
Note that this code uses a single listener function registered on the document object, which will act on every <A> tag on the page that doesn't trap clicks for itself.
Use an onclick attribute:
click?
The return false prevents the default behaviour, in the absence of JavaScript, however, the link will be followed.
function do_whatever (e)
{
e.preventDefault ();
// do whatever you want with e.target
}
var links = document.getElementsByTagName ("a");
for (var i=0; i<links.length; ++i)
links[i].addEventListener ('click', do_whatever);
http://jsfiddle.net/bTuN7/
All done inside script and it won't 'hurt' if JavaScript doesn't work.
If you think about AJAX, then you have to know, that googlebot tries to parse it. http://www.youtube.com/watch?v=9qGGBYd51Ts
You can code like:
$('a').click(function() {
doSomethingWithURL($(this).attr('href'));
return false;
});
JavaScript is not executed in case it's disabled or if it's some web crawler, so from my point of view this is preferable.
There's quite a few methods out there such as this:
http://www.malbecmedia.com/blog/development/coding-a-ajax-site-that-degrades-gracefully-with-jquery/
Remember, though, that by virtue of a well setup server and caching you're not going to gain yourself much performance with an Ajax Load.
Here in stackoverflow, if you started to make changes then you attempt to navigate away from the page, a javascript confirm button shows up and asks: "Are you sure you want to navigate away from this page?" blee blah bloo...
Has anyone implemented this before, how do I track that changes were committed?
I believe I could do this myself, I am trying to learn the good practices from you the experts.
I tried the following but still doesn't work:
<html>
<body>
<p>Close the page to trigger the onunload event.</p>
<script type="text/javascript">
var changes = false;
window.onbeforeunload = function() {
if (changes)
{
var message = "Are you sure you want to navigate away from this page?\n\nYou have started writing or editing a post.\n\nPress OK to continue or Cancel to stay on the current page.";
if (confirm(message)) return true;
else return false;
}
}
</script>
<input type='text' onchange='changes=true;'> </input>
</body>
</html>
Can anyone post an example?
Update (2017)
Modern browsers now consider displaying a custom message to be a security hazard and it has therefore been removed from all of them. Browsers now only display generic messages. Since we no longer have to worry about setting the message, it is as simple as:
// Enable navigation prompt
window.onbeforeunload = function() {
return true;
};
// Remove navigation prompt
window.onbeforeunload = null;
Read below for legacy browser support.
Update (2013)
The orginal answer is suitable for IE6-8 and FX1-3.5 (which is what we were targeting back in 2009 when it was written), but is rather out of date now and won't work in most current browsers - I've left it below for reference.
The window.onbeforeunload is not treated consistently by all browsers. It should be a function reference and not a string (as the original answer stated) but that will work in older browsers because the check for most of them appears to be whether anything is assigned to onbeforeunload (including a function that returns null).
You set window.onbeforeunload to a function reference, but in older browsers you have to set the returnValue of the event instead of just returning a string:
var confirmOnPageExit = function (e)
{
// If we haven't been passed the event get the window.event
e = e || window.event;
var message = 'Any text will block the navigation and display a prompt';
// For IE6-8 and Firefox prior to version 4
if (e)
{
e.returnValue = message;
}
// For Chrome, Safari, IE8+ and Opera 12+
return message;
};
You can't have that confirmOnPageExit do the check and return null if you want the user to continue without the message. You still need to remove the event to reliably turn it on and off:
// Turn it on - assign the function that returns the string
window.onbeforeunload = confirmOnPageExit;
// Turn it off - remove the function entirely
window.onbeforeunload = null;
Original answer (worked in 2009)
To turn it on:
window.onbeforeunload = "Are you sure you want to leave?";
To turn it off:
window.onbeforeunload = null;
Bear in mind that this isn't a normal event - you can't bind to it in the standard way.
To check for values? That depends on your validation framework.
In jQuery this could be something like (very basic example):
$('input').change(function() {
if( $(this).val() != "" )
window.onbeforeunload = "Are you sure you want to leave?";
});
The onbeforeunload Microsoft-ism is the closest thing we have to a standard solution, but be aware that browser support is uneven; e.g. for Opera it only works in version 12 and later (still in beta as of this writing).
Also, for maximum compatibility, you need to do more than simply return a string, as explained on the Mozilla Developer Network.
Example: Define the following two functions for enabling/disabling the navigation prompt (cf. the MDN example):
function enableBeforeUnload() {
window.onbeforeunload = function (e) {
return "Discard changes?";
};
}
function disableBeforeUnload() {
window.onbeforeunload = null;
}
Then define a form like this:
<form method="POST" action="" onsubmit="disableBeforeUnload();">
<textarea name="text"
onchange="enableBeforeUnload();"
onkeyup="enableBeforeUnload();">
</textarea>
<button type="submit">Save</button>
</form>
This way, the user will only be warned about navigating away if he has changed the text area, and will not be prompted when he's actually submitting the form.
To make this work in Chrome and Safari, you would have to do it like this
window.onbeforeunload = function(e) {
return "Sure you want to leave?";
};
Reference: https://developer.mozilla.org/en/DOM/window.onbeforeunload
With JQuery this stuff is pretty easy to do. Since you can bind to sets.
Its NOT enough to do the onbeforeunload, you want to only trigger the navigate away if someone started editing stuff.
jquerys 'beforeunload' worked great for me
$(window).bind('beforeunload', function(){
if( $('input').val() !== '' ){
return "It looks like you have input you haven't submitted."
}
});
This is an easy way to present the message if any data is input into the form, and not to show the message if the form is submitted:
$(function () {
$("input, textarea, select").on("input change", function() {
window.onbeforeunload = window.onbeforeunload || function (e) {
return "You have unsaved changes. Do you want to leave this page and lose your changes?";
};
});
$("form").on("submit", function() {
window.onbeforeunload = null;
});
})
To expand on Keith's already amazing answer:
Custom warning messages
To allow custom warning messages, you can wrap it in a function like this:
function preventNavigation(message) {
var confirmOnPageExit = function (e) {
// If we haven't been passed the event get the window.event
e = e || window.event;
// For IE6-8 and Firefox prior to version 4
if (e)
{
e.returnValue = message;
}
// For Chrome, Safari, IE8+ and Opera 12+
return message;
};
window.onbeforeunload = confirmOnPageExit;
}
Then just call that function with your custom message:
preventNavigation("Baby, please don't go!!!");
Enabling navigation again
To re-enable navigation, all you need to do is set window.onbeforeunload to null. Here it is, wrapped in a neat little function that can be called anywhere:
function enableNavigation() {
window.onbeforeunload = null;
}
Using jQuery to bind this to form elements
If using jQuery, this can easily be bound to all of the elements of a form like this:
$("#yourForm :input").change(function() {
preventNavigation("You have not saved the form. Any \
changes will be lost if you leave this page.");
});
Then to allow the form to be submitted:
$("#yourForm").on("submit", function(event) {
enableNavigation();
});
Dynamically-modified forms:
preventNavigation() and enableNavigation() can be bound to any other functions as needed, such as dynamically modifying a form, or clicking on a button that sends an AJAX request. I did this by adding a hidden input element to the form:
<input id="dummy_input" type="hidden" />
Then any time I want to prevent the user from navigating away, I trigger the change on that input to make sure that preventNavigation() gets executed:
function somethingThatModifiesAFormDynamically() {
// Do something that modifies a form
// ...
$("#dummy_input").trigger("change");
// ...
}
The standard states that prompting can be controlled by canceling the beforeunload event or setting the return value to a non-null value. It also states that authors should use Event.preventDefault() instead of returnValue, and the message shown to the user is not customizable.
As of 69.0.3497.92, Chrome has not met the standard. However, there is a bug report filed, and a review is in progress. Chrome requires returnValue to be set by reference to the event object, not the value returned by the handler.
It is the author's responsibility to track whether changes have been made; it can be done with a variable or by ensuring the event is only handled when necessary.
window.addEventListener('beforeunload', function (e) {
// Cancel the event as stated by the standard.
e.preventDefault();
// Chrome requires returnValue to be set.
e.returnValue = '';
});
window.location = 'about:blank';
When the user starts making changes to the form, a boolean flag will be set. If the user then tries to navigate away from the page, you check that flag in the window.onunload event. If the flag is set, you show the message by returning it as a string. Returning the message as a string will popup a confirmation dialog containing your message.
If you are using ajax to commit the changes, you can set the flag to false after the changes have been committed (i.e. in the ajax success event).
Here try this it works 100%
<html>
<body>
<script>
var warning = true;
window.onbeforeunload = function() {
if (warning) {
return "You have made changes on this page that you have not yet confirmed. If you navigate away from this page you will lose your unsaved changes";
}
}
$('form').submit(function() {
window.onbeforeunload = null;
});
</script>
</body>
</html>
You can add an onchange event on the textarea (or any other fields) that set a variable in JS. When the user attempts to close the page (window.onunload) you check the value of that variable and show the alert accordingly.
Based on all the answers on this thread, I wrote the following code and it worked for me.
If you have only some input/textarea tags which requires an onunload event to be checked, you can assign HTML5 data-attributes as data-onunload="true"
for eg.
<input type="text" data-onunload="true" />
<textarea data-onunload="true"></textarea>
and the Javascript (jQuery) can look like this :
$(document).ready(function(){
window.onbeforeunload = function(e) {
var returnFlag = false;
$('textarea, input').each(function(){
if($(this).attr('data-onunload') == 'true' && $(this).val() != '')
returnFlag = true;
});
if(returnFlag)
return "Sure you want to leave?";
};
});
here is my html
<!DOCTYPE HMTL>
<meta charset="UTF-8">
<html>
<head>
<title>Home</title>
<script type="text/javascript" src="script.js"></script>
</head>
<body onload="myFunction()">
<h1 id="belong">
Welcome To My Home
</h1>
<p>
<a id="replaceME" onclick="myFunction2(event)" href="https://www.ccis.edu">I am a student at Columbia College of Missouri.</a>
</p>
</body>
And so this is how I did something similar in javaScript
var myGlobalNameHolder ="";
function myFunction(){
var myString = prompt("Enter a name", "Name Goes Here");
myGlobalNameHolder = myString;
if (myString != null) {
document.getElementById("replaceME").innerHTML =
"Hello " + myString + ". Welcome to my site";
document.getElementById("belong").innerHTML =
"A place you belong";
}
}
// create a function to pass our event too
function myFunction2(event) {
// variable to make our event short and sweet
var x=window.onbeforeunload;
// logic to make the confirm and alert boxes
if (confirm("Are you sure you want to leave my page?") == true) {
x = alert("Thank you " + myGlobalNameHolder + " for visiting!");
}
}
From the WebAPIs->WindowEventHandler->onbeforeunload, it recommends use window.addEventListener() and the beforeunload event, instead of onbeforeunload.
Syntax example
window.addEventListener("beforeunload", function(event) { ... });
window.onbeforeunload = function(event) { ... };
Note: The HTML specification states that authors should use the Event.preventDefault() method instead of using Event.returnValue to prompt the user.
So, in terms of your case, the code should look like this:
//javascript
window..addEventListener("beforeunload", function(event) {
//your code
// If you prevent default behaviour in Mozilla Firefox prompt will always be shown
e.preventDefault();
// Chrome requires returnValue to be set
e.returnValue = '';
})
It can be easily done by setting a ChangeFlag to true, on onChange event of TextArea. Use javascript to show confirm dialog box based on the ChangeFlag value. Discard the form and navigate to requested page if confirm returns true, else do-nothing.
What you want to use is the onunload event in JavaScript.
Here is an example: http://www.w3schools.com/jsref/event_onunload.asp
There is an "onunload" parameter for the body tag you can call javascript functions from there. If it returns false it prevents navigating away.