I am printing data from a new window after which I want to close the window. If I close the window straight away then it doesn't have enough time for the javascript function to run which writes data to the document.
I am using setTimeout to mimic this behaviour. However, I am wondering if there is a native way to do this.
For obvious reasons setting time out isn't an optimal solution as many things could block execution etc - perhaps a callback from the print function would do the trick, docs do not mention anything about it though.
Here's my code:
nw.Window.open('print.html', {show: false, new_instance: false}, function(new_win) {
new_win.on('loaded', function() {
this.print({autoprint: true, headerFooterEnabled: false});
});
});
And in the print.html:
var div = document.getElementById("orderBill");
div.innerHTML = '<h1>Header</h1><p>Some text</p>';
var win = nw.Window.get();
setTimeout(function(){ win.close(); }, 5000);
Move the window.close() to the onafterprint event?
https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onafterprint
Related
We recently discovered that Chrome no longer supports window.showModalDialog which is problematic because our enterprise application uses this method.
There is, apparently, a short term workaround that allows you to restore showModalDialog but it involves modifying the registry which is too complicated (and risky) four our average user. Therefore I'm not a big fan of this workaround.
The long term solution is obviously to remove all calls to this obsolete method and replace them with a convenient jQuery plugin (such as VistaPrint's Skinny Modal Dialog plugin, for example. Other suggestions are welcome by the way).
The typical scenario we use the modal dialog is to ask the user for Yes/No confirmation before executing an action that cannot be undone, ask the user to agree to terms and condition before proceeding, etc. Typically the onclick event on the "Yes" or "Ok" button in the modal dialog looks like this:
window.returnValue = true;
window.close();
Similarly, the "Cancel" or "No" button looks like this:
window.returnValue = false;
window.close();
The fact that we can return a value from the dialog is very convenient because it allows the "parent" window to be notified whether the user has clicked the "Ok" or the "Cancel" button like so:
var options = "center:1;status:1;menubar:0;toolbar:0;dialogWidth:875px;dialogHeight:650px";
var termsOfServiceAccepted = window.showModalDialog(myUrl, null, options);
if (termsOfServiceAccepted) {
... proceed ...
}
The last thing I'm going to mention about the showModalDialog is that it works great even when the document displayed in the dialog is from a different domain. It's very common for us to have our javascript running from http://the-client.com but the "Terms of Service" web page is from http://the-enterprise-vendor.com
I need a temporary solution that I can deploy ASAP while we work on the long term solution. Here are my criteria:
minimal code change in existing JavaScript
the pop up window must be able to return a value to the "parent". Typically this value is a Boolean but it could be any simple type (e.g.: string, int, etc.)
solution must work even if the URL of the content is from different domain
Here's what I have so far:
1) Add the following method in my JavaScript:
function OpenDialog(url, width, height, callback)
{
var win = window.open(url, "MyDialog", width, height, "menubar=0,toolbar=0");
var timer = setInterval(function ()
{
if (win.closed)
{
clearInterval(timer);
var returnValue = win.returnValue;
callback(returnValue);
}
}, 500);
}
As you can see in this method, I try to make the pop up window look as similar to a dialog as possible by hiding the menu and the toolbar, I setup a time every 500 milliseconds to check if the window has been closed by the user and if so, get the 'returnValue' and invoke a callback.
2) replace all calls to showModalDialog with the following:
OpenDialog(myUrl, 875, 650, function (termsOfServiceAccepted)
{
if (termsOfServiceAccepted)
{
... proceed ....
}
});
The fourth parameter to the method is the callback where I check if the user has clicked the "Ok" button before allowing her to proceed.
I know it's a long question but basically it boils down to:
What do you think of the solution I propose?
In particular, do you think I'll be able to get a returnValue from a window that was opened with window.open?
Any other alternative you can suggest?
I have two ideas that could help you but the first one is tied to CORS, so you won't be able to use it from different domains at least you can access both services and configure them.
FIRST IDEA:
The first one is related to this native api. You could create on the parent window a global function like this:
window.callback = function (result) {
//Code
}
As you can see it receives a result argument which can hold the boolean value you need. The you could open the popup using the same old window.open(url) function. The popup's onlick event handler could look like this:
function() {
//Do whatever you want.
window.opener.callback(true); //or false
}
SECOND IDEA: Solves the problem
The other idea I got is to use this other native api to trigger an event on the parent window when the popup resolves (better known as cross-document messaging). So you could do this from the parent window:
window.onmessage = function (e) {
if (e.data) {
//Code for true
} else {
//Code for false
}
};
By this way you are listening to any posted message on this window, and checking if the data attached to the message is true (the user clicks ok in the popup) or false (the user clicks cancel in the popup).
In the popup you should post a message to the parent window attaching a true or a false value when corresponds:
window.opener.postMessage(true, '*'); //or false
I think that this solution perfectly fits your needs.
EDIT
I have wrote that the second solution was also tied to CORS but digging deeper
I realized that cross-document messaging isn't tied to CORS
I open a new window like this:
var newWindow = window.open('myPage.aspx', null, 'height=650,width=900,status=yes,toolbar=no,scrollbars=yes,menubar=no,location=no,top=0, left=0');
And I wait for it to close:
var windowTimer = window.setInterval(function () {
if (win.closed !== false) {
//If window is closed ...
window.clearInterval(windowTimer);
}
}, 100);
This does work in Chrome and IE9 and Edge but not in Firefox, why?
Firefox does get inside the function but it never gets on win.closed if, even if there is an else it neither goes into it... is there any alternative to this?
Solution that worked for me:
On the popup window:
//Fires an event on the window that opened it
window.onbeforeunload = function () {
window.opener.myEvent();
};
On the main window:
window.myEvent= function () {
//This fires only when the popup gets closed on beforeunload
}
Note: the event to fire in the main window must be declared as public so it can be accessible, like so window.myEvent= function ()
Another reference: cross-window javascript events
Basically, I think the simplest way to do this is the following:
function hasClosed(){
document.getElementById('open').textContent = 'window has been closed';
}
window.addEventListener('beforeunload', function(){
if(window.opener) window.opener.hasClosed();
});
document.getElementById('open').addEventListener('click', function(e){
e.preventDefault();
window.open('test.html');
});
open window
Please keep in mind that SO snippets are not allowed to open windows, so the code is not functional inside the snippet. Simply copy the code and save it as a file called test.html.
You do not need to keep checking, the child will simply call the function on the parent. This has the advantage that you are not using resources to keep checking for it. Also, be aware that when navigating in this window, onbeforeunload gets called if a new page is loaded, calling the parent function, but maybe you could just do the check you were already doing in the hasClosed function.
You might want to give an uuid to your window and pass it into it so it can inform you of it's identity on closing, but that's all refinement.
We recently discovered that Chrome no longer supports window.showModalDialog which is problematic because our enterprise application uses this method.
There is, apparently, a short term workaround that allows you to restore showModalDialog but it involves modifying the registry which is too complicated (and risky) four our average user. Therefore I'm not a big fan of this workaround.
The long term solution is obviously to remove all calls to this obsolete method and replace them with a convenient jQuery plugin (such as VistaPrint's Skinny Modal Dialog plugin, for example. Other suggestions are welcome by the way).
The typical scenario we use the modal dialog is to ask the user for Yes/No confirmation before executing an action that cannot be undone, ask the user to agree to terms and condition before proceeding, etc. Typically the onclick event on the "Yes" or "Ok" button in the modal dialog looks like this:
window.returnValue = true;
window.close();
Similarly, the "Cancel" or "No" button looks like this:
window.returnValue = false;
window.close();
The fact that we can return a value from the dialog is very convenient because it allows the "parent" window to be notified whether the user has clicked the "Ok" or the "Cancel" button like so:
var options = "center:1;status:1;menubar:0;toolbar:0;dialogWidth:875px;dialogHeight:650px";
var termsOfServiceAccepted = window.showModalDialog(myUrl, null, options);
if (termsOfServiceAccepted) {
... proceed ...
}
The last thing I'm going to mention about the showModalDialog is that it works great even when the document displayed in the dialog is from a different domain. It's very common for us to have our javascript running from http://the-client.com but the "Terms of Service" web page is from http://the-enterprise-vendor.com
I need a temporary solution that I can deploy ASAP while we work on the long term solution. Here are my criteria:
minimal code change in existing JavaScript
the pop up window must be able to return a value to the "parent". Typically this value is a Boolean but it could be any simple type (e.g.: string, int, etc.)
solution must work even if the URL of the content is from different domain
Here's what I have so far:
1) Add the following method in my JavaScript:
function OpenDialog(url, width, height, callback)
{
var win = window.open(url, "MyDialog", width, height, "menubar=0,toolbar=0");
var timer = setInterval(function ()
{
if (win.closed)
{
clearInterval(timer);
var returnValue = win.returnValue;
callback(returnValue);
}
}, 500);
}
As you can see in this method, I try to make the pop up window look as similar to a dialog as possible by hiding the menu and the toolbar, I setup a time every 500 milliseconds to check if the window has been closed by the user and if so, get the 'returnValue' and invoke a callback.
2) replace all calls to showModalDialog with the following:
OpenDialog(myUrl, 875, 650, function (termsOfServiceAccepted)
{
if (termsOfServiceAccepted)
{
... proceed ....
}
});
The fourth parameter to the method is the callback where I check if the user has clicked the "Ok" button before allowing her to proceed.
I know it's a long question but basically it boils down to:
What do you think of the solution I propose?
In particular, do you think I'll be able to get a returnValue from a window that was opened with window.open?
Any other alternative you can suggest?
I have two ideas that could help you but the first one is tied to CORS, so you won't be able to use it from different domains at least you can access both services and configure them.
FIRST IDEA:
The first one is related to this native api. You could create on the parent window a global function like this:
window.callback = function (result) {
//Code
}
As you can see it receives a result argument which can hold the boolean value you need. The you could open the popup using the same old window.open(url) function. The popup's onlick event handler could look like this:
function() {
//Do whatever you want.
window.opener.callback(true); //or false
}
SECOND IDEA: Solves the problem
The other idea I got is to use this other native api to trigger an event on the parent window when the popup resolves (better known as cross-document messaging). So you could do this from the parent window:
window.onmessage = function (e) {
if (e.data) {
//Code for true
} else {
//Code for false
}
};
By this way you are listening to any posted message on this window, and checking if the data attached to the message is true (the user clicks ok in the popup) or false (the user clicks cancel in the popup).
In the popup you should post a message to the parent window attaching a true or a false value when corresponds:
window.opener.postMessage(true, '*'); //or false
I think that this solution perfectly fits your needs.
EDIT
I have wrote that the second solution was also tied to CORS but digging deeper
I realized that cross-document messaging isn't tied to CORS
Ok, I feel I have done my due diligence here... JSFIddle - http://jsfiddle.net/taytayevanson/8BpHw/5/
I am trying to create a page that will pop multiple tabs. I understand that using this code...
New Tab
will pop 1 new tab. However, as explained in this stackoverflow q/a, it needs to be a "user initiated event" for Chrome to pop a new tab and not a window. Because of this requirement, a loop will pop 1 new tab and then new windows for each following link.
jQuery("a.site").each(function(){
var string = jQuery(this).attr("href") + "/" + jQuery("#arguments").val();
jQuery(this).attr("href",string);
jQuery(this).trigger('click');
});
I have tried programmatically creating links and clicking them, with different plugins, timeouts, methods, and I even tried "daisy-chaining" the process and firing it on a page load (a huge PHP/GET variable/page load trigger thing) but it would still pop windows because the event was not user initiated.
I tried this...
function clickLink(link) {
var cancelled = false;
if (document.createEvent) {
var event = document.createEvent("MouseEvents");
event.initMouseEvent("click", true, true, window,
0, 0, 0, 0, 0,
false, false, false, false,
0, null);
cancelled = !link.dispatchEvent(event);
}
else if (link.fireEvent) {
cancelled = !link.fireEvent("onclick");
}
if (!cancelled) {
window.location = link.href;
}
}
and although I can read it, I don't understand it well enough to comprehend what i'm supposed to pass into this function. I tried something like this...
jQuery("a.site").each(function(){
var string = jQuery(this).attr("href") + "/" + jQuery("#launcher").val();
jQuery(this).attr("href",string);
clickLink(jQuery(this));
});
But I get a "object has no method 'dispatchEvent'" console error. I tried using that same "var event" and just calling...
link.trigger(event);
but there was a console error there as well. The only thing I have not tried is in this Q/A (using jQuery.get() to open a tab and write to it) but seeing as it still calls window.open(), I feel like i'll still run into the exact same loop issue.
Ok. Got all that out of the way... Is there a real answer for this besides "it's controlled by your browser" ? I feel like there must be a way. Thank you, sorry for the novel :)
See using dispatchEvent to open new tab: {tested on chrome}
DEMO
$('a.site').each(function () {
var clk = document.createEvent("MouseEvents");
clk.initMouseEvent("click", false, true, window, 0, 0, 0, 0, 0, true, false, false, true, 0, null);
this.dispatchEvent(clk);
});
I wouldn't rely on using a triggered click to open a link, not all browsers will support it the same as if user clicks on it ( for obvious security reasons)
Would just loop through the elements and and grab the href, manipulate it the way you want, and pass result to window.open(url).
I have a website that opens a new window. I am trying to trigger onclose event on the child window (if the user closed the window the parent window will alert it).
I found a stackoverflow question regarding that problem at: How to run function of parent window when child window closes?
But, the answer also preforms action on the child window which I think I can't do because the child window opens a website not in my control (I can't edit its html).
I was thinking of using the following to trigger the on close event
var inFormOrLink;
$('a').live('click', function() { inFormOrLink = true; });
$('form').bind('submit', function() { inFormOrLink = true; });
$(window).bind("beforeunload", function() {
return inFormOrLink;
})
How do I apply this on the new tab/window?
This is not possible to do solely on the client-side.
In order to do this, you'll need to do the following:
Upon opening a tab, send an ajax call to a script that doesn't stop loading until it receives a second ajax call, this is usually done with a script that waits for an sql value to exist before outputting.
Upon closing the tab, send the second ajax call to that script so that it replies to the original ajax call.
Viola.
I'm not aware of a simpler way to do this.
Original window:
function waitForTabClose(windowID) {
$.post('waitfortabclose.php',{windowID:windowID},function(data) {
if (data == 1) {
// Do tab closed stuff
} else {
waitForTabClose(windowID);
}
});
}
waitfortabclose.php
$i=1;
$wID = $_POST['windowID'];
do {
if (file_get_contents($wID) == $wID) {
echo 1;exit;
}
set_time_limit(30);
sleep(5);
} while($i++ < 50);
echo 0;
New Tab
window.onclose = function() {
$.post('windowclosed.php',{windowID:windowID);
};
windowclosed.php
$wID = $_POST['windowID'];
file_put_contents($wID,$wID);
This is pseudocode, and hasn't been tested. The functionality can be written in a lot of ways, this is just how I'd do it.
Found a solution to what i were looking for. it was much easier then the above answer plus its actually works and what i were looking for.
var win = open('http://www.google.com');
if (win.closed) {
alert('Window closed! Hoorah!');
}
Thanks very much for whoever tried helping.