How do I programmatically detect how a browser handles window.close()? - javascript

Different web browsers handle the window.close() function differently. IE prompts the user for confirmation, while Firefox and Safari just fail to honor it unless the window was originally opened with Javascript and display a message saying as much in the console.
A third party web application used internally in our organization that I support displays a 'close' button at the end of a wizard-like series of pages. This works well for IE, which is what the majority of our users use. However, this obviously fails in FF. I'd prefer to leave the button in and use Javascript to gracefully degrade the UI by not displaying that button in any browser that will not perform the window.close().
As a rule of thumb, I try to check browser capability rather than relying on a hard-coded policy based on browser detection whenever possible. Is there a way to programmatically check the support for window.close() so I can determine whether the button should be displayed in the first place?

Try this:
Demo: http://jsfiddle.net/ThinkingStiff/mnv87/
Script:
function hasClose() {
var close = window.open( '', '', 'height=100,width=100,left=3500', false );
close.close();
return close.closed;
};
if( hasClose() ) {
//show button
} else {
//hide button
};
Note hasClose() will also return false if popups are blocked.

Why not check compatibility, and then append if compatible? Using jQuery:
<script type="text/javascript" src="latest_jquery_file.js"></script>
<script type="text/javascript">
$(document).on("ready", (function(e)
{
$("body").append('<p>Close The Window!!</p>');
$('#windowcloser').click(function(){
window.close();
});
})
);
</script>
Since jQuery is cross browser compatible, it should

Very simple. Your script should try (or try) to window.close, and if its still alive after that try - show the message, and, optionally, erase/replace page content, or use location.reload to not give your users any reason to stay at the page anymore.
p.s.: keep in mind, closing windows from JavaScript is very impolite. So you better have some good reasons for doing it ;)

Related

Closing Browser Tab not working in Chrome

I am trying to close the tab using script, but it's not working.
<button type="button" class="btn btn-primary" id="btnClose">Close</button>
$('#btnClose').click(function() {
var newWindow = window.open('https://localhost:44384/MasterUpdate/Index/1', '_self', '');
window.close(newWindow);
});
The URL I am using is for testing purposes only. In my code I manually manage it using this:
string referer = Request.Headers["Referer"].ToString();
ViewBag.GetCurrentURL = referer;
I have tried so many ways but they didn't work for me.
javascript:window.open('','_self').close();
window.top.close();
window.close();
As Rory pointed out, there are few conditions when window.close() works.
Below is the excerpt from this link:
close browser tab/window
Note that window.close() will only work under the following conditions:
On all modern browsers, the web page to be closed must be the first in that window/tab's session history. That is, if you hit the Back button on the browser, you will not go to a previous page in that window/tab because there is none.
You can easily accomplish that by opening that page either with JavaScript, for example, by using window.open(), or through a link that has a target="_blank" attribute. You can find example code for the former in the demo below, and the latter in the article on opening links in a new window or tab.
If you only test your code in an old browser (eg, old versions of Chrome or Firefox, or any version of Internet Explorer), you will end up with the mistaken impression that it works fine even if the above conditions are not true. Newer browser versions impose these restrictions for security (and other) reasons.
Modern browsers will also resist your attempt to trick them into thinking that an existing window/tab was opened with JavaScript when it was not. Some older versions fell for such trickery, but these methods should no longer work in the current versions of Chrome and Firefox.
Also, for tab/window must be opened via window.open() for window.close(0 to work.
If you will to close the tab you've created with window.open you just have to store the new tab into variable and then use .close() method of this variable when you want to close it.
Short example:
const newWindow = window.open('');
setTimeout(() => newWindow.close(), 1000);
This example shows how to create new window and then close it after 1 sec.
If you want to manualy close the tab, just call newWindow.close() function wherever you want.

Popup without user action?

How is this site triggering its popup while bypassing Chrome's pop-up blocker?
http://undertexter.se/
I thought pop-up blockers only allowed window.open if it was triggered by a user action but that's not the case here so how are they doing it?
OUTDATED
Origin resources and fiddles do not work anymore.
I figured out that there is an popup opening in chrome if you visit the Website first time (empty cache) and click somewhere on the document.
After a refresh and a click on it again nothing will happen if cache wasn't removed.
So lets start the game of reverse engineering...
Took the script from
http://undertexter.se/ and startet refuscation.
After a few steps I got the following code and I think this is not planned by browser manufactures to support something like this.
Now I wish you a lot of luck to use that for your own but I think it's evil.
Look on js fiddle for the result:
Its the reverse of:
http://www.wigetmedia.com/tags/undertexter.se.js
http://jsfiddle.net/W9BdS/
Tested on my own server, This opens up http://google.com in a new (standalone) window in Chromium 28 on Ubuntu 12.04. Adblock is active.
<script type="text/javascript">
document.addEventListener('click', function() {
window.open('http://google.com','...','width=1080 height=640')
})
</script>
try this using JQuery
$('#yourCotrolId').on('click', function() {
window.open('yourLink','...','width=1080 height=640')
});
window.open is blocked by modern browsers when called not in a click event handler.
I faced this myself while using Rails' format.js responses and wrote a small plugin that makes showing JS popups as simple as calling window.open():
Popup("<div>Hello world</div>").show('up')
You could use the .trigger method for simulating an user action:
Click
$('a').trigger('click');
.trigger() can not be used to mimc such native browser events, you can use .simulate() from simulate.js to mimic such events.
include simulate.js in your file and use,
$('a').simulate('click');

Jquery mobile data-rel="dialog" doesnot work on iphone or ipad

The following code
<a data-rel="dialog" href="/Client/Events?ID=c2a7a58e-bef1-4574-987f-4adfc2c3ecc1">
<div class="ui-li-aside"> 1 </div>
<div>
Alejandra Garcia
</div>
</a>
This works on my computer browsers, also works on windows phone browser. But does not work on iphone or ipad browser. Looks like the link gets clicked but i see no dialog. Either it is super delayed or just not working.
The response and load time for the page is pretty quick and works seamless on a regular desktop browser. Its a very small page that loads up.
any tips that i should try to get it to work?
I suspect it has to do with urls you are using and JQM not understanding what to make of links like this:
/Client/Events/StubCheckIn/innasf?stubID=c807321b-5381-4338-adef-9e676374d85d
There is no file ending, no hashtag and I've been fighting with a simple [?para=meter] (https://github.com/jquery/jquery-mobile/issues/4253) link and JQM handling it for a few days.
The easiest way I solve "nothing happening on ipad" is enableing the iPad debugger and console.log-ging through the respective JQM widget. In your case start here (about line 3582):
// click routing - direct to HTTP or Ajax, accordingly
$( document ).bind( "click", function( event ) {
// your first flag
console.log("flag 1 - click detected")
if( !$.mobile.linkBindingEnabled ){
return;
}
var link = findClosestLink( event.target ), $link = $( link ), httpCleanup;
if ( !link || event.which > 1 || !$link.jqmHijackable().length ) {
// your second flag
console.log("flag 2 - not a link?!?)
return;
}
...
Do this all the way through the click-handler and make sure you flag all returns, which end the function for various reasons.
When you are done with the click-handler (not that long) you will see it firing a changePage, so follow it to the changePage handler and continue flagging. This should start around line (#3232) here:
// Show a specific page in the page container.
$.mobile.changePage = function( toPage, options ) {
console.log("flag x - made it to changepage");
...
Go all the way through changepage and then follow to transitionpages (that won't be it I think) and $.mobile.loadPage (about #2931, more likely).
Once you have flagged everything (stop after loadpage! :-), reload the page on browser and ipad and see where the ipad fails vs the browser. Probably will take an hour but you will have a good understanding of how JQM works afterwards :-)
Another reason could be the pushstate handler (about #3781). If a browser supports pushstate (desktop yes, iOS... not sure, iOS3 no) you can make nice URLs, so if you go from your page:
root.com/client/events/checkin/innasf
to a dialog
http://root.com/Client/Events/StubCheckIn/innasf?stubID=96e63aee-1465-4ecd-ad35-123f240d09ff
your browser still displays the page url - probably because you set changehash to false (which keeps the url). This (I believe) is done by the pushstate handler, because your URL should be:
root.com/client/events/checkin/innasf#http://root.com/Client/Events/StubCheckIn/innasf?stubID=96e63aee-1465-4ecd-ad35-123f240d09ff&some-dialog-ending
This will be the url non-pushstate devices will try to resolve (my iPad ios3.3, for example), where it also does not work.
My guess however would be that your links fail somewhere in the click or changepage handler, when the URL is resolved by JQM.
If you flag yourself through, let me know where the difference between browser and iOS shows up. Then we can see if this is fixable.
Ok, I checked the site under the Debug console in iOS Safari. It appears Safari is blocking the cross-domain request to facebook that your dialog loads (referenced here: Unsafe JavaScript attempt to access frame warning in Safari) - that was the warning the debug console showed. From my research, it seems Safari is stricter about this than other browsers.

window.onbeforeunload not working on the iPad?

Does anyone know if the onbeforeunload event is supported on the iPad and/or if there's a different way to use it?
I've tried pretty much everything, and it seems like the onbeforeunload event is never triggered on the iPad (Safari browser).
Specifically, this is what I've tried:
window.onbeforeunload = function(event) { event.returnValue = 'test'; }
window.onbeforeunload = function(event) { return 'test'; }
(both of the above together)
window.onbeforeunload = function(event) { alert('test')'; }
(all of the above functions but inside <body onbeforeunload="...">
All of these work on FF and Safari on the PC, but not on the iPad.
Also, I've done the following just after loading the page:
alert('onbeforeunload' in window);
alert(typeof window.onbeforeunload);
alert(window.onbeforeunload);
Respectively, the results are:
true
object
null
So, the browser does have the property, but for some reason it doesn't get fired.
The ways I try to navigate away from the page are by clicking the back and forward buttons, by doing a google search in the top bar, by changing location in the address bar, and by clicking on a bookmark.
Does anyone have any idea about what's going on? I'd greatly appreciate any input.
Thanks
This bit of JavaScript works for me on Safari and Chrome on ipad and iphone, as well as desktop/laptop/other browsers:
var isOnIOS = navigator.userAgent.match(/iPad/i)|| navigator.userAgent.match(/iPhone/i);
var eventName = isOnIOS ? "pagehide" : "beforeunload";
window.addEventListener(eventName, function (event) {
window.event.cancelBubble = true; // Don't know if this works on iOS but it might!
...
} );
I have found that the onunload() event does fire. It's behavior is somewhat odd; whatever you have in your callback function attached to the event is actually run after the new page has loaded in the background (You can't tell it's loaded yet, but server logging will show that it has).
More oddly, if you have a confirm() call in your onunload(), and the user has clicked a link to go somewhere else, you are in business. If, however, the user closes the iPad Safari browser tab, the onunload() event will fire, but your confirm() will have an implicit cancel as response.
Only Apple would know for sure, but my guess is that they purposely did not enable that functionality in mobile Safari because it is most often used by shady characters to get you to stay on their site or pop up lots of porn/advertising windows.
There's a known bug in WebKit with onbeforeunload. I believe it's fixed in the latest beta of Chrome 5, but it's quite possible the iPad's browser is made from a version of WebKit that doesn't have the fix.
Related Chrome bug report.
beforeunload event is not supported by Mobile Safari. You can see the list of all supported events here: Handling Events Apple documentation
And the beforeunload is not in the list!
https://code.google.com/p/chromium/issues/detail?id=97035
see hear.
alerts are no longer allowed during page dismissal events (beforeunload, unload, pagehide).
I think alerts, prompt, confirm, and other actions like these are also no longer allowed.
Here's a solution that should work on all modern browsers:
var unloaded = false;
window.addEventListener("beforeunload", function(e)
{
if (unloaded)
return;
unloaded = true;
console.log("beforeUnload");
});
window.addEventListener("visibilitychange", function(e)
{
if (document.visibilityState == 'hidden')
{
if (unloaded)
return;
unloaded = true;
console.log("beforeUnload");
}
});
Mobile browsers don't tend to not support beforeunload because the browser can go into the background without unloading the page, then be killed by the operating system at any time.
Most desktop browser contain a bug that causes visibilityState to not get called when the document unloads. See: here.
Therefore, it's important to include both events to cover all scenarios.
NB
I have used console.log instead of alert in my example because alert will get blocked by some browsers when called from beforeunload or visibilitychange.
If you just need to know if the page has been left you can use document.unload. It works fine in ios browsers. If you see on Apple documentation you'll find that it's deprecated and they recommend to use document.pagehide

iFrame Navigation controlled by JS

I'm using javascript to control the href= field of the iframe located within the page. I am currently using
function DoIFrameNav(object_URL)
{
document.all.additionalText.src="iframeContents.php?id="+object_URL;
selectedEvent = object_URL;
}//end DoIFrameNav
to perform this action. And
onclick=\"DoIFrameNav(".$iCounter.");
to call the action when the user clicks on the table row.
It works perfectly in Firefox and IE6, but nothing else...
Chrome just ignores it...
What would be the universally browser compatible way of doing this?
You should not use document.all in a script that is intended to be cross-browser. Removing that should be your first step. Use document.getElementById() instead. At that point, the code you posted should be acceptable to all major browsers (hopefully).

Categories