Handling the browser's window / tab close event in javascript [duplicate] - javascript

This is the code which i used for window.onbeforeunload
<head>
<script>
window.onbeforeunload = func;
function func()
{
var request = new XMLHttpRequest();
request.open("POST", "exit.php", true);
request.onreadystatechange = stateChanged;
request.send(null);
}
function stateChanged()
{
if (request.readyState == 4 || request.readyState == "complete")
alert("Succes!");
}
</script>
</head>
this works with IE and Mozilla but does not work with Chrome..... please help......
thanks in advance.....

It seems that the only thing you can do with onbeforeunload in recent version of Chrome is to set the warning message.
window.onbeforeunload = function () {
return "Are you sure";
};
Will work. Other code in the function seems to be ignored by Chrome
UPDATE: As of Chrome V51, the returned string will be ignored and a default message shown instead.

Know I'm late to this, but was scratching my head why my custom beforeunload message wasn't working in Chrome and was reading this. So in case anyone else does the same, Chrome from Version 51 onwards no longer supports custom messages on beforeunload. Apparently it's because the feature has been misused by various scams. Instead you get a predefined Chrome message which may or may not suit your purposes. More details at:
https://developers.google.com/web/updates/2016/04/chrome-51-deprecations?hl=en#remove-custom-messages-in-onbeforeload-dialogs
Personally do not think the message they've chosen is a great one as it mentions leaving the site and one of the most common legitimate uses for onbeforeunload is for dirty flag processing/checking on a web form so it's not a great wording as a lot of the time the user will still be on your site, just have clicked the cancel or reload button by mistake.

You should try this:
window.onbeforeunload = function(e) {
e.returnValue = 'onbeforeunload';
return 'onbeforeunload';
};
This works on latest Chrome. We had the same issue the e.returnValue with value of onbeforeunload solved my problem.
Your code should be like this:
<head>
<script>
window.onbeforeunload = function(e) {
e.returnValue = 'onbeforeunload';
func();
return ''onbeforeunload'';
};
function func()
{
var request = new XMLHttpRequest();
request.open("POST", "exit.php", true);
request.onreadystatechange = stateChanged;
request.send(null);
}
function stateChanged()
{
if (request.readyState == 4 || request.readyState == "complete")
alert("Succes!");
}
</script>
</head>

Confirmed this behavior on chrome 21.0.1180.79
this seems to work with the same restritions as XSS, if you are refreshing the page or open a page on same domain+port the the script is executed, otherwise it will only be executed if you are returning a string (or similar) and a dialog will be shown asking the user if he wants to leans or stay in the page.
this is an incredible stupid thing to do, because onunload/onbeforeunload are not only used to ask/prevent page changes.
In my case i was using it too save some changes done during page edition and i dont want to prevent the user from changing the page (at least chrome should respect a returning true or change the page without the asking if the return is not a string), script running time restrictions would be enought.
This is specially annoying in chrome because onblur event is not sent to editing elements when unloading a page, chrome simply igores the curent page and jumps to another. So the only change of saving the changes was the unload process and it now can't be done without the STUPID question if the user wants to change it... of course he wants and I didnt want to prevent that...
hope chrome resolves this in a more elegant way soon.

Try this, it worked for me:
window.onbeforeunload = function(event) {
event.returnValue = "Write something clever here..";
};

Try this. I've tried it and it works. Interesting but the Succes message doesn`t need confirmation like the other message.
window.onbeforeunload = function()
{
if ( window.XMLHttpRequest )
{
console.log("before"); //alert("before");
var request = new XMLHttpRequest();
request.open("POST", "exit.php", true);
request.onreadystatechange = function () {
if ( request.readyState == 4 && request.status == 200 )
{
console.log("Succes!"); //alert("Succes!");
}
};
request.send();
}
}

None of the above worked for me. I was sending a message from the content script -> background script in the before unload event function. What did work was when I set persistent to true (in fact you can just remove the line altogether) in the manifest:
"background": {
"scripts": [
"background.js"
],
"persistent": true
},
The logic is explained at this SO question here.

Current versions of Chrome require setting the event's returnValue property. Simply returning a string from the event handler won't trigger the alert.
addEventListener('beforeunload', function(event) {
event.returnValue = 'You have unsaved changes.';
});

I'm running Chrome on MacOS High Sierra and have an Angular 6 project whithin I handle the window.beforeunload an window.onbeforeunload events. You can do that, it's worked for me :
handleUnload(event) {
// Chrome
event.returnValue = true;
}
It show me an error when I try to put a string in event.returnValue, it want a boolean.

Don't know if it allows custom messages to display on the browser.
<script type="text/javascript">
window.addEventListener("beforeunload", function(e) {
e.preventDefault(); // firefox
e.returnValue = ''; // Chrome
});
</script>

Related

How to turn off brower's pop-up when an EvenListener is called [duplicate]

When a user leaves a page, I need to ask him if he wants to perform a particular action before leaving.
<script type="text/javascript">
$(document).ready(function() {
window.onbeforeunload = askConfirm;
});
function askConfirm() {
var addFriend = confirm("Would you like to ping?");
if (addFriend) {
var xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp=new XMLHttpRequest();
} else {
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.open("GET","http://example.com?ping=1234",true);
xmlhttp.send();
}
return null;
}
Depending on the value of that last return statement ("", null, true, false, or not having a return statement at all) I can have one of two situations:
1) The user gets the "Would you like to ping?" confirmation (good), the ping is sent (good), and the user is presented with a "This page is asking you to confirm that you want to leave" popup (BAD).
-or-
2) The user gets the "Would you like to ping?" confirmation (good), the ping is not sent (BAD), and the user is not presented with a "This page is asking you to confirm that you want to leave" popup (good).
How can I have the AJAX ping sent, yet suppress the "This page is asking you to confirm that you want to leave" popup?
Edit: As ridiculous as it sounds, the "work around" that I found for this issue is to alert() after the xmlhttp.send() statement. The only clean way to do that is to alert the user that his ping has been sent. If future StackOverflowers find a better solution, I would love to know.
Thanks.
You can make your Ajax request synchronous.
xmlhttp.open("GET","http://example.com?ping=1234", false); // use false here
xmlhttp.send();
It might cause a slight delay if your server is slow, but it should solve the problem of the ping not being sent.
well instead of doing it before you leave, I did it onunload and here is what I got to work in FF and IE (besides chrome, that's all I got): http://jsfiddle.net/rmpLm/9/.
perhaps you can get it to work on chrome, but if you cant, maybe you could make it so that if you hit ok, it takes you to a page where you send it. hope it helps : )
EDIT: maybe you should consider making it so it does it onload

Emit message to add-on from content script onbeforeunload?

I have a content script which times how long a user views a page. To do this, I inject a content script into each page, start a timer and then emit a message back to the add-on when the onbeforeunload event is triggered.
The message never seems to get passed to the background script however.
Given that my main.js looks like this:
var pageMod = require('page-mod'),
self = require("self");
pageMod.PageMod({
include: "http://*",
contentScriptFile: [self.data.url('jquery.min.js'),
self.data.url('content.js')],
onAttach: function(worker) {
worker.port.on('pageView', function(request) {
console.log("Request received");
});
}
});
I can send a message to main.js using the following code no problem.
self.port.emit('pageView', { visitTime: time });
I run into a problem when I try to do it as the user leaves the page however. The message is never received when I do it like this:
$(window).bind('onbeforeunload', function(e) {
self.port.emit('pageView', { visitTime: time });
// This should prevent the user from seeing a dialog.
return undefined;
});
I've tried listening for beforeunload too, that doesn't work either. What could be the problem?
The window object that content scripts access in Firefox browser add-ons is a proxy object and can be a little temperamental. Using window.addEventListener will work.
window.addEventListener('beforeunload', function(e) {
# Do stuff then return undefined so no dialog pops up.
return undefined
});
The onbeforeUnload event is not synchronous, so the browser garbage collects the page before it is finished. Use a synchronous AJAX request:
function Data()
{
var client = new XMLHttpRequest();
client.open("GET", "/request", false); // third paramater indicates sync xhr
client.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
client.send({ visitTime: time });
client.onreadystatechange = emitter;
}
function emitter()
{
self.port.emit('pageView', { visitTime: time });
}
or return a string as an alternative.

Handling http_request in IE 8, using AJAX

i've been working on some kind of remote control for some time now and figured out a problem that confuses me:
The remote controle is supposed to control some kind of machine. The complete hardware based code is written in c by myself, but thats not really interesting for my problem.
Im using a webserver and a webpage to get access to some basic commands, just like driving forward, backward or turning motor on/off (i use a wlan accesspoint on the board in the machine to connect to it). So far everything works fine, but............:
My Problem is, that there are several options to control the functions of the machine (Terminal, wired-connected Notebook, remote control, "normal" working loop) at the same time. This means, if the machine switches on the motor by itself or a worker uses the terminal, it is neccessary for me to have a feedback on my remote control aswell (at the moment i switch the color of the different button-border from green=inactive to red=active).
The way i did that is easy explained:
If for an example the motor is switched on in c, i write a file with a decimal number that represents a binary code. Just like motor on is 0001 means i write a dec 1. Motor off would be 0010, means i write a dec 2. Because it is possible that there are more than only one function running at the same time i just pass values like 13 (motor on: 0001 = 1; forward: 0100 = 4; lights on: 1000 = 8; => 8+4+1=13). I use a binary AND comparsion to get the actual information about the status afterwards.
Nevertheless i cant refresh the page every two seconds to check the file i write to for changes, im using ajax to have a simple and fancy request possibility:
var http_request = false;
function RequestCommandStatus(url) {
http_request = false;
if (window.XMLHttpRequest) {
http_request = new XMLHttpRequest();
} else if (window.ActiveXObject) {
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
if (!http_request) {
alert('Ended due to an error!');
return false;
}
http_request.open('GET', url, true);
http_request.onreadystatechange = control4Commands;
http_request.send(null);
}
and after that i do the comparsion stuff:
function control4Commands() {
if (http_request.readyState == 4) {
var answer = http_request.responseText;
if ((answer & 0x1) == 0x1){
//do something
}
if ((answer & 0x2) == 0x2){
//do something
}
if ((answer & 0x4) == 0x4){
//do something
}
if ((answer & 0x8) == 0x8){
//do something
}
}
}
setInterval("RequestValveStatus('myfile.txt')", 1000);
This works pretty good in Firefox but for some reason i got a strange problem in IE8 (even if i enabled every known scripting language and allowed pretty much complete access and control):
For some reason the request seems to be executed once, but after that there is no more interaction between the page and the server. The value of the file changes like it is supposed to. If i reload the page manualy, and for an example, the motor is still running, it changes the color of the border to red. In my opinion this should make sure that the request atleast succeded once.
By using the script debugger of the developer tools, i got the error message, that the http_request.open() failed because of access denied. My first suggestion was that it might be about the path or the type of the file i read from, but i wasnt able to fix it in IE8 with .html, .php, .txt and "several" other types. Also changing the path/origin didnt solved the problem.
I'd really like to discuss this problem with you and feel free to post me your ideas about this way of getting the actual status of the functions.
Greeting,
Ohemgi
I'm sorry for my bad english. Feel free to ask if you cant follow my explanations :-)
try to change
setInterval("RequestValveStatus('myfile.txt')", 1000);
into
setInterval(function() { RequestValveStatus('myfile.txt'); }, 1000);

javascript - strange debugging issue

My code changes are not being reflected in IE or FF.
In IE:
I commented out the alert('start'), but I still see the alert when I stop-restart my visual studio debugger.
In FF:
Same code change, but none of the alerts show at all. I uncommented alert('start') and I still dont see it in FF.
I tried setting my port to stay fixed at 5204. I also stopped the ASP.NET development server prior to starting the debugger again. Still doesnt help.
Environment: VS 2010 IE7 and FF3.6.
Code
simplexhr = {
doxhr: function (container, url) {
//alert("START");
if (!document.getElementById || !document.createTextNode) {
alert("NO JS SUPPORT");
return;
}
simplexhr.outputContainer = document.getElementById(container);
if (!simplexhr.outputContainer) {
alert("NO OUTPUT CONTAINER");
return;
}
var request;
try {
//alert("Mozilla AJAX");
request = new XMLHttpRequest();
alert(request);
}
catch (error) {
try {
//alert("IE AJAX");
request = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (error) {
return true;
}
}
request.onreadystatechange = function () {
if (request.readyState == 1)
simplexhr.outputContainer.innerHTML = 'loading...';
}
alert("made it to try AJAX");
request.open('get', url);
//alert("ready state: " + request.readyState);
}
}
UPDATE
On further testing, this problem is due to caching. But, it only happens when I use "unobtrusive javascript" or javascript inside its own *.js file linked in the header:
<script src="Scripts/simpleXHR.js" type="text/javascript"></script>
Moving the code into the page - viewing source - the javascript updates everytime with no caching issues. So is there a better way to perform "unobtrusive javascript"? Or should it be renamed "unproductive javascript" :P
Sounds like it might be a browser cache issue. Try clearing your cache in each browser. Hopefully that will pick up the changes.
You could verify that by doing a view-source in the browser and see if you're actually getting the latest code.

link Click tracking does not work on Safari browser

I have a basic html page which has links that point to different site. What I want to do is track the clicks. I am doing so by sending a 0 pixel image call on Click event of the link without returning false on click event.
The same works fine on all the browsers except Safari(on windows OS).
when a link is clicked using javascript I delay the redirect and send an image request over to the server and log the click on server side. I have tried increasing the delay but with no success... The trackers work gr8 on all the browsers except Safari which does not sent the request at all.
I dont know why but possibly its that safari waits for the complete js to be executed before making the request and after the whole js is executed it gets redirected....
=========================================================
<html>
<head>
<script type="text/javascript">
function logEvent(){
image = new Image(1,1);
image.onLoad=function(){alert("Loaded");};
image.onLoad=function(){alert("Error");};
image.src='http://#path_to_logger_php#/log.php?'+Math.random(0, 1000) + '=' + Math.random(0, 1000);
pauseRedirect(500);
}
function pauseRedirect(millis){
var date = new Date();
var curDate = null;
do {curDate = new Date();}
while(curDate-date < millis);
}
</script>
</head>
<body>
Site 1<br/>
Site 2<br/>
</body>
</html>
=========================================================
Code works in chrome, firefox, ie and Opera. Does not work on Safari only..... any clues....
I had the same issue with all WebKit browsers. In all others you only need to do new Image().src = "url", and the browser will send the request even when navigating to a new page. WebKit will stop the request before it's sent when you navigate to a new page right after. Tried several hacks that inject the image to the document and even force a re-paint through img.clientHeight. I really don't want to use event.preventDefault, since that causes a lot of headaches when a link has target="_blank", form submit, etc. Ended up using a synchronous XmlHttpRequest for browsers supporting Cross Origin Resource Sharing, since it will send the request to the server even though you don't get to read the response. A synchronous request has the unfortunate side-effect of locking the UI-thread while waiting for response, so if the server is slow the page/browser will lock up until it receives a response.
var supportsCrossOriginResourceSharing = (typeof XMLHttpRequest != "undefined" && "withCredentials" in new XMLHttpRequest());
function logEvent() {
var trackUrl = 'http://#path_to_logger_php#/log.php?'+Math.random(0, 1000) + '=' + Math.random(0, 1000);
if(supportsCrossOriginResourceSharing) {
xhrTrack(trackUrl);
} else {
imgTrack(trackUrl);
}
}
function xhrTrack(trackUrl) {
var xhr = new XMLHttpRequest();
xhr.open("GET", trackUrl, false);
xhr.onreadystatechange = function() {
if(xhr.readyState >= this.OPENED) xhr.abort();
}
try { xhr.send() } catch(e) {}
}
function imgTrack(trackUrl) {
var trackImg = new Image(1,1);
trackImg.src = trackUrl;
}

Categories