how to keep javascript window.open variable reference - javascript

I have a requirement that I need to create a link to open a form in a new window and then when I click the same link it will focus on the existing window again.
this works well with the following code
<input type="button" value="Click" onclick = "return OpenWindow();"/>
<script>
var win = null;
function OpenWindow()
{
if (win == null || win.closed)
{
win = window.open('http://localhost/Conditions.aspx', 'Condition');
}
win.focus();
return false;
}
</script>
However, I experienced a problem, when I switch to different page and come back to the page which has the link. the variable win will not retain the previous reference.
If I click the link again, it will refresh the existing window (which is not what I want!) and then focus on it.
Is there any way that I can keep variable reference? or does anyone know how to solve this problem?

I had the same issue and was resolved on Window.open only if the window is not open
If you basically want the window focused instead of refreshed when the link is clicked, even if the parent window has been closed, re-opened, or changed, this will do the trick.
I was about to resort to using cookies.

Chia, your problem is that JS doesn't persist across pages.
HTML is stateless, so the JS that sits on top also needs to "forget" what it did on page-1, after you move on to page-2 and page-3.
There are ways of storing strings and numbers, and retrieving them on other pages, but that's not what you're looking for.
And to that end, there's nothing you can really do, with your current setup.
There are different ways of allowing you to keep the child reference (do main-page navigation inside of an iFrame in the main page... if you really, really have to... or AJAX in the page changes, for people with capable browsers, and use old-fashioned navigation for browsers with worse JS engines).
But it's not going to be possible for you to open window2, click on a link which points window1 at page3, and still have page3 have a reference to window2.

Related

Is it possible to put focus on frame after trigger to open frame is invoked a second time (Firefox)?

I am having an issue in firefox. My research so far is telling me that there is not really a reliable way to deal with my problem, but I am wanting to ask just in case.
I have the following javascript/jquery to open a new window triggered by pressing a button on my page:
alipayTransactionModalTrigger.click(function() {
NIWindow=window.open("<!--ALIPAY_CONF_REDIRECT_URL-->", "NI payment");
alipayTransactionModal.dialog("open");
});
In Chrome and Firefox, this opens a new frame, and the frame gets focus. This is fine. However, if a user leaves this new frame open, and comes back to my original page. They are able to hit the button to trigger this event again. If this occurs, the new frame reloads as it should, but in Firefox the new frame does NOT pull focus this on this refresh. I am not sure why it would pull focus on the initial new frame load, but not pull focus if the frame is refreshed with the same event trigger. I haven't had the courage yet to check this in IE...
Is this one of those things that you cannot reliably control? Or is there a way to do this? Note, I have tried using NIWindow.focus() after the initial window open line of code above. No luck.
I believe I read something about possibly using alerts, but I was not sure how to implement the described solution, and I read that it was a bit of a hacky solution.
I could just always open a new window "_blank", and that would assure focus, but the newly opened frame url uses parameters that are based on the parent window. I have no access to that code, so there is no way for me to add checks to make sure data matches up, until I get a response back from this redirect
Give each new window a new name. Do you have a reason for reusing the "NI payment" name?.
If your code has dependencies on this window name you should consider passing the window reference (NIWindow) directly instead of the name. Injecting/passing your dependencies instead of relying on a magic super global is a better approach in general.

In Javascript, how to reuse a window previously opened by another page

I have a window which uses javascript to open another child window, in the standard window.open("http://foobar","name") manner. If I open again with the same name, it reuses the window. This is great and exactly what I want.
However, if the original window is closed, I would like to be able to reopen it and have its window.open go to the previously opened child window. Unfortunately, because it is a new parent window it will open another child window (which it will happily and correctly reuse).
Does anybody here know of a way to get hold of that previous child window so I can avoid making more windows than necessary?
Behind the scenes, the driver of this question is this: I have a java program which will periodically open different websites and I do not want to force a plethora of tabs or windows. Command-line options do not let you reuse windows or declare targets; javascript lets you declare a target. I figured I would write a small javascript page which opened a page in a specifically-named window and then close itself. Anytime you want to see a new page, hit that page passing in your new page.... Much to my dismay, though, targets seem specific to the window which creates them.
So if you have ideas which are relevant to my actual problem I'm interested too.
Embedding a browser took less time than trying various ways of controlling browsers.

Handle IE window close event in javascript

