I am popping up an HTML page from a Silverlight application using the HtmlPage.PopupWindow() method. I am trying to handle the event of when the popup window is closed from within Silverlight. This is how I am attempting to do this:
var window = HtmlPage.PopupWindow(new Uri("http://mypopup..."), "popup", options);
EventHandler<HtmlEventArgs> windowClosed = (sender, e) =>
{
// would like to refresh the page when popup is closed...
HtmlPage.Document.Submit();
};
window.AttachEvent("onUnload", windowClosed);
However the event handler never seems to get called. Is this something that is possible or am I missing something?
The Silverlight app and the HTML popup page are on the same domain, however they are actually on different ports. I was thinking that maybe the pages being on different ports would be considered a cross-site restriction and cause the JavaScript to fail.
You have a very very small bug in event name :)
change "onUnload" by "onunload" and try again
You are correct, the variation in port number is enough to prevent Silverlight from accessing events and content of the popup window.
Your onUnload event must be defined in the popup window rather than the parent/opener window to detect any actions made on the child window. In the popup you would track actions in that window and send a call to the parent/opener for status updates. With this call you would also pass any values that you need to that window as you can't read the data of the child window from the parent/opener.
If the page is an iframe of the target page, then you would use parent; as in parent.functionname(data);. If the page is a separate window of the target page you would use opener; as in opener.functionname(data);.
Related
I have a web application that runs in Chrome with Same-Origin Policy disabled (i.e., --disable-web-security). I use window.open() to create a new window that loads a URI that sometimes redirects. If no redirect occurs, I can read the contents of the document hosted inside the window using the document property when the onload event fires. Unfortunately, in cases where a redirect does occur, it seems that onload never fires, and the window object returned from window.open() is no longer useful.
Here's the code, to give you an idea of what's going on:
var win = window.open('http://somewhere');
win.onload = function() {
doStuffWith(win.document.body);
win.close();
};
Is there any way that I can hold on to a valid window handle even when a redirect occurs immediately after the new window is opened?
Per #CBroe's suggestion I extended my code to see if I can get at the contents of the window if I wait a little while. After the code above, I appended:
setTimeout(function() {
console.log(win.location);
doStuffWith(win.document.body);
}, 5000);
The location is reported as swappedout:// (huh!?) and the document's body is empty.
The problem is that if the relocation is not exactly after lets say an on click event pop-up blocker provided by most browsers blocks the request, on success of some function you want, open a modal with a button and have the relocate on click of the new button. Its the only way. Not great but it will do the trick.
This also applies to the on load.
I need to spawn a tab using window.open('...', '_blank');
Then, I need that tab to CLOSE ITSELF, when the user click a button (button is in the new tab).
I have control over the codebase and server of both applications.
I tried the following:
in app#1:
window.tab = window.open('http://localhost:5007', '_blank');
in app#2:
function clickedButton() {
window.opener.tab.close();
}
Unfortunately I get security exception:
Error: Blocked a frame with origin "http://localhost:5007" from accessing a cross-origin frame.
How can I get around this error? Is there anyway I can use this library to overcome this? https://github.com/ternarylabs/porthole
I am simply going to quote documentation here, just for anyone who needs a reference click W3C and MDN.
function openWin() {
myWindow = window.open("", "myWindow", "width=200, height=100"); // Opens a new window
}
function closeWin() {
myWindow.close(); // Closes the new window
}
To break it down, the open and close functions use parameters than can be very useful, such as the URL, when desiring to open or close the current window, or in your case the opened window.
A practical example would be this stack overflow question. N
I hope it helps!
EDIT
To answer the OP's edit to the question: If it is a matter of triggering an event on a window which was opened, you can on the new window have an event handler which will trigger window.close() like so:
$('#anElementId').click(function() { window.opener.$('body').trigger('theCloseEvent', anyPassedData); })
However, if you truly do have control over the new tab, because it leads to a URL whose code base you are in control of, then it is only a matter of triggering an event there that you can trigger either once the window loads, or once you click a button... like so:
HTML
<button id="close-window">Close me</button>
Javascript/jQuery:
$(document).ready(function(){
$("#close-window").click(function(){
alert("ok");
window.close();
});
});
EDIT #2
To further extend the OP's edit, I want to include here an issue that can easily be encountered when attempting to trigger the opened window to close itself.
Quoted from How can I close a browser window without receiving the “Do you want to close this window” prompt?:
Scripts are not allowed to close a window that a user opened. This is considered a security risk. Though it isn't in any standard, all browser vendors follow this (Mozilla docs). If this happens in some browsers, it's a security bug that (ideally) gets patched very quickly.
None of the hacks in the answers on this question work any longer, and if someone would come up with another dirty hack, eventually it will stop working as well.
I suggest you don't waste energy fighting this and embrace the method that the browser so helpfully gives you — ask the user before you seemingly crash their page.
In other words, unless your webpage's script has control of the window which was opened, you should/cannot close said window. That is because the script running the window.close is not in control of the opened window.
EDIT #3
So many edits I know! But I am answering this in between my daily routine so bear with me. To answer the porthole.js question, it should be much more possible to do something with it, however you need to realize that you are working with iframes.
There is a significant difference when working with websites vs working with iframes, in which iframes are Widgets and websites (including mini sites) are given a URL. There are lots of considerations as well in terms of security and sandboxing, as can be seen on the portholejs demo here. This difference is also what does not allow you to work with different websites the way you want to initially.
My advise would be to evaluate your options with respect to your implementation: website to website vs website to widget.
Good luck!
Ok, I was able to accomplish this in the way I theorized by using porthole.js.
I believe this is the only cross-browser way to accomplish this without using hacks.
The solution consists of 2 apps (you must add code to both app for this to work).
app #1: http://localhost:4000
app #2: http://localhost:5000
In my case, I needed app#1 to spawn a need tab containing app#2. Then I needed app#2 to be able to CLOSE ITSELF upon clicking a button inside app#2.
If these apps were on the same domain (including same port), this would be relatively easy by saving a reference to the tab in app#1:
window.tab = window.open('...', '_blank');
And then accessing that reference from within app#2 via window.opener.tab.close()
However, for my case the apps needed to be on diff domains and doing this method resulted in a browser security exception. So instead, what I needed to do was host app#2 within an iframe inside app#1 (on some specific route, say /iframe), this way they ARE on the same domain as far as the browser windows are concerned, and now the second tab should be able to close itself using window.opener.tab.close().
However, a problem still remained because I needed the trigger to be a button INSIDE app#2 (aka a button inside the iframe), and since the hosting app and the iframe app are again not on the same domain, it seems like I would be back to square one... or maybe not.
In this case, porthole.js saves the day. You must load porthole.js into both apps (this is why you need access to both codebases). Here's the code:
in app#1 (http://localhost:4000/iframe)
// create a proxy window to send to and receive messages from the iFrame
var windowProxy;
window.onload = function() {
windowProxy = new Porthole.WindowProxy(
'http://localhost:5000', 'embedded-iframe');
windowProxy.addEventListener(function(event) {
//handle click event from iframe and close the tab
if(event == 'event:close-window') {
window.opener && window.opener.tab && window.opener.tab.close();
}
});
}
in app#2: (http://localhost:5000)
var windowProxy;
window.onload = function() {
windowProxy = new Porthole.WindowProxy(
'http://localhost:4000/#/iframe');
$('button').on('click', function() {
windowProxy.post('event:close-window');
});
}
And wa-lah, a self closing tab.
I have a parent opening a new window, and trying to detect when the child window has loaded. In Chrome, I've tried
open('http://www.google.com').onload = function() { alert(location.href); };
but that doesn't seem to work.
Why doesn't the above method work? Are there alternatives?
If you want to be absolutely certain that a page has loaded, you can use messaging.
If you are able to use HTML5, there is a new feature called web-messaging.
This works very well on cross domain sources.
If HTML5 is not an option, use JS instead. I used a simple jQuery plugin called: windowmsg. It has worked excellently for me. I'm really not sure about this working on a cross site environment, but I think it should.
Beware of the security issues that these kind of solutions offer.
The method as it is should work(and works for me), but not when opening a window with a document from a different domain.
For security-reasons the new window will not dispatch the load-event to a document from another domain.
Technically speaking the child window and parent window are two different instances of the browser. We call them as child window and parent window. They do not have access to each other.So its not possible to perform any action in one window on the click of HTML elements in second window.
So, I suggest that you should not open a new window if you need access. You can use fancybox or lightbox that is effectively a part of the same window and that, you have control.
I'm building an app that involves authentication via third-party. To make the process not redirect the actual app I open a new window that then does the authentication and returns to main window after success.
This doesn't, however, go as well as planned. When the popup redirects to third-party and back, window.opener gets null. It's still possible to close the popup by window.close() but I also need to refresh the logged-in-area in the main window, like this:
window.opener.check_auth_status();
I really hope there is a way to fix this, e.g. binding a function to popup-close in the main window? Refreshing the whole page would be highly unnecessary.
One way is to set an interval to main window checking if the popup is closed, but this seems so fiddly.
You have a few options that may or may not work in the latest versions of the browsers due to security updates
1) check that the window is closed from the opener - not fiddly and actually the safest
2) give the opener a name
window.name="myMainWindow";
and in popup (script from SAME domain) - should normally not open a new window or change content
var handle = window.open("","myMainWindow");
handle.check_auth_status();
3) use an iFrame in the popup and when you want to access the opener, use top.opener
I have a page located at x.com. On this page is a button that, when clicked, will launch a new window (using javascript's window.open() method) to a page that is located at z.com. The popup does a few things, then redirects the original window (the opener, x.com) to a different page based on some parameters defined in the popup.
This works fine in Firefox/Chrome, but not in IE. In IE (8 specifically, but I believe 7 also has this problem) the original window (the opener) is not redirected. Instead, a new window comes up and THAT window is redirected.
I've tried many different methods to try and get this to work, including changing the popup to an iframe loaded on the page and having a function on the opener that the popup/iframe call. The problem seems to be that IE refuses to allow cross-domain sites to talk to each other via javascript.
Is there a way around this? How can I get the parent window to redirect to a page based on parameters in a popup or iframe?
EDIT:
Here is some code for samples:
In a page on domainA.com, I have this:
<img src='/images/test.png' onclick="window.open('http://www.domainB.com/item.aspx', 'name', 'width=100,height=100,menubar=no,status=no,toolbar=no');" />
In item.aspx on domainB.com I have this in the javascript:
opener.location.href = 'http://www.somethingelse.com/';
In Firefox/Chrome, this works fine. In IE, when domainB.com tries to set location.href on opener (aka the parent window, which is domainA.com), it instead opens a new window, which is not what I want. I want it to redirect the opener (parent window) to the URL I specified.
Bara
Hi I solved my problem by doing the following
instead of using window.opener.location = "....
Use window.opener.document.location = "url". This worked for me.
Another thing is make sure that you are not redirecting from http into https this will also cause it to break.
Cheers
I ended up resolving it by doing the following:
I added an iFrame to my main page. The iFrame is in the same domain as my popup. The iFrame contains a button that, when clicked, will launch the popup.
The popup does it's thing, then changes the iFrame's hash tag to something like #change (so the url would be www.whatever.com/iframe.aspx#change). In the iFrame's javascript, I have a loop going that checks the hash to see if it says "change" and if so, it will redirect the parent page to wherever I want. This works beautifully.
Because I did not want the infinite loop on every single page, I do a browser check so that this only applies to IE. For all other browsers I just use window.opener which works fine.
Bara