Related
In my application, I tried to print out a voucher page for the user like this:
var htm ="<div>Voucher Details</div>";
$('#divprint').html(htm);
window.setTimeout('window.print()',2000);
'divprint' is a div in my page which store information about the voucher.
It works, and the print page pops up. But I want to advance the application once the user clicks 'print' or 'close' in the browser's pop-up print dialog.
For example, I'd like to redirect user to another page after pop up window is closed:
window.application.directtoantherpage();//a function which direct user to other page
How can I determine when the pop up print window is closed or print is finished?
You can listen to the afterprint event.
https://developer.mozilla.org/en-US/docs/Web/API/window.onafterprint
window.onafterprint = function(){
console.log("Printing completed...");
}
It may be possible to use window.matchMedia to get this functionality in another way.
(function() {
var beforePrint = function() {
console.log('Functionality to run before printing.');
};
var afterPrint = function() {
console.log('Functionality to run after printing');
};
if (window.matchMedia) {
var mediaQueryList = window.matchMedia('print');
mediaQueryList.addListener(function(mql) {
if (mql.matches) {
beforePrint();
} else {
afterPrint();
}
});
}
window.onbeforeprint = beforePrint;
window.onafterprint = afterPrint;
}());
Source: http://tjvantoll.com/2012/06/15/detecting-print-requests-with-javascript/
On chrome (V.35.0.1916.153 m) Try this:
function loadPrint() {
window.print();
setTimeout(function () { window.close(); }, 100);
}
Works great for me. It will close window after user finished working on printing dialog.
compatible with chrome, firefox, opera, Internet Explorer
Note: jQuery required.
<script>
window.onafterprint = function(e){
$(window).off('mousemove', window.onafterprint);
console.log('Print Dialog Closed..');
};
window.print();
setTimeout(function(){
$(window).one('mousemove', window.onafterprint);
}, 1);
</script>
See https://stackoverflow.com/a/15662720/687315. As a workaround, you can listen for the afterPrint event on the window (Firefox and IE) and listen for mouse movement on the document (indicating that the user has closed the print dialog and returned to the page) after the window.mediaMatch API indicates that the media no longer matches "print" (Firefox and Chrome).
Keep in mind that the user may or may not have actually printed the document. Also, if you call window.print() too often in Chrome, the user may not have even been prompted to print.
window.print behaves synchronously on chrome .. try this in your console
window.print();
console.log("printed");
"printed" doesn't display unless the print dialog is closed(canceled/saved/printed) by the user.
Here is a more detailed explanation about this issue.
I am not sure about IE or Firefox will check and update that later
You can detect when window.print() is finished simply by putting it in another function
//function to call if you want to print
var onPrintFinished=function(printed){console.log("do something...");}
//print command
onPrintFinished(window.print());
tested in Firefox,Google chrome,IE
This Actually worked for me in chrome. I was pretty suprised.
jQuery(document).bind("keyup keydown", function(e){
if(e.ctrlKey && e.keyCode == 80){
Print(); e.preventDefault();
}
});
Where Print is a function I wrote that calls window.print(); It also works as a pure blocker if you disable Print();
As noted here by user3017502
window.print() will pause so you can add an onPrintFinish or onPrintBegin like this
function Print(){
onPrintBegin
window.print();
onPrintFinish();
}
Tested IE, FF, Chrome and works in all.
setTimeout(function () { window.print(); }, 500);
window.onfocus = function () { setTimeout(function () { window.close(); }, 500); }
Given that you wish to wait for the print dialog to go away I would use focus binding on the window.
print();
var handler = function(){
//unbind task();
$(window).unbind("focus",handler);
}
$(window).bind("focus",handler);
By putting in the unbind in the handler function we prevent the focus event staying bond to the window.
Simplest way to detect if print has finished and close print window:
window.onafterprint = function(){
window.onfocus = function(){
window.close();
}
};
Print in new window with w = window.open(url, '_blank') and try w.focus();w.close(); and detect when page is closed. Works in all browsers.
w = window.open(url, '_blank');
w.onunload = function(){
console.log('closed!');
}
w.focus();
w.print();
w.close();
Window close after finish print.
It works for me with $(window).focus().
var w;
var src = 'http://pagetoprint';
if (/chrom(e|ium)/.test(navigator.userAgent.toLowerCase())) {
w = $('<iframe></iframe>');
w.attr('src', src);
w.css('display', 'none');
$('body').append(w);
w.load(function() {
w[0].focus();
w[0].contentWindow.print();
});
$(window).focus(function() {
console.log('After print');
});
}
else {
w = window.open(src);
$(w).unload(function() {
console.log('After print');
});
}
I think the window focus approach is the correct one. Here is an example in which I wanted to open a PDF url blob in a hidden iframe and print it. After printed or canceled, I wanted to remove the iframe.
/**
* printBlob will create if not exists an iframe to load
* the pdf. Once the window is loaded, the PDF is printed.
* It then creates a one-time event to remove the iframe from
* the window.
* #param {string} src Blob or any printable url.
*/
export const printBlob = (src) => {
if (typeof window === 'undefined') {
throw new Error('You cannot print url without defined window.');
}
const iframeId = 'pdf-print-iframe';
let iframe = document.getElementById(iframeId);
if (!iframe) {
iframe = document.createElement('iframe');
iframe.setAttribute('id', iframeId);
iframe.setAttribute('style', 'position:absolute;left:-9999px');
document.body.append(iframe);
}
iframe.setAttribute('src', src);
iframe.addEventListener('load', () => {
iframe.contentWindow.focus();
iframe.contentWindow.print();
const infanticide = () => {
iframe.parentElement.removeChild(iframe);
window.removeEventListener('focus', infanticide);
}
window.addEventListener('focus', infanticide);
});
};
It is difficult, due to different browser behavior after print. Desktop Chrome handles the print dialogue internally, so doesn't shift focus after print, however, afterprint event works fine here (As of now, 81.0). On the other hand, Chrome on mobile device and most of the other browsers shifts focus after print and afterprint event doesn't work consistently here. Mouse movement event doesn't work on mobile devices.
So, Detect if it is Desktop Chrome,
If Yes, use afterprint event. If No, use focus based detection. You can also use mouse movement event(Works in desktop only) in combination of these, to cover more browsers and more scenarios.
well, just to remind everyone that the afterprint will not determine the print action button instead it will execute whenever the print window is closed or closing, both cancel button or esc key which closing the print window will consider afterprint while there is no actual print happening yet.
Implementing window.onbeforeprint and window.onafterprint
The window.close() call after the window.print() is not working in Chrome v 78.0.3904.70
To approach this I'm using Adam's answer with a simple modification:
function print() {
(function () {
let afterPrintCounter = !!window.chrome ? 0 : 1;
let beforePrintCounter = !!window.chrome ? 0 : 1;
var beforePrint = function () {
beforePrintCounter++;
if (beforePrintCounter === 2) {
console.log('Functionality to run before printing.');
}
};
var afterPrint = function () {
afterPrintCounter++;
if (afterPrintCounter === 2) {
console.log('Functionality to run after printing.');
//window.close();
}
};
if (window.matchMedia) {
var mediaQueryList = window.matchMedia('print');
mediaQueryList.addListener(function (mql) {
if (mql.matches) {
beforePrint();
} else {
afterPrint();
}
});
}
window.onbeforeprint = beforePrint;
window.onafterprint = afterPrint;
}());
//window.print(); //To print the page when it is loaded
}
I'm calling it in here:
<body onload="print();">
This works for me.
Note that I use a counter for both functions, so that I can handle this event in different browsers (fires twice in Chrome, and one time in Mozilla).
For detecting the browser you can refer to this answer
Rewriting the question -
I am trying to make a page on which if user leave the page (either to other link/website or closing window/tab) I want to show the onbeforeunload handeler saying we have a great offer for you? and if user choose to leave the page it should do the normal propogation but if he choose to stay on the page I need him to redirect it to offer page redirection is important, no compromise. For testing lets redirect to google.com
I made a program as follows -
var stayonthis = true;
var a;
function load() {
window.onbeforeunload = function(e) {
if(stayonthis){
a = setTimeout('window.location.href="http://google.com";',100);
stayonthis = false;
return "Do you really want to leave now?";
}
else {
clearTimeout(a);
}
};
window.onunload = function(e) {
clearTimeout(a);
};
}
window.onload = load;
but the problem is that if he click on the link to yahoo.com and choose to leave the page he is not going to yahoo but to google instead :(
Help Me !! Thanks in Advance
here is the fiddle code
here how you can test because onbeforeunload does not work on iframe well
This solution works in all cases, using back browser button, setting new url in address bar or use links.
What i have found is that triggering onbeforeunload handler doesn't show the dialog attached to onbeforeunload handler.
In this case (when triggering is needed), use a confirm box to show the user message. This workaround is tested in chrome/firefox and IE (7 to 10)
http://jsfiddle.net/W3vUB/4/show
http://jsfiddle.net/W3vUB/4/
EDIT: set DEMO on codepen, apparently jsFiddle doesn't like this snippet(?!)
BTW, using bing.com due to google not allowing no more content being displayed inside iframe.
http://codepen.io/anon/pen/dYKKbZ
var a, b = false,
c = "http://bing.com";
function triggerEvent(el, type) {
if ((el[type] || false) && typeof el[type] == 'function') {
el[type](el);
}
}
$(function () {
$('a:not([href^=#])').on('click', function (e) {
e.preventDefault();
if (confirm("Do you really want to leave now?")) c = this.href;
triggerEvent(window, 'onbeforeunload');
});
});
window.onbeforeunload = function (e) {
if (b) return;
a = setTimeout(function () {
b = true;
window.location.href = c;
c = "http://bing.com";
console.log(c);
}, 500);
return "Do you really want to leave now?";
}
window.onunload = function () {
clearTimeout(a);
}
It's better to Check it local.
Check out the comments and try this: LIVE DEMO
var linkClick=false;
document.onclick = function(e)
{
linkClick = true;
var elemntTagName = e.target.tagName;
if(elemntTagName=='A')
{
e.target.getAttribute("href");
if(!confirm('Are your sure you want to leave?'))
{
window.location.href = "http://google.com";
console.log("http://google.com");
}
else
{
window.location.href = e.target.getAttribute("href");
console.log(e.target.getAttribute("href"));
}
return false;
}
}
function OnBeforeUnLoad ()
{
return "Are you sure?";
linkClick=false;
window.location.href = "http://google.com";
console.log("http://google.com");
}
And change your html code to this:
<body onbeforeunload="if(linkClick == false) {return OnBeforeUnLoad()}">
try it
</body>
After playing a while with this problem I did the following. It seems to work but it's not very reliable. The biggest issue is that the timed out function needs to bridge a large enough timespan for the browser to make a connection to the url in the link's href attribute.
jsfiddle to demonstrate. I used bing.com instead of google.com because of X-Frame-Options: SAMEORIGIN
var F = function(){}; // empty function
var offerUrl = 'http://bing.com';
var url;
var handler = function(e) {
timeout = setTimeout(function () {
console.log('location.assign');
location.assign(offerUrl);
/*
* This value makes or breaks it.
* You need enough time so the browser can make the connection to
* the clicked links href else it will still redirect to the offer url.
*/
}, 1400);
// important!
window.onbeforeunload = F;
console.info('handler');
return 'Do you wan\'t to leave now?';
};
window.onbeforeunload = handler;
Try the following, (adds a global function that checks the state all the time though).
var redirected=false;
$(window).bind('beforeunload', function(e){
if(redirected)
return;
var orgLoc=window.location.href;
$(window).bind('focus.unloadev',function(e){
if(redirected==true)
return;
$(window).unbind('focus.unloadev');
window.setTimeout(function(){
if(window.location.href!=orgLoc)
return;
console.log('redirect...');
window.location.replace('http://google.com');
},6000);
redirected=true;
});
console.log('before2');
return "okdoky2";
});
$(window).unload(function(e){console.log('unloading...');redirected=true;});
<script>
function endSession() {
// Browser or Broswer tab is closed
// Write code here
alert('Browser or Broswer tab closed');
}
</script>
<body onpagehide="endSession();">
I think you're confused about the progress of events, on before unload the page is still interacting, the return method is like a shortcut for return "confirm()", the return of the confirm however cannot be handled at all, so you can not really investigate the response of the user and decide upon it which way to go, the response is going to be immediately carried out as "yes" leave page, or "no" don't leave page...
Notice that you have already changed the source of the url to Google before you prompt user, this action, cannot be undone... unless maybe, you can setimeout to something like 5 seconds (but then if the user isn't quick enough it won't pick up his answer)
Edit: I've just made it a 5000 time lapse and it always goes to Yahoo! Never picks up the google change at all.
I have a javascript function that runs on window.onload:
if(window.onload) {
var curronload = window.onload;
var newonload = function() {
curronload();
formatICCID_IMEI();
};
window.onload = newonload;
} else {
window.onload = formatICCID_IMEI;
function formatICCID_IMEI() {
var IMEI = $find("<%=cbIMEI.ClientID %>");
alert(IMEI.get_textBoxControl().value);
alert(IMEI.get_textBoxControl().value.indexOf("."));
if (IMEI.get_textBoxControl().value.indexOf(".") > -1) {
alert("Hi!");
}
}
I'm using this more elaborate way of calling my function from this link because if I just use window.onload or document.onload, my control (cbIMEI) is not found. Using this more elaborate method, I don't have that problem. However, my function formatICCID_IMEI is acting strangely. I don't know if it's due to the way I'm calling formatICCID_IMEI, or just something in formatICCID_IMEI that I'm not seeing. If I comment out
if (IMEI.get_textBoxControl().value.indexOf(".") > -1) {
alert("Hi!");
the first and second alerts tell me that
IMEI.get_textBoxControl().value = 351937.04.230880.7
and that
IMEI.get_textBoxControl().value.indexOf = 6
all as expected. HOWEVER, if I comment out the two above alert lines and uncomment the IF condition, the line
alert("Hi!");
never runs. If I uncomment all lines, none of the alerts run. The same behavior holds true if I'm in debug mode. If the condition is uncommented, my cursor never gets to my function at all. What the heck?
You have no close bracket for the if(window.onload) condition - is that intentional?
Since you're using jQuery, why are you not just using the standard $(document).ready stuff?
function formatICCID_IMEI() {
var IMEI = $find("<%=cbIMEI.ClientID %>");
alert(IMEI.get_textBoxControl().value);
alert(IMEI.get_textBoxControl().value.indexOf("."));
if (IMEI.get_textBoxControl().value.indexOf(".") > -1) {
alert("Hi!");
}
}
$(document).ready(formatICCID_IMEI);
In my application, I tried to print out a voucher page for the user like this:
var htm ="<div>Voucher Details</div>";
$('#divprint').html(htm);
window.setTimeout('window.print()',2000);
'divprint' is a div in my page which store information about the voucher.
It works, and the print page pops up. But I want to advance the application once the user clicks 'print' or 'close' in the browser's pop-up print dialog.
For example, I'd like to redirect user to another page after pop up window is closed:
window.application.directtoantherpage();//a function which direct user to other page
How can I determine when the pop up print window is closed or print is finished?
You can listen to the afterprint event.
https://developer.mozilla.org/en-US/docs/Web/API/window.onafterprint
window.onafterprint = function(){
console.log("Printing completed...");
}
It may be possible to use window.matchMedia to get this functionality in another way.
(function() {
var beforePrint = function() {
console.log('Functionality to run before printing.');
};
var afterPrint = function() {
console.log('Functionality to run after printing');
};
if (window.matchMedia) {
var mediaQueryList = window.matchMedia('print');
mediaQueryList.addListener(function(mql) {
if (mql.matches) {
beforePrint();
} else {
afterPrint();
}
});
}
window.onbeforeprint = beforePrint;
window.onafterprint = afterPrint;
}());
Source: http://tjvantoll.com/2012/06/15/detecting-print-requests-with-javascript/
On chrome (V.35.0.1916.153 m) Try this:
function loadPrint() {
window.print();
setTimeout(function () { window.close(); }, 100);
}
Works great for me. It will close window after user finished working on printing dialog.
compatible with chrome, firefox, opera, Internet Explorer
Note: jQuery required.
<script>
window.onafterprint = function(e){
$(window).off('mousemove', window.onafterprint);
console.log('Print Dialog Closed..');
};
window.print();
setTimeout(function(){
$(window).one('mousemove', window.onafterprint);
}, 1);
</script>
See https://stackoverflow.com/a/15662720/687315. As a workaround, you can listen for the afterPrint event on the window (Firefox and IE) and listen for mouse movement on the document (indicating that the user has closed the print dialog and returned to the page) after the window.mediaMatch API indicates that the media no longer matches "print" (Firefox and Chrome).
Keep in mind that the user may or may not have actually printed the document. Also, if you call window.print() too often in Chrome, the user may not have even been prompted to print.
window.print behaves synchronously on chrome .. try this in your console
window.print();
console.log("printed");
"printed" doesn't display unless the print dialog is closed(canceled/saved/printed) by the user.
Here is a more detailed explanation about this issue.
I am not sure about IE or Firefox will check and update that later
You can detect when window.print() is finished simply by putting it in another function
//function to call if you want to print
var onPrintFinished=function(printed){console.log("do something...");}
//print command
onPrintFinished(window.print());
tested in Firefox,Google chrome,IE
This Actually worked for me in chrome. I was pretty suprised.
jQuery(document).bind("keyup keydown", function(e){
if(e.ctrlKey && e.keyCode == 80){
Print(); e.preventDefault();
}
});
Where Print is a function I wrote that calls window.print(); It also works as a pure blocker if you disable Print();
As noted here by user3017502
window.print() will pause so you can add an onPrintFinish or onPrintBegin like this
function Print(){
onPrintBegin
window.print();
onPrintFinish();
}
Tested IE, FF, Chrome and works in all.
setTimeout(function () { window.print(); }, 500);
window.onfocus = function () { setTimeout(function () { window.close(); }, 500); }
Given that you wish to wait for the print dialog to go away I would use focus binding on the window.
print();
var handler = function(){
//unbind task();
$(window).unbind("focus",handler);
}
$(window).bind("focus",handler);
By putting in the unbind in the handler function we prevent the focus event staying bond to the window.
Simplest way to detect if print has finished and close print window:
window.onafterprint = function(){
window.onfocus = function(){
window.close();
}
};
Print in new window with w = window.open(url, '_blank') and try w.focus();w.close(); and detect when page is closed. Works in all browsers.
w = window.open(url, '_blank');
w.onunload = function(){
console.log('closed!');
}
w.focus();
w.print();
w.close();
Window close after finish print.
It works for me with $(window).focus().
var w;
var src = 'http://pagetoprint';
if (/chrom(e|ium)/.test(navigator.userAgent.toLowerCase())) {
w = $('<iframe></iframe>');
w.attr('src', src);
w.css('display', 'none');
$('body').append(w);
w.load(function() {
w[0].focus();
w[0].contentWindow.print();
});
$(window).focus(function() {
console.log('After print');
});
}
else {
w = window.open(src);
$(w).unload(function() {
console.log('After print');
});
}
I think the window focus approach is the correct one. Here is an example in which I wanted to open a PDF url blob in a hidden iframe and print it. After printed or canceled, I wanted to remove the iframe.
/**
* printBlob will create if not exists an iframe to load
* the pdf. Once the window is loaded, the PDF is printed.
* It then creates a one-time event to remove the iframe from
* the window.
* #param {string} src Blob or any printable url.
*/
export const printBlob = (src) => {
if (typeof window === 'undefined') {
throw new Error('You cannot print url without defined window.');
}
const iframeId = 'pdf-print-iframe';
let iframe = document.getElementById(iframeId);
if (!iframe) {
iframe = document.createElement('iframe');
iframe.setAttribute('id', iframeId);
iframe.setAttribute('style', 'position:absolute;left:-9999px');
document.body.append(iframe);
}
iframe.setAttribute('src', src);
iframe.addEventListener('load', () => {
iframe.contentWindow.focus();
iframe.contentWindow.print();
const infanticide = () => {
iframe.parentElement.removeChild(iframe);
window.removeEventListener('focus', infanticide);
}
window.addEventListener('focus', infanticide);
});
};
It is difficult, due to different browser behavior after print. Desktop Chrome handles the print dialogue internally, so doesn't shift focus after print, however, afterprint event works fine here (As of now, 81.0). On the other hand, Chrome on mobile device and most of the other browsers shifts focus after print and afterprint event doesn't work consistently here. Mouse movement event doesn't work on mobile devices.
So, Detect if it is Desktop Chrome,
If Yes, use afterprint event. If No, use focus based detection. You can also use mouse movement event(Works in desktop only) in combination of these, to cover more browsers and more scenarios.
well, just to remind everyone that the afterprint will not determine the print action button instead it will execute whenever the print window is closed or closing, both cancel button or esc key which closing the print window will consider afterprint while there is no actual print happening yet.
Implementing window.onbeforeprint and window.onafterprint
The window.close() call after the window.print() is not working in Chrome v 78.0.3904.70
To approach this I'm using Adam's answer with a simple modification:
function print() {
(function () {
let afterPrintCounter = !!window.chrome ? 0 : 1;
let beforePrintCounter = !!window.chrome ? 0 : 1;
var beforePrint = function () {
beforePrintCounter++;
if (beforePrintCounter === 2) {
console.log('Functionality to run before printing.');
}
};
var afterPrint = function () {
afterPrintCounter++;
if (afterPrintCounter === 2) {
console.log('Functionality to run after printing.');
//window.close();
}
};
if (window.matchMedia) {
var mediaQueryList = window.matchMedia('print');
mediaQueryList.addListener(function (mql) {
if (mql.matches) {
beforePrint();
} else {
afterPrint();
}
});
}
window.onbeforeprint = beforePrint;
window.onafterprint = afterPrint;
}());
//window.print(); //To print the page when it is loaded
}
I'm calling it in here:
<body onload="print();">
This works for me.
Note that I use a counter for both functions, so that I can handle this event in different browsers (fires twice in Chrome, and one time in Mozilla).
For detecting the browser you can refer to this answer
I am aware of javascript techniques to detect whether a popup is blocked in other browsers (as described in the answer to this question). Here's the basic test:
var newWin = window.open(url);
if(!newWin || newWin.closed || typeof newWin.closed=='undefined')
{
//POPUP BLOCKED
}
But this does not work in Chrome. The "POPUP BLOCKED" section is never reached when the popup is blocked.
Of course, the test is working to an extent since Chrome doesn't actually block the popup, but opens it in a tiny minimized window at the lower right corner which lists "blocked" popups.
What I would like to do is be able to tell if the popup was blocked by Chrome's popup blocker. I try to avoid browser sniffing in favor of feature detection. Is there a way to do this without browser sniffing?
Edit: I have now tried making use of newWin.outerHeight, newWin.left, and other similar properties to accomplish this. Google Chrome returns all position and height values as 0 when the popup is blocked.
Unfortunately, it also returns the same values even if the popup is actually opened for an unknown amount of time. After some magical period (a couple of seconds in my testing), the location and size information is returned as the correct values. In other words, I'm still no closer to figuring this out. Any help would be appreciated.
Well the "magical time" you speak of is probably when the popup's DOM has been loaded. Or else it might be when everything (images, outboard CSS, etc.) has been loaded. You could test this easily by adding a very large graphic to the popup (clear your cache first!). If you were using a Javascript Framework like jQuery (or something similar), you could use the ready() event (or something similar) to wait for the DOM to load before checking the window offset. The danger in this is that Safari detection works in a conflicting way: the popup's DOM will never be ready() in Safari because it'll give you a valid handle for the window you're trying to open -- whether it actually opens or not. (in fact, i believe your popup test code above won't work for safari.)
I think the best thing you can do is wrap your test in a setTimeout() and give the popup 3-5 seconds to complete loading before running the test. It's not perfect, but it should work at least 95% of the time.
Here's the code I use for cross-browser detection, without the Chrome part.
function _hasPopupBlocker(poppedWindow) {
var result = false;
try {
if (typeof poppedWindow == 'undefined') {
// Safari with popup blocker... leaves the popup window handle undefined
result = true;
}
else if (poppedWindow && poppedWindow.closed) {
// This happens if the user opens and closes the client window...
// Confusing because the handle is still available, but it's in a "closed" state.
// We're not saying that the window is not being blocked, we're just saying
// that the window has been closed before the test could be run.
result = false;
}
else if (poppedWindow && poppedWindow.test) {
// This is the actual test. The client window should be fine.
result = false;
}
else {
// Else we'll assume the window is not OK
result = true;
}
} catch (err) {
//if (console) {
// console.warn("Could not access popup window", err);
//}
}
return result;
}
What I do is run this test from the parent and wrap it in a setTimeout(), giving the child window 3-5 seconds to load. In the child window, you need to add a test function:
function test() {}
The popup blocker detector tests to see whether the "test" function exists as a member of the child window.
ADDED JUNE 15 2015:
I think the modern way to handle this would be to use window.postMessage() to have the child notify the parent that the window has been loaded. The approach is similar (child tells parent it's loaded), but the means of communication has improved. I was able to do this cross-domain from the child:
$(window).load(function() {
this.opener.postMessage({'loaded': true}, "*");
this.close();
});
The parent listens for this message using:
$(window).on('message', function(event) {
alert(event.originalEvent.data.loaded)
});
Hope this helps.
Just one improvement to InvisibleBacon's snipet (tested in IE9, Safari 5, Chrome 9 and FF 3.6):
var myPopup = window.open("popupcheck.htm", "", "directories=no,height=150,width=150,menubar=no,resizable=no,scrollbars=no,status=no,titlebar=no,top=0,location=no");
if (!myPopup)
alert("failed for most browsers");
else {
myPopup.onload = function() {
setTimeout(function() {
if (myPopup.screenX === 0) {
alert("failed for chrome");
} else {
// close the test window if popups are allowed.
myPopup.close();
}
}, 0);
};
}
The following is a jQuery solution to popup blocker checking. It has been tested in FF (v11), Safari (v6), Chrome (v23.0.127.95) & IE (v7 & v9). Update the _displayError function to handle the error message as you see fit.
var popupBlockerChecker = {
check: function(popup_window){
var _scope = this;
if (popup_window) {
if(/chrome/.test(navigator.userAgent.toLowerCase())){
setTimeout(function () {
_scope._is_popup_blocked(_scope, popup_window);
},200);
}else{
popup_window.onload = function () {
_scope._is_popup_blocked(_scope, popup_window);
};
}
}else{
_scope._displayError();
}
},
_is_popup_blocked: function(scope, popup_window){
if ((popup_window.innerHeight > 0)==false){ scope._displayError(); }
},
_displayError: function(){
alert("Popup Blocker is enabled! Please add this site to your exception list.");
}
};
Usage:
var popup = window.open("http://www.google.ca", '_blank');
popupBlockerChecker.check(popup);
Hope this helps! :)
Rich's answer isn't going to work anymore for Chrome. Looks like Chrome actually executes any Javascript in the popup window now. I ended up checking for a screenX value of 0 to check for blocked popups. I also think I found a way to guarantee that this property is final before checking. This only works for popups on your domain, but you can add an onload handler like this:
var myPopup = window.open("site-on-my-domain", "screenX=100");
if (!myPopup)
alert("failed for most browsers");
else {
myPopup.onload = function() {
setTimeout(function() {
if (myPopup.screenX === 0)
alert("failed for chrome");
}, 0);
};
}
As many have reported, the "screenX" property sometimes reports non-zero for failed popups, even after onload. I experienced this behavior as well, but if you add the check after a zero ms timeout, the screenX property always seems to output a consistent value.
Let me know if there are ways to make this script more robust. Seems to work for my purposes though.
This worked for me:
cope.PopupTest.params = 'height=1,width=1,left=-100,top=-100,location=no,toolbar=no,menubar=no,scrollbars=no,resizable=no,directories=no,status=no';
cope.PopupTest.testWindow = window.open("popupTest.htm", "popupTest", cope.PopupTest.params);
if( !cope.PopupTest.testWindow
|| cope.PopupTest.testWindow.closed
|| (typeof cope.PopupTest.testWindow.closed=='undefined')
|| cope.PopupTest.testWindow.outerHeight == 0
|| cope.PopupTest.testWindow.outerWidth == 0
) {
// pop-ups ARE blocked
document.location.href = 'popupsBlocked.htm';
}
else {
// pop-ups are NOT blocked
cope.PopupTest.testWindow.close();
}
The outerHeight and outerWidth are for chrome because the 'about:blank' trick from above doesn't work in chrome anymore.
I'm going to just copy/paste the answer provided here: https://stackoverflow.com/a/27725432/892099 by DanielB . works on chrome 40 and it's very clean. no dirty hacks or waiting involves.
function popup(urlToOpen) {
var popup_window=window.open(urlToOpen,"myWindow","toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, copyhistory=yes, width=400, height=400");
try {
popup_window.focus();
}
catch (e) {
alert("Pop-up Blocker is enabled! Please add this site to your exception list.");
}
}
How about a Promise approach ?
const openPopUp = (...args) => new Promise(s => {
const win = window.open(...args)
if (!win || win.closed) return s()
setTimeout(() => (win.innerHeight > 0 && !win.closed) ? s(win) : s(), 200)
})
And you can use it like the classic window.open
const win = await openPopUp('popuptest.htm', 'popuptest')
if (!win) {
// popup closed or blocked, handle alternative case
}
You could change the code so that it fail the promise instead of returning undefined, I just thought that if was an easier control flow than try / catch for this case.
Check the position of the window relative to the parent. Chrome makes the window appear almost off-screen.
I had a similar problem with popups not opening in Chrome. I was frustrated because I wasn't trying to do something sneaky, like an onload popup, just opening a window when the user clicked. I was DOUBLY frustrated because running my function which included the window.open() from the firebug command line worked, while actually clicking on my link didn't! Here was my solution:
Wrong way: running window.open() from an event listener (in my case, dojo.connect to the onclick event method of a DOM node).
dojo.connect(myNode, "onclick", function() {
window.open();
}
Right way: assigning a function to the onclick property of the node that called window.open().
myNode.onclick = function() {
window.open();
}
And, of course, I can still do event listeners for that same onclick event if I need to. With this change, I could open my windows even though Chrome was set to "Do not allow any site to show pop-ups". Joy.
If anyone wise in the ways of Chrome can tell the rest of us why it makes a difference, I'd love to hear it, although I suspect it's just an attempt to shut the door on malicious programmatic popups.
Here's a version that is currently working in Chrome. Just a small alteration away from Rich's solution, though I added in a wrapper that handles the timing too.
function checkPopupBlocked(poppedWindow) {
setTimeout(function(){doCheckPopupBlocked(poppedWindow);}, 5000);
}
function doCheckPopupBlocked(poppedWindow) {
var result = false;
try {
if (typeof poppedWindow == 'undefined') {
// Safari with popup blocker... leaves the popup window handle undefined
result = true;
}
else if (poppedWindow && poppedWindow.closed) {
// This happens if the user opens and closes the client window...
// Confusing because the handle is still available, but it's in a "closed" state.
// We're not saying that the window is not being blocked, we're just saying
// that the window has been closed before the test could be run.
result = false;
}
else if (poppedWindow && poppedWindow.outerWidth == 0) {
// This is usually Chrome's doing. The outerWidth (and most other size/location info)
// will be left at 0, EVEN THOUGH the contents of the popup will exist (including the
// test function we check for next). The outerWidth starts as 0, so a sufficient delay
// after attempting to pop is needed.
result = true;
}
else if (poppedWindow && poppedWindow.test) {
// This is the actual test. The client window should be fine.
result = false;
}
else {
// Else we'll assume the window is not OK
result = true;
}
} catch (err) {
//if (console) {
// console.warn("Could not access popup window", err);
//}
}
if(result)
alert("The popup was blocked. You must allow popups to use this site.");
}
To use it just do this:
var popup=window.open('location',etc...);
checkPopupBlocked(popup);
If the popup get's blocked, the alert message will display after the 5 second grace period (you can adjust that, but 5 seconds should be quite safe).
This fragment incorporates all of the above - For some reason - StackOverflow is excluding the first and last lines of code in the code block below, so I wrote a blog on it. For a full explanation and the rest of the (downloadable) code have a look at
my blog at thecodeabode.blogspot.com
var PopupWarning = {
init : function()
{
if(this.popups_are_disabled() == true)
{
this.redirect_to_instruction_page();
}
},
redirect_to_instruction_page : function()
{
document.location.href = "http://thecodeabode.blogspot.com";
},
popups_are_disabled : function()
{
var popup = window.open("http://localhost/popup_with_chrome_js.html", "popup_tester", "width=1,height=1,left=0,top=0");
if(!popup || popup.closed || typeof popup == 'undefined' || typeof popup.closed=='undefined')
{
return true;
}
window.focus();
popup.blur();
//
// Chrome popup detection requires that the popup validates itself - so we need to give
// the popup time to load, then call js on the popup itself
//
if(navigator && (navigator.userAgent.toLowerCase()).indexOf("chrome") > -1)
{
var on_load_test = function(){PopupWarning.test_chrome_popups(popup);};
var timer = setTimeout(on_load_test, 60);
return;
}
popup.close();
return false;
},
test_chrome_popups : function(popup)
{
if(popup && popup.chrome_popups_permitted && popup.chrome_popups_permitted() == true)
{
popup.close();
return true;
}
//
// If the popup js fails - popups are blocked
//
this.redirect_to_instruction_page();
}
};
PopupWarning.init();
Wow there sure are a lot of solutions here. This is mine, it uses solutions taken from the current accepted answer (which doesn't work in latest Chrome and requires wrapping it in a timeout), as well as a related solution on this thread (which is actually vanilla JS, not jQuery).
Mine uses a callback architecture which will be sent true when the popup is blocked and false otherwise.
window.isPopupBlocked = function(popup_window, cb)
{
var CHROME_CHECK_TIME = 2000; // the only way to detect this in Chrome is to wait a bit and see if the window is present
function _is_popup_blocked(popup)
{
return !popup.innerHeight;
}
if (popup_window) {
if (popup_window.closed) {
// opened OK but was closed before we checked
cb(false);
return;
}
if (/chrome/.test(navigator.userAgent.toLowerCase())) {
// wait a bit before testing the popup in chrome
setTimeout(function() {
cb(_is_popup_blocked(popup_window));
}, CHROME_CHECK_TIME);
} else {
// for other browsers, add an onload event and check after that
popup_window.onload = function() {
cb(_is_popup_blocked(popup_window));
};
}
} else {
cb(true);
}
};
Jason's answer is the only method I can think of too, but relying on position like that is a little bit dodgy!
These days, you don't really need to ask the question “was my unsolicited popup blocked?”, because the answer is invariably “yes” — all the major browsers have the popup blocker turned on by default. Best approach is only ever to window.open() in response to a direct click, which is almost always allowed.
HI
I modified the solutions described above slightly and think that it is working for Chrome at least.
My solution is made to detect if popup is blocked when the main page is opened, not when popup is opened, but i am sure there are some people that can modify it.:-)
The drawback here is that the popup-window is displayed for a couple of seconds (might be possible to shorten a bit) when there is no popup-blocker.
I put this in the section of my 'main' window
<script type="text/JavaScript" language="JavaScript">
var mine = window.open('popuptest.htm','popuptest','width=1px,height=1px,left=0,top=0,scrollbars=no');
if(!mine|| mine.closed || typeof mine.closed=='undefined')
{
popUpsBlocked = true
alert('Popup blocker detected ');
if(mine)
mine.close();
}
else
{
popUpsBlocked = false
var cookieCheckTimer = null;
cookieCheckTimer = setTimeout('testPopup();', 3500);
}
function testPopup()
{
if(mine)
{
if(mine.test())
{
popUpsBlocked = false;
}
else
{
alert('Popup blocker detected ');
popUpsBlocked = true;
}
mine.close();
}
}
</script>
The popuptest looks like this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Popup test</title>
<script type="text/javascript" language="Javascript">
function test() {if(window.innerHeight!=0){return true;} else return false;}
</script>
</head>
<body>
</body>
</html>
As i call the test-function on the popup-page after 3500 ms the innerheight has been set correctly by Chrome.
I use the variable popUpsBlocked to know if the popups are displayed or not in other javascripts.
i.e
function ShowConfirmationMessage()
{
if(popUpsBlocked)
{
alert('Popups are blocked, can not display confirmation popup. A mail will be sent with the confirmation.');
}
else
{
displayConfirmationPopup();
}
mailConfirmation();
}
function openPopUpWindow(format)
{
var win = window.open('popupShow.html',
'ReportViewer',
'width=920px,height=720px,left=50px,top=20px,location=no,directories=no,status=no,menubar=no,toolbar=no,resizable=1,maximize:yes,scrollbars=0');
if (win == null || typeof(win) == "undefined" || (win == null && win.outerWidth == 0) || (win != null && win.outerHeight == 0) || win.test == "undefined")
{
alert("The popup was blocked. You must allow popups to use this site.");
}
else if (win)
{
win.onload = function()
{
if (win.screenX === 0) {
alert("The popup was blocked. You must allow popups to use this site.");
win.close();
}
};
}
}
As far as I can tell (from what I've tested) Chrome returns a window object with location of 'about:blank'.
So, the following should work for all browsers:
var newWin = window.open(url);
if(!newWin || newWin.closed || typeof newWin.closed=='undefined' || newWin.location=='about:blank')
{
//POPUP BLOCKED
}