I need to handle when Internet Explorer (6, 8 and 9) window is closed, in order to ask his confirmation on it. I tried the unbeforeunload, but, as you might know, it's triggered also when any link is clicked, o a form is submited. Some can say to use event mouse coordinates, but there are several ways to break such a validation (Alt+F4 for ex.). There's also a way to set some variable to true when clicking links and check if in the event, but that does not work neither, as I got lots of various links on my pages, and the event is triggered multiple times in some cases.
Also I tried to solve the problem using frames, like: make 2 frames, put my pages to one frame, and to the other (with zero size) put a page with onbeforeunload handler. That would work just fine, but we work with a set of environment js, that we can't prevent to download, and those scripts remove any frames on the page, putting the entire page in the main window - fail…
Can anybody, please, suggest anything else?
If you are going to use onbeforeunload (and it sounds right), you should have a flag that is set so that the event only bothers asking if there is a reason to stay on the page.
var hasChanges = false;
window.onbeforeunload = function() {
if (hasChanges) {
return "You have changes that will be lost if you continue leaving the page";
};
};
Then you just have to set the variable to true (hasChanges = true) if there is a reason to stay on the page...so if nothing has changed, clicking your other links will not trigger the dialog.

Why does Firefox lose focus on page reload?

I have two instances of Firefox running simultaneously next to each other. One window is in the front and the other one in the background. Both instances use the same target URL.
Whenever I do a page reload in one of my instance the other instance loses the focus and gets minimized to the Windows taskbar.
Has anyone ever experienced this effect?
I've found the problem. Some buggy jQuery code returned a window reference rather than a DOM Element. The call to $(element).blur() ( element is a window reference ) now explains the strange behaviour.
Could be a buggy 'onunload' handler. If both windows are open to the same page, then doing a reload in one will trigger onunload, which eventually calls window.blur(). If both windows are child windows of the same parent page (ie: created via window.open(), or regular link with target="somename"), they could be assigned the same name.
I don't know what FF"s priorities are on conflicting window names in JavaScript, but you could try opening the two windows in various orders, and reloading one or the other and see which one minimizes (if at all).

JavaScript close window when opener is closed in IE

For my web application I need to close the child window whenever the parent window is closed. By "closed" I mean that the browser window is actually closed, not just navigated to a new page.
I have seen the "How can I close the child window if the parent window is closed?" question already, but mine is an extension on that. The answer to that question solves the problem of closing the child window on any unload event of the parent. However unload != close (IMO); just clicking on a link triggers the unload event.
Since there isn't an "onclose" event in JS, I decided that the best method is on the parent's unload event setTimeout on the child to see if it's parent still exists and close if not:
var w = window.open("", "Logger", "height=480,width=640,resizeable,scrollbars=yes");
if (w) {
JSEvents.on(window,'unload',function(){
if (w && !w.closed) {
w.setTimeout(function(){
//IE this==w.opener
if (!w.opener || w.opener.closed) {
w.close();
}
},500);
}
});
}
However, I believe that I have pretty conclusively shown that in IE(7) you cannot use setTimeout during the unload event on either the parent or child window. In the above example this == w.opener inside of the setTimeout anonymous function. This test never produces an alert:
JSEvents.on(window, 'unload', function(){
window.setTimeout(function(){alert('HERE');},500);
});
A straight alert without the setTimeout will produce the alert.
Is there a trick to setting a setTimeout on the child from the parent that I can use?
Is there another method for detecting when the parent is closed that I can use?
It is much easier to do in FF, so I am focusing on getting this to work under IE.
Is there a trick to setting a setTimeout on the child from the parent that I can use?
You can't do it with code from the parent in IE. When IE closes a window, the members you defined from code inside it are gone, and references to those members (such as the child's timeout pointing to your function) are left dangling. Depending on what version of IE you've got, maybe nothing will happen, or maybe you'll get a “can't execute code from a freed script” error.
You can do it inside the child. The parent could set a flag on the child onunload (eg. w.parentUnloaded= true) which a setInterval poller on the child could check for, and close itself —
if (window.parentUnloaded && (!window.opener || window.opener.closed))
Is this an IE bug? Well... other browsers react differently to unloaded scripts, certainly. But there is no standard that says what is supposed to happen here. Even within the same browser series, behaviours change as browsers are updated to avoid cross-context scripting issues.
With stuff like this and event timing issues(*), cross-window scripting is much more difficult to get right than it looks. It's generally best avoided; if you can put your ‘pop-ups’ in divs in the main page, it is usually better to do that.
(*: there are cases(**) where an event can be fired in one window and execute whilst JavaScript in another window is still in the process of running. So window ‘a’ could call a method on window ‘b’ and have that execute whilst other code in window ‘b’ is still in progress. This can dramatically confuse the scripts in window ‘b’, if they are written under the normal JavaScript assumption that there is only one thread of execution active at once. This is why I suggest using the poller in the child rather than having the parent explicitly call the child. In the future we will use HTML5's postMessage method to avoid these problems.)
(**: You could very well argue that this should never happen, and it certainly is weird, but it does happen in many browsers, in particular when modal dialogues are involved or some versions of the IE Sun Java plugin are in use.)
You can't just leave pop-up windows lying around after the application is closed; it's just not polite.
Some would say the impoliteness was opening the pop-ups in the first place. ;-)
It would seem to me that it would make sense to close any child windows when the parent is left, regardless of whether the user was closing the window, or just navigating back to his home page, or a bookmark, or typing an address, or something. Personally I'd probably want to lose the child windows on a refresh too, if I'm trying to ‘reset’ the application to a beginning state.
If you have multiple documents the parent is going to be navigating between which are all part of the same application and should not close the children, you're making things really hard for yourself! :-) However you could adapt the above ‘child window if’ approach to try to sniff the opener.location and see if that's within your application to decide whether to close or not. The trick is if the opener had been navigated to a different domain, the access would throw a security exception, so you'd have to wrap the location access up in a try...catch block that also closed the windows if the opener location was unreadable.
bucabay wrote (and Anthony something similar):
The browser considers the window closed once you refresh or close the window. So as far as the child is concerned, it's opener is gone once you refresh the parent.
That's very sensible and logical. Browsers probably should have one ‘window’ per document like that. But try it — they don't. A child pop-up retains access to its opener (and, as long as that opener is a document in the same security context, the contents of the opener), over a refresh of the opener, in IE/FF/Op/Saf/Chr.
In pop up window: (this works if the opener is closed OR changes domains)
var int = window.setInterval(function(){
// On opener domain change, all browsers throw an error. Lets use that error to our advantage using try/catch:
try
{
if(opener && typeof opener.document != 'undefined')
{
// Adding this variable fixes IE8. Why? Because F U thats why.
var openerRef = window.opener.location.host;
}
else{
// Loads the survey when opener is closed
window.location = 'exit-survey.jsp';
}
}
// Loads the survey if an error throws (error throws when opener changes domain)
catch(err)
{
window.location = 'exit-survey.jsp';
}
}, 500);
})
Have you tried creating the function inside the opened window like this:
window.closeWithParent = function() {
if (!window.opener || window.opener.closed) {
window.close();
}
};
window.parentClosing = function() {
window.setTimeout(window.closeWithParent, 500);
};
Then from your parent window:
JSEvents.on(window,'unload', function() {
if (w.parentClosing) w.parentClosing();
});
I'm not sure, but I think that interfacing with the window object across windows might be causing the problem you are seeing. Also, this way the setTimeout is called in the child windows scope (hopefully) instead of your parent window, which is being unloaded (this losing any timeouts).
The problem is from the browsers perspective a window is a concept which is created to display the content of a document. When you navigate from that document to another that window is closed and a new one is created.
The fact that the browsers conceptual windows are hosted by an actual client window owned by the browser and that client window may be re-used to display subsequent documents isn't actually any of your business (if you don't mind the phrase).
Its how the browser chooses to display the content, that window having a close button that may be potentially clicked by the user is outside of what most browsers consider that any host document needs to know.
Hence any trick you might invent to circumvent this now, if it works at all, may be closed by tighter security in later versions of a browser.
My advice would be to drop this requirement.
The browser considers the window closed once you refresh or close the window. So as far as the child is concerned, it's opener is gone once you refresh the parent.
So you cannot test if a window just refreshed, or opened another instance on that same domain using JavaScript references. (such as window.opener)
You can however create indirect references to other windows and save them in any browser storage that is cross window, or even server storage. Having the storage reflect the state of the window will allow other windows to observe that window even though they do not have a reference.
You could use cookies, or DOM Storage etc. I have a library that uses cookies (it was written a year ago when DOM storage was not supported - FF2+, IE8+ I think). If you want to see it as an example, I can do that.
Anyway, what you can do is keep a piece of data that represents the parent window. Keep it updated at regular intervals, and poll it from the child.
Example with cookies:
// parent
setInterval(function() { setCookie('parent_alive', new Date()) }, 1000);
// child
setInterval(function() { if (readCookie('parent_alive') < new Date()-5000) window.close() }, 1000)
Here the child will close 5 seconds after the parent does not update the cookie "parent_alive". The main problem is that internet connection may prevent a page from loading for 5 seconds, by which the child thinks it was closed. So it is a balancing act.
Note the polling is quite efficient if you use session cookies since they stay in memory. However, if you use persistent cookies you will probably be hitting the disk which would suck.
It seems that the correct way to add a script into the child window's scope is to use the DOM to create the script tag. The following code works to check if the parent window is open still a quarter second after it unloads in IE.
var w = window.open("", "Logger", "height=480,width=640,resizeable,scrollbars=yes");
if (w) {
JSEvents.on(window,'unload',function(){
if (w && !w.closed) {
var srpt = w.document.createElement('script');
srpt.type = 'text/javascript';
srpt.text = 'window.setTimeout(function(){if(!window.opener||window.opener.closed){window.close();}},250);';
w.document.body.appendChild(srpt);
}
});
}
Thanks for everyone's help in pointing me in this direction. The solution was just figuring out how to dynamically insert a new script tag with text content instead of a src.

Categories