Disclaimer before the uppity types start in: This is not to be deployed "in the wild". This is for local, personal use by a Chrome add-on only. I am not trying trick visitors to my sites or do anything else unsavory. I've seen a bit of chastising of those wanting to hook onbeforeunload.
Some Background
Far and away my biggest gripe with Chrome (at least on Mac OS) is its tab close buttons which, when I have several tabs open (as I usually do), results in my frequently closing tabs unintentionally as the tabs themselves become fairly small and thus the click target area that isn't covered by the tab close button is very small. On certain tabs with news stories, blog posts, documentation, etc. it's annoying but not a huge inconvenience. I just CMD+T to reopen the tab and there's no real harm done. However, certain tabs, in particular Gmail, have definite downsides to being closed. I frequently have one or more chat dialogs with coworkers open and reopening a tab does not restore the chat dialog, and initiating a new chat loses me the current chat history (yes, it's saved, but it's not conveniently accessible by scrolling backwards in context). There are a handful of requests for Google to add the option to simply remove tab close buttons (I prefer to use CMD+W myself), but I'm not holding my breath on that.
A Partial Solution
A while back a friend pointed me towards the dotJS Chrome add-on which allows per-domain custom JavaScript execution, akin to GreaseMonkey, but slightly different. At any rate, it gave me a means to "fix" issues/wants on a number of sites I visit regularly, and I've found it to be very helpful thus far. The other day it occurred to me that I could probably keep my Gmail, et al tab(s) open with a bit of JavaScript. I threw together a small script that based on a regular expression would prompt you before closing a tab. The gist of the code is as follows:
var unloadHandler = function(e) {
if (/(mail.google.com|google.com\/reader|gmail.com)/.test(location)) {
return 'Are you sure you want to close: ' + location.host;
}
};
window.onbeforeunload = unloadHandler;
Lo and behold, this did the trick for most of the sites I tried it on; except one: Gmail. Let me correct that: it worked, insofar as it prompted me to confirm the closing of the Gmail tab, and if I opted to not close it, it would keep the tab open, but before the dialog prompted me, the page had gone completely white. Element inspector shows that the markup is all still there (so far as I can tell), and the styles on the elements shouldn't be hiding things (i.e. display: none; visibility: hidden; etc) and the elements' positioning is still correct (e.g. they're within the viewable area). I went through one-by-one removing elements to see if anything was obscuring the Gmail interface, but was never able to reveal it on screen. I cannot for the life of me figure out what's going on. I'm not sure if Gmail is hooked into some event I'm unaware of (an on*before*beforeunload?), or if Google's browser is doing something special with their Gmail page, or what is causing the strange behavior. Google Reader is unaffected by this oddity (I can prevent close and retain the contents of the page) as are all of the other sites I've tested with.
Does anyone know what might be causing this issue?
For the record, I am running the following: Mac OS X 10.6.5, Google Chrome 10.0.648.205, and dotJS 1.3.
I appreciate any feedback, but I am not looking for solutions that involve: pinning tabs, changing my workflow/usage (e.g. not selecting tabs with the mouse), etc. I really want to figure out what, specifically, Gmail (or perhaps Chrome?) is doing that is sabotaging my efforts here. Thanks in advance.
I think Gmail's own code causes this behavior. I can reproduce your problem (on linux machine) with subscribing for this event from the console with this function
window.onbeforeunload = function(e) {
return "Hey what\'s wrong with you?!";
};
After it I've started the developer tool profiler, the last call after closing the window (and choose the 'stay on this page' answer for the question) is a removeChild function call, which removes some content from the <iframe id="canvas_frame" />. So the content elements are not there anymore.
function Fc(b) {
return b && b.parentNode ? b.parentNode.removeChild(b) : m
}
I've found some 'traces' in the obfuscated code for subscribing for the beforeunload event, but it's hard to be sure :)
function It(b, a) {
this.Qc = jCa++;
this.ea = b;
this.ka = new J(this);
this.Qa = a;
this.Ka = [];
this.Za = !1;
this.ka.ya(this.ea, "unload", this.Da);
this.ka.ya(this.ea, "beforeunload", this.ab);
Ypa(Zd(a), this);
this.ia()
}
I tried to reproduce this behavior in Firefox but I think google ships different javascript codes for different browsers so I can't reproduce it.
Related
I'm seeing an odd bug in IE that I'm not seeing in Chrome. Specifically, this involves some JS code not firing when a (Telerik) wizard is navigated back to it's first step.
When the user clicks their "Previous" button, some data isn't being properly loaded. Hitting F12 and bringing up the developer console has shown me the following Warning:
DOM7011: The code on this page disabled back and forward caching. For more information, see: http://go.microsoft.com/fwlink/?LinkID=291337
Ok, so I go to the link provided and I noticed the documentation states:
In order to be cached, webpages must meet these conditions:
...
- The F12 Developer tools window isn't open
This is a problem, because when I use the navigation buttons within my wizard WHILE the dev window is open, it behaves properly, just as it does in Chrome.
How can I debug my related Javascript so I can figure out what's going on? Also, I understand what caching is but I'm not exactly sure what this is about and I have no idea why Chrome behaves differently. Is there a way that I can force IE to behave like chrome and cut on (or off) whatever features that are causing this issue?
Yuck. Back to old school debugging for you.
Short of putting the whole browser into a Windows debugger, you can pretty much forget about setting breakpoints. All you can do is log.
If you are lucky and your problem isn't too deep, you can use a sprinkling of simple alert() statements to let you know the state of things at various stages in your code. One nice thing is that you can serialize objects now pretty nicely; for example, you can do JSON.stringify(this), which will probably give you a giant output, which you can copy and paste into your IDE and unpack. A major upside to doing this is that the alert will block, so you can take your time studying the output. A major downside to this is that race conditions are now much more likely.
Alternatively, you can add a <textarea> to the page and throw your JSON.stringify(this) results into that. Because this means extra DOM mutations, it also increases the odds of race conditions, but not by much. (If race conditions are a possibility, you can do this:
(function () {
var currentState = JSON.stringify(this);
setTimeout(function () {
document.querySelector('textarea').value = currentState;
}, 1000);
})()
Even though these are now asynchronous, if you use this multiple times in sequence, these will execute in that same sequence (unless you change the timeout period).
If you are doing actual page navigations (and not just changing the URL with pushState()), then actually reading those logs is going to be a problem. The solution is to put the page in a frame and write the content out to a sibling frame. As long as both frames are running on the same domain, you will have no problem pushing the data into the sibling frame. If you can't put them on the same domain, you are kind of screwed.
I have a link that opens a new window using window.open. The pop up works fine, however the normal web page stops loading objects (images, scripts, ajax scripts) and sometimes the page doesn't load at all.
Here is my code:
MyWindow=window.open('player.php','Player','width=500','height=300'); return false;
Is there anything I am doing wrong?
Thanks,
Peter
First of all, please be more specific: tell us more about your browser and which version, and possible your OS. It could be more related to the browser than to the web content.
Then on to the possible problem; you start with saying "I have a link that ...".
To me that sound like you use <a href="javascript:DoSomething()">. Or perhaps <a href="#" onclick="DoSomething()">.
I tried both in some modern browsers: Chrome v37, IE v11. Both browsers did not produce what you describe:
- Chrome v37 will happily keep on loading, even if I immediately click a "window.open()"-link on top of a (huge) webpage;
- IE v11 will someshow show "false", which is strange, but still not what you got.
In some cases I also got to deal with the popup blocker.
A general tip might be to NOT USE <a href> for things like this. Behaviour seems inconsistent across browsers, also these days there are better alternatives, such as <span onclick="">...</span> and <button onclick="">...<button> or by using JQuery or other frameworks (which I do not know much about).
Although this many not be a conclusive answer, maybe this can help you experiment on your own, and think about possible causes or alternative ways of doing things.
The behaviour you describe should definitely NOT normally happen. This is confirmed by robbmj's JSFiddle, that fails to reproduce the problem. That's evidence that something is going on in the main page that is not plain vanilla page loading, or your "link opening" has something unusual to it. Apart from the syntax error (you use four parameters, not three).
Since you do not supply information on either of these points (how do you load the main page? How do you trigger the popup-opening code?), we do not even know if the problem
might be browser-related; I'd start and try to test things in IE, Chrome and Mozilla to see
whether anything changes; this might provide some useful insights.
One possibility
A very strong possibility is that your inadvertent fourth parameter goes into the window.open() "replace" parameter, which is a boolean, and triggers undefined behaviour or simply an error that stops everything. You should have things somewhat working in IE and not working at all in Firefox.
You should also be able to see whether this is the case by using Firefox and the Firebug extension, or the Web Developer Console in Chrome.
Another possibility
A more esoteric possibility is that the way you define the link might make the browser believe you've actually moved on to another page, so that there's no point in continuing loading the current page. Depending on the browser, this might have to do with how the link is defined and could be remedied by defining it some other way.
For example it could conceivably happen if you had
...
which I suspect is what led user Tomzan to ask, "is the link something like javascript:...?"
So if this is the case, try with this instead (this works for me in IE9/Chrome/FF):
link
function openPopup() {
MyWindow = window.open('player.php', 'Player', 'width=500, height=300');
// Also try the following. You won't probably like the results (it should send the
// popup window behind), but if it works, it proves we're dealing with a browser
// issue there.
// Blur and refocus
// MyWindow.blur();
// window.focus();
// Just focus
// window.focus();
return false;
}
Workaround
A possibly acceptable workaround could be to disable the link altogether (or hide it via CSS), and only reactivate/show it upon main document being ready. This sidesteps the problem, even if user experience could be somewhat worse due to a longer wait.
But if it's so likely that a user clicks on the link before waiting for the whole page to load, I'd also consider not automatically loading the rest of the page at all, and reorganize information to provide a more streamlined navigation. Or maybe distribute it on two sequential pages. Again, unfortunately you did not supply enough information to do more than guess.
As you probably know, JavaScript is single threaded. Every event is queued until there is idle time for it to be executed.
In the case of window.open, both windows must share a single context to keep it thread-safe because the opened window can access to it's parent using window.opener.
I don't know how browsers implements it, but we can guess two possibilities:
Idle time is shared between the two windows. It means if the popup does many blocking statements, it can freeze the main window's events.
Only one of the two windows can be active, which depends on which one has the focus. In that case, all events may be paused in the main window when you're using the popup.
If you want a more precise answer, I need more details about your code.
document.addEventListener("DOMContentLoaded", function () {
//whatever the code
MyWindow=window.open('player.php','Player','width=500','height=300'); return false;
}, false);
Try to wrap the code in SetTimeout
setTimeout(function () {
window.open( .. )
}, 0);
Your document should be loaded first, then popup should be open, So write your javascript code in the scope of $(document).ready().
enter code here
$(document).ready(function(){
$("#clickme").click(function(e){
MyWindow=window.open('player.php','Player','width=500','height=300'); return false;
});
});
It seems like when trying to open 2 windows from a succession of windows.open calls, it only allows the first window to open and deletes the reference to the second window. I know this probably sounds a little kludgy, but we do need to have that second popup.
Any ideas?
Unfortunately we are addressing a user-case, where ie6 on the user end has popup blocker enabled.
EDIT: I just realized that you probably are using a blank ('') window name for both windows:
var win = window.open(url, '', 'blah=1');
var win2 = window.open(url2, '', 'stuff=1'); //later
This is probably handled with different windows in browsers other than IE6.
If that does not work, you might consider injecting divs that display on top of your content (instead of using popups), which is considered a better practice.
The IE pop-up blocker, by default, only allows one new window to be opened per user-initiated-action (i.e. a click on some element). If you try to open two new windows in the same handler in response to a single user-initiated-action, only the first window will successfully be opened. This is by design.
There is an override key that users can use: on IE6 I think it is CTRL, but it might be CTRL+ALT because it got changed in later versions (not sure if that was back-ported or not).
If you go to Tools->Internet Options->Pop-up Blocker->Settings->Blocking Level: and look at the value in the drop-down box for "High" it will tell you the override key in a parenthetical phrase.
In the same settings dialog, you can also add this specific site to the "Allowed sites" list, and then pop-up blocker will let all new window creation attempts on said site succeed. I'm pretty sure this list can also be pre-populated through group policy or IEAK or something like that too. But it's just a list that is stored in the registry, so you can also write log-in scripts that will just add things if they need to be added.
If you have further questions, let me know (I was the developer who implemented the IE pop-up blocker).
IE6 makes it sound like it's a corporate installation. Assuming that's true, contact your administrators and have group policy set your internal website to be in the Intranet zone, and turn off the popup blocker for that zone.
As far as I know all popular web browsers execute the onclick attribute of an anchor link first, then follow the path specified by the href attribute.
The problem here is that the onclick attribute only gets called when clicking with the left mousebutton (without pressing ctrl or shift for a new tab or window) or when pressing enter on your keyboard while the tabIndex is set to the link you want to follow.
But there are many other ways of following a link than just those two.
Ctrl + click
shift + click
rightmousebutton + open
rightmousebutton + new tab
drag & drop link to address bar
and so on...
My client uses onclick for conversion statistics. Which seems heavily unreliable.
My question:
What percentage of hyperlinks are being followed without activating their onclick attribute?
All estimates are highly appreciated. I'm completely lost; I think it can be any number...
Aside from those of us who habitually middle-click/ctrl-click to open links in new tabs, there's another major cause of onClick failure: NoScript and similar plugins which allow javascript to run only when it comes from whitelisted sites. If your domain isn't on my whitelist, then your onClick won't run, no matter how I trigger the link.
If you want reliable stats on which pages people are visiting, there's only one bulletproof source for that: The web server logs.
The logs are probably also your best bet for tracking how people move throughout the site, but they're not entirely reliable, as some privacy-paranoid users will falsify their referer headers or just not send them at all, but I expect that to be far less common than disabling javascript.
It depends. If the audience is more technically inclined, I'd assume that using alternative ways of following a link would be more common. All in all, though, even a lot of technical people seem to be unaware of things like clicking the middle mouse button to open or close a tab. If that's the case with technical people, I wouldn't be surprised if almost no one in the general audience used it.
The links are all exit-links. I was thinking of a PHP script that does the counting of clicks.
Though this is not the subject of your question, you might want to have a look at Google Analytics then. They are The Master in tracking you. They track right-clicks (even when not actually selecting "open in new window" after that, which they obviously cannot know), which will yield Ajax calls to http://www.google.com/url.
To see Analytics in action: with Adblock and the like disabled, search something on google.com and open up Live HTTP Headers in Firefox (or your Firebug Net tab in Firefox, or WebKit's Resources pane in Safari or Chrome, sorted by time). Next, click, right-click, shift-click or control-click any search result (preferably a result that does not require a lot of HTTP traffic by itself, or is in your browser's cache).
the onclick attribute only gets called when clicking with the left
mousebutton (without pressing ctrl or shift for a new tab or window)
Not entirely true. I created a quick test at JS Bin, to show that modifier keys do not affect the onclick event. (For right-click, one should use the oncontextmenu event.)
What are you doing in your onclick handler that you are worried about not working? e.g. if you have a regular link to a page... and the onclick just opens that same page in a pre-sized popup for user convenience in a web application... then there's likely no issue (e.g. CTRL+Click) still opens the page, it just gets opened in a new tab)
If you are just trying to "log" every click in the site/application for tracking purposes then maybe you can hook into the onmousedown/up or focus/blur events instead/also.
This question already has answers here:
Identifying Between Refresh And Close Browser Actions
(13 answers)
Closed 6 years ago.
After being through numerous forums available on the net for last 5 days, I am still not able to completely track down the browser close event. My requirement is to generate a popup message, when user tries to close the browser.
I have called my javascript function on body 'onbeforeunload' event. And I have hardcoded the conditions to check the mouse-coordinates for the red 'X' buton of browser, refresh, File-close or Alt-F4.
My code works fine when browser window is Maximized, but fails if we shrink it after a limit. Please help me, if some body has already found the solution to a similar problem.
Thank you.
Aggregated Responses of OP
------
Ok, just tell me if it is possible to detect if a user has clicked on the Refresh button of the browser. Also, Refresh can be triggered by Right-click - Refresh or Ctrl-R. My requirement is to make a variable false on Refresh. I am just able to do it on F5, but all other ways are still out of my reach. The same would be applied to Back button.
Hi ppl, Thanks for all who replied at least. I have talked to my seniors regarding this and they have now understood and have compromised with the browser menu buttons. So now my task has become easy. Now, I am using a variable and making it true by default. As, I mentioned earlier I just have to catch the onbeforeunload and popup a message when user tries to leave. The message will not popup when user is navigating to other pages, as I have made the variable as false on all the links of my page using following piece of code:
document.onclick = function() {
//To check if user is navigating from the page by clicking on a hyperlink.
if (event.srcElement.tagName == 'A')
blnShowMsg = false; //To not popup the warning message
else
blnShowMsg = true; //To popup the warning message
}
In my case still the message is shown when user does Refresh, back or goes to any link in Favorites, etc.
Thanks buddy, but I have already gone through that and didn't find much help there too. My seniors are not happy with that solution as putting a flag on every link of my application is a complicated job and they fear of breaking the application. Any other suggestions would be appreciated. Thanks once again.
Is there no one who can think of a solution here!!! where are all the experts???
The question isn't an unusual one. Yet after 5 days searching the internet you still haven't found a satisfactory answer. That in itself should be a fairly plain indicator.
What I've found on the web is there is a serious aversion to the 'no can do' answer. When something can't be done the normal response is to make no response.
Bottom line is not only can what you are trying do not be done it should not be done.
I think you need to go back to your seniors and explain to them that a Web UI is a guest hosted by a browser on a client machine. This guest status is an important one.
Would you want a guest in your home to have the power to enforce you to alert them when you want to go to the toilet? No?
Similarly the browser limits what info the guest UI is allowed to access. Even if you found a workaround for the fact that browsers aren't giving up this info voluntarily, such clever hacks are fragile and likely to be constant source of bugs.
Since its likely that the application was originally intended to be delivered via the browser before any code was cut, the fault lies with including the requirement in the first place.
All we can do sympathise with you in being asked to perform an near impossible and certainly not sensible requirement.
Add this script to your HTML:
window.onbeforeunload = function (e)
{
e = e || window.event;
var y = e.pageY || e.clientY;
if (y < 0){
return "Do You really Want to Close the window ?"
}
else {
return "Refreshing this page can result in data loss.";
}
}
In your function:
document.onclick = function()
{
//To check if user is navigating from the page by clicking on a hyperlink.
if (event.srcElement.tagName == 'A')
blnShowMsg = false; //To not popup the warning message
else
blnShowMsg = true; //To popup the warning message
}
blnShowMsg will be true for any click on your page except sometimes when the user click a link. I say sometimes because if event.srcElement.tagName doesn't work in some browser it will allways be true. And you have to add lots of cases to to allow using form controls etc... Some browsers can even automatically reload a page, and I'm not sure if onload events will run then or not.
But popping a warning about leaving the page (or similar) all the time is sure to annoy a lot of people, and they'll probably leave permanently...
If you're making for instance a online program where it's critical that something is saved before leaving, I'll say that catching the before unload event is a little too late, better to make some kind of autosave (see Gmail) and/or some kind of non-obtrusive warning when the user mouseover the navigation menues without saving.
But you can't force stupid users not to do anything stupid, on a web interface this is even more true because you have less controll: if the user want to terminate the program before saving they will find a way to do so, and they will call you and complain when the unsaved data dissapears ;P
I have a method that is a bit clunky but it will work in most instances.
Create a "Holding" popup page containing a FRAMESET with one, 100% single FRAME and place the normal onUnload and onbeforeUnload event handlers in the HEAD.
<html>
<head>
<script language="Javascript" type="text/javascript">
window.onbeforeunload = exitCheck;
window.onunload = onCloseDoSomething;
function onCloseDoSomething()
{
alert("This is executed at unload");
}
function exitCheck(evt)
{
return "Any string here."}
</script>
</head>
<frameset rows="100%">
<FRAME name="main" src="http://www.yourDomain.com/yourActualPage.aspx">
</frameset>
<body>
</body>
</html>
Using this method you are free to use the actual page you want to see, post back and click hyperlinks without the outer frame onUnload or onbeforeUnload event being fired.
If the outer frame is refreshed or actually closed the events will fire.
Like i said, not full-proof but will get round the firing of the event on every postback.
I believe there was some ways to do this in some browsers (and probably not very reliably) some years ago. Because I remember those awful massive spam-popups that spawned more popups as you closed one. But that's why it's not a good idea to allow scripts to detect this, and why browsers should prevent it and most modern browsers probably does.
I was asked to do something similar for a survey invitation script; they wanted to ask the visitor if they would like to answer a survey about their website, and then the survey should pop up when they leave the site. The solution I found was to (repeatedly) explain the management that this was probably impossible, or at best very unreliable; and instead the survey should popup immediately (if the visitor agreed to take the survey) and the intro page should tell the visitor to leave this window open and go back to it after reviewing the page.
onunload and onbeforeunload are not meant for this, so will naturally be unreliable.
A better solution is to change the problem. Have the client send a heartbeat, periodically telling the server the page is still active. When the hearbeat stops, you know you can clean up the server.
You might find this interesting: https://stackoverflow.com/a/3586772/1483977
Or this: Identifying Between Refresh And Close Browser Actions
"Thanks buddy, but I have already gone through that and didn't find much help there
too. My seniors are not happy with that solution as putting a flag on evry link of my
application is a complicated job and they fear of breaking the application. Any other
suggestions would be appreciated. Thanks once again."
If you use jQuery, you can add link flags automatically. The way I would handle your problem is when the user performs the "dangerous" actions, iterate all the page links that are "dangerous" and then bind events to them.
$("#dangerbutton").click(function(){
$("a").not( safeList ).click(function()
{
var dest = $(this).attr('href');
someWarningFunction(function(){
/* Stay where we are because user opted to stay */
},function(){
/* Continue Following Link because user didn't mind */
window.location= dest;
});
return false;
});
});
This way will only fire on link clicks on your page. Users have to get used to the fact that "close window == cancel everything" logic, because many use and trust that facility.
You might have seen in many of the web form pages to warn the user before closing the page.When somebody refreshes the page, then there is a chance for loosing all filled data. In that case it is very helpful.
Page life cycle includes two events like onunload and onbeforeunload. For this case you need to bind the script function in window. Onbeforeunload so that it will be called when page is unloading.
Again this warning should not be fired when you are actually submitting the page. For that set a boolean value (e.g. shouldsubmit) to submit the page.