By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
434,600 Members | 1,108 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,600 IT Pros & Developers. It's quick & easy.

FireFox (version 2) Ajax call to update page times out if child window is closed

Frinavale
Expert Mod 5K+
P: 9,731
I have 2 FireFox (version 2) browser windows opened.

One is the child of the other.

When the user is finished with the child window, a method in the parent window is called to refresh a section of the page.

This is the JavaScript code that I'm using to refresh the content in the parent page:
Expand|Select|Wrap|Line Numbers
  1. <script type="text/javascript">           
  2.             function UpdateList() {
  3.                 showUpdatingMessage();
  4.                 document.getElementById('myHiddenFieldForStuff').value = true;
  5.                 __doPostBack('myASPButtonClientID', '');
  6. }
  7.  </script>
Please note that the __doPostBack() method is supplied by ASP.NET. This method submits the page to the server and indicates that the control that caused this to happen was a button with the ClientID of "myASPButtonClientID". This method determines whether or not the whole page should be updated or if an asynchronous call to the server should take place. Since the button with the clientID of "myASPButtonClientID" is within an ASP.NET UpdatePanel, the __doPostBack() method preforms an asynchronous call to the server and only a portion of the page is updated.

This is the JavaScript code in the child page that is used to call the UpdateList JavaScript method in the parent page:
Expand|Select|Wrap|Line Numbers
  1.   <script type="text/javascript">
  2.             window.onbeforeunload = CloseEvent;
  3.  
  4.             function CloseEvent() {
  5.                 if (window.opener && !window.opener.closed) {
  6.                     window.opener.UpdateList();
  7.                 }
  8.             }
  9.             function CloseBrowserWindow() {
  10.                 //window.close();
  11.                 CloseEvent();
  12.             }
  13.         </script>
The "CloseBrowserWindow" method is called when a Button is clicked. It's supposed to close the window, which triggers the window.onbeforeunload event to fire, which calls the method in the parent window.

Right now the JavaScript responsible for closing the browser window is commented-out. The reason is because in FireFox version 2, when the child window is closed, the postback to the server times out.

When the child window remains opened, the request does not time out and everything works as it should (as it does in FireFox 3).

I'm not sure why this is happening (in FireFox version 2..) It'd be nice to know the reason but I'm not expecting JavaScript experts to know the mysteries of FireFox (version 2)

As a work around, I was thinking that if I were able to close the child window from the parent window the problem could be averted.

The only thing is, I have no idea how to do this.

I'd really appreciate any insight on this topic.

Thanks,

-Frinny
Mar 12 '09 #1

✓ answered by Frinavale

I was able to fix it...the following doesn't look like much of a change from the original but I tried a whole bunch of things to get to this stage.

The only difference is that instead of calling the function in the setTimeout method, I pass it the function name instead:
Expand|Select|Wrap|Line Numbers
  1. window.onbeforeunload = function() {
  2.   if (window.opener && !window.opener.closed) {
  3.     var win = window.opener;
  4.     window.opener.setTimeout( win.UpdateList, 100);
  5.   }
  6. }
  7. function CloseBrowserWindow() {
  8.   window.close();
  9. }
There is some interesting things I discovered about the setTimeout method!

For instance, the first parameter to the setTimeout method should be a String...but the string can contain a call to method.

For example, the following code will display an alert after 2 seconds:
Expand|Select|Wrap|Line Numbers
  1. <html>
  2. <head>
  3.   <script type="text/javascript">
  4.     function timedMsg()
  5.     {
  6.       var t=setTimeout("alert('2 second delayed Hello World!')",2000);
  7.     }
  8.   </script>
  9. </head>
  10.  
  11. <body>
  12.   <form>
  13.     <input type="button" value="Click Me!" onClick = "timedMsg()">
  14.   </form>
  15. </body>
  16.  
  17. </html>
Note that the first parameter is a String that contains a method call to the alert function. Of course you can do the same thing providing your own function instead of an alert:
Expand|Select|Wrap|Line Numbers
  1. <html>
  2. <head>
  3.   <script type="text/javascript">
  4.     function timedMsg()
  5.     {
  6.       var t=setTimeout("delayedHelloWorld()",2000);
  7.     }
  8.     function delayedHelloWorld()
  9.     {
  10.       alert('2 second delayed Hello World!')
  11.     }
  12.   </script>
  13. </head>
  14.  
  15. <body>
  16.   <form>
  17.     <input type="button" value="Click Me!" onClick = "timedMsg()">
  18.   </form>
  19. </body>
  20.  
  21. </html>
The only thing is that you can't easily pass variables as parameters to your method that is in a String as the first parameter of the setTimeout function. You can do it but it looks a bit nasty:
Expand|Select|Wrap|Line Numbers
  1. <html>
  2. <head>
  3.   <script type="text/javascript">
  4.     function timedMsg()
  5.     {
  6.       var message = "2 second delayed Hello World!";
  7.       var firstParameter="delayedHelloWorld('" + message +"')";
  8.       var t=setTimeout(firstParameter,2000);
  9.     }
  10.     function delayedHelloWorld(message)
  11.     {
  12.       alert(message);
  13.     }
  14.   </script>
  15. </head>
  16.  
  17. <body>
  18.   <form>
  19.     <input type="button" value="Click Me!" onClick = "timedMsg()">
  20.   </form>
  21. </body>
  22.  
  23. </html>

Anyways, after much playing around I finally figured it out. Providing a function name (I'm assuming this is like C++ and is actually the memory location of the function??) ended up solving my problem:

Expand|Select|Wrap|Line Numbers
  1. <html>
  2. <head>
  3.   <script type="text/javascript">
  4.     function timedMsg()
  5.     {
  6.       var t=setTimeout(delayedHelloWorld,2000);
  7.     }
  8.     function delayedHelloWorld()
  9.     {
  10.       alert('2 second delayed Hello World!')
  11.     }
  12.   </script>
  13. </head>
  14.  
  15. <body>
  16.   <form>
  17.     <input type="button" value="Click Me!" onClick = "timedMsg()">
  18.   </form>
  19. </body>
  20.  
  21. </html>
  22.  

Share this Question
Share on Google+
29 Replies


gits
Expert Mod 5K+
P: 5,325
could you try to trigger the close event after the request is completed? i guess that the problem is that by closing the browser-window the reference to the current request object is dropped ... you could even try a timeout for the close-operation which should even avoid that behaviour ... i say i guess it because i don't know the exact reason but anytime we have that problem both of the solutions fix it ...

may be i'll investigate it a bit and could give a better answer ;)

kind regards
Mar 12 '09 #2

Frinavale
Expert Mod 5K+
P: 9,731
@gits
I'm not following? I don't understand what you're getting at here.....

@gits
I have no idea how long the update's going to take. It's a very complicate page with many things that need updating. So, it's not a very quick process...and when you combine that with a little bit of lag, how can you tell how long it's going to take?

[edit]
Oh wait, do you mean put put a timeout in the parent window to allow the close-operation in the child window to take place before raising the post back to the server?
[/edit]
Mar 12 '09 #3

gits
Expert Mod 5K+
P: 5,325
is UpdateList() an Ajax-operation? then you could just call to close the window in the callback of the request.

in case you want to use the timeout then you just need a short one ... as i said ... it fixes such issues and i guess again :) that the timeout just avoids the reference dropping and let the browser instantiate and bind the requestobj correctly
Mar 12 '09 #4

gits
Expert Mod 5K+
P: 5,325
regarding your edit ... i thought that something like this:

Expand|Select|Wrap|Line Numbers
  1. function CloseBrowserWindow() {
  2.     CloseEvent();
  3.     window.setTimeout(function() { 
  4.         window.close(); 
  5.     }, 100);
  6. }
should help.

kind regards
Mar 12 '09 #5

Frinavale
Expert Mod 5K+
P: 9,731
So, you don't close the child window from the parent window then?
Mar 12 '09 #6

gits
Expert Mod 5K+
P: 5,325
as far as i'm aware of this behaviour that doesn't matter ... it is a problem of closing a window 'the same time' when starting a request ... so it could be circumvented by using a timeout ... that is just the experience i made ..
Mar 12 '09 #7

Frinavale
Expert Mod 5K+
P: 9,731
I added the suggested code and it did not solve the problem.
I'm still getting a time out message in the parent window if the client window is closed even though there is a timeout set.
Mar 12 '09 #8

Frinavale
Expert Mod 5K+
P: 9,731
@gits
This behaviour seems to be linked to my earlier question...
Mar 12 '09 #9

gits
Expert Mod 5K+
P: 5,325
is it an Ajax-Request that does the update?
Mar 12 '09 #10

Frinavale
Expert Mod 5K+
P: 9,731
>>>quite response: yes..................<<<

Let's just say that I have no control over the Ajax request....

Well, I do but Please don't make me do it!
It's torture!
Mar 12 '09 #11

gits
Expert Mod 5K+
P: 5,325
ahh ... and please drop the onbeforeonload when using the timeout-solution ... does it work then? because this will start the request again ...
Mar 12 '09 #12

Frinavale
Expert Mod 5K+
P: 9,731
But then it won't be called when the user clicks the browser's "X" button.
Mar 12 '09 #13

gits
Expert Mod 5K+
P: 5,325
of course ... because that will close the window immediatly ... and we have the same problem again - does it work with the 'normal' button then?
Mar 12 '09 #14

Frinavale
Expert Mod 5K+
P: 9,731
Testing...give me a sec (well few minutes as it times out)
Mar 12 '09 #15

Frinavale
Expert Mod 5K+
P: 9,731
The timeout solution does not work.
Mar 12 '09 #16

gits
Expert Mod 5K+
P: 5,325
hmmm ... strange ... with our own-framework it always works reliably ... anyway: we could try another (but a bit ugly) solution ;) ... when you open the window then start an interval that observes whether the window is open or already closed ... as soon as it sees that the window is closed then you could start the update-call ... and from the child window you just set the needed params in the parent in case you need to ... so everything request-related is handled by the parent ... even when it is an ugly 'poll'-solution ... or you could try another timout-solution ... like this:

Expand|Select|Wrap|Line Numbers
  1. function CloseEvent() {
  2.     if (window.opener && !window.opener.closed) {
  3.         window.opener.setTimeout(function() {
  4.             window.opener.UpdateList();
  5.         }, 100);
  6.     }
  7. }
may be this timeout helps? ... i hate such trial&error ... but may be i'm not aware enough of the ms-ajax-framework ...
Mar 12 '09 #17

Frinavale
Expert Mod 5K+
P: 9,731
The following works:
Expand|Select|Wrap|Line Numbers
  1.            function CloseEvent() {
  2.                 if (window.opener && !window.opener.closed) {
  3.                     window.opener.setTimeout(function() {
  4.                       window.opener.UpdateList();
  5.                   }, 100);
  6.                 }
  7.             }
  8.             function CloseBrowserWindow() {
  9.                 CloseEvent();
  10.                 window.setTimeout(function() {
  11.                     window.close();
  12.                 }, 100);
  13.             }
Mar 12 '09 #18

Frinavale
Expert Mod 5K+
P: 9,731
Thanks again for your help Gits.

Now off to try and solve the tons of JS related issues in IE8.
Mar 12 '09 #19

Frinavale
Expert Mod 5K+
P: 9,731
Ok, now I'm really confused.

Check out the following code:
Expand|Select|Wrap|Line Numbers
  1.   window.onbeforeunload = CloseEvent;
  2.             function CloseEvent() {
  3.                 if (window.opener && !window.opener.closed) {
  4.                     window.opener.setTimeout(function() {
  5.                       window.opener.UpdateList();
  6.                   }, 100);
  7.                 }
  8.             }
  9.             function CloseBrowserWindow() {
  10.                 //CloseEvent();
  11.                 //window.setTimeout(function() {
  12.                     window.close();
  13.                 //}, 100);
  14.             }
The UpdateList method is called when I close the browser using the "X" button.
But when I use the "exit" button, it doesn't work....the UpdateList method is never even called.
Why? Really! Why?
Mar 12 '09 #20

gits
Expert Mod 5K+
P: 5,325
we need to use a closure here ... because the window is already closed then, and the window.opener reference is wrong ... try the following:

Expand|Select|Wrap|Line Numbers
  1. window.onbeforeunload = function() {
  2.     var win = window.opener;
  3.  
  4.     window.opener.setTimeout(function() {
  5.         win.UpdateList();
  6.     }, 100);
  7. }
kind regards
Mar 12 '09 #21

Frinavale
Expert Mod 5K+
P: 9,731
I have a bunch of questions....

When you're talking about a "closure" are you talking about an "inline" function.
For example:
Expand|Select|Wrap|Line Numbers
  1. //this would be a closure
  2. window.onload = function(){/*do something*/}
  3.  
  4. //this would not be a closure
  5. window.onload = myFunction;
  6.  
  7. function myFunction(){/*do something*/}
Is there a difference between the two?



How can the window be closed in the CloseEvent function here?
It's called during the onbeforeunload event....before the document's unloaded...
Expand|Select|Wrap|Line Numbers
  1.          window.onbeforeunload = CloseEvent;
  2.             function CloseEvent() {
  3.                 if (window.opener && !window.opener.closed) {
  4.                     window.opener.setTimeout(function() {
  5.                       window.opener.UpdateList();
  6.                   }, 100);
  7.                 }
  8.             }
  9.             function CloseBrowserWindow() {
  10.                 //CloseEvent();
  11.                 //window.setTimeout(function() {
  12.                     window.close();
  13.                 //}, 100);
  14.             }}

How it is this different from what you're suggesting (see comments)?
Expand|Select|Wrap|Line Numbers
  1. window.onbeforeunload = function() {
  2. //here you're making a reference to the window.opener
  3.     var win = window.opener;
  4.  
  5. //here you are directly referencing the window to opener.
  6.     window.opener.setTimeout(function() {
  7.  
  8. //Here you are not directly referencing the window.opener....
  9. //you're using a "copy" (??) of the window.opener?
  10. //Does this make a difference?
  11.         win.UpdateList();
  12.     }, 100);
  13. }

Thanks for clarifying things.

-Frinny
Mar 13 '09 #22

Dormilich
Expert Mod 5K+
P: 8,639
@Frinavale
neither of those are a closure (at least how I understand it). a closure is a function defined inside another function, which preserves its parameters/variables (not so sure about the last one), hence the name.
Expand|Select|Wrap|Line Numbers
  1. function myFunction()
  2. {
  3.     var x = "some value";
  4.  
  5.     // this is the closure
  6.     var mf = function(x)
  7.     {
  8.          // do some cool stuff with parameter x
  9.     }
  10.  
  11.     // use the closure
  12.     element.onclick = mf;
  13. }
Mar 13 '09 #23

gits
Expert Mod 5K+
P: 5,325
that is right ... and window.opener refers to the window's opener ... when we store the reference first and then closure it then the garbage-collector doesn't drop the reference because it finds a variable that is referencing it. so window.close() closes the window and when we use the timeout the onbeforeunload would have triggered a function that refers to window.opener some time later where the window was closed already ... and so JavaScript would try to refer to the parent's opener ... but that wouldn't work. so we just make use of the closure-construct and store the reference in a variable ... it is a similar problem with the this keyword that is often used in ajax-callbacks.

what you have written above is just showing a anonymous function and a named function ... but every function could be used for closuring variables ...

kind regards
Mar 13 '09 #24

Frinavale
Expert Mod 5K+
P: 9,731
Ok :)
Things are making much more sense now.

Thanks for taking the time to explain it to me.

The following works:
Expand|Select|Wrap|Line Numbers
  1. window.onbeforeunload = function() {
  2.   var win = window.opener;
  3.   window.opener.setTimeout(
  4.     function() {
  5.        win.UpdateList();
  6.      }, 
  7.     100);
  8. }
  9. function CloseBrowserWindow() {
  10.   window.close();
  11. }
Mar 13 '09 #25

Frinavale
Expert Mod 5K+
P: 9,731
I lied..this solution does not work in IE7.
If I don't use the window.opener.setTimeout(), then it works fine...but of course if I remove the window.opener.setTimeout portion it won't work in FF...
Mar 13 '09 #26

Frinavale
Expert Mod 5K+
P: 9,731
I was able to fix it...the following doesn't look like much of a change from the original but I tried a whole bunch of things to get to this stage.

The only difference is that instead of calling the function in the setTimeout method, I pass it the function name instead:
Expand|Select|Wrap|Line Numbers
  1. window.onbeforeunload = function() {
  2.   if (window.opener && !window.opener.closed) {
  3.     var win = window.opener;
  4.     window.opener.setTimeout( win.UpdateList, 100);
  5.   }
  6. }
  7. function CloseBrowserWindow() {
  8.   window.close();
  9. }
There is some interesting things I discovered about the setTimeout method!

For instance, the first parameter to the setTimeout method should be a String...but the string can contain a call to method.

For example, the following code will display an alert after 2 seconds:
Expand|Select|Wrap|Line Numbers
  1. <html>
  2. <head>
  3.   <script type="text/javascript">
  4.     function timedMsg()
  5.     {
  6.       var t=setTimeout("alert('2 second delayed Hello World!')",2000);
  7.     }
  8.   </script>
  9. </head>
  10.  
  11. <body>
  12.   <form>
  13.     <input type="button" value="Click Me!" onClick = "timedMsg()">
  14.   </form>
  15. </body>
  16.  
  17. </html>
Note that the first parameter is a String that contains a method call to the alert function. Of course you can do the same thing providing your own function instead of an alert:
Expand|Select|Wrap|Line Numbers
  1. <html>
  2. <head>
  3.   <script type="text/javascript">
  4.     function timedMsg()
  5.     {
  6.       var t=setTimeout("delayedHelloWorld()",2000);
  7.     }
  8.     function delayedHelloWorld()
  9.     {
  10.       alert('2 second delayed Hello World!')
  11.     }
  12.   </script>
  13. </head>
  14.  
  15. <body>
  16.   <form>
  17.     <input type="button" value="Click Me!" onClick = "timedMsg()">
  18.   </form>
  19. </body>
  20.  
  21. </html>
The only thing is that you can't easily pass variables as parameters to your method that is in a String as the first parameter of the setTimeout function. You can do it but it looks a bit nasty:
Expand|Select|Wrap|Line Numbers
  1. <html>
  2. <head>
  3.   <script type="text/javascript">
  4.     function timedMsg()
  5.     {
  6.       var message = "2 second delayed Hello World!";
  7.       var firstParameter="delayedHelloWorld('" + message +"')";
  8.       var t=setTimeout(firstParameter,2000);
  9.     }
  10.     function delayedHelloWorld(message)
  11.     {
  12.       alert(message);
  13.     }
  14.   </script>
  15. </head>
  16.  
  17. <body>
  18.   <form>
  19.     <input type="button" value="Click Me!" onClick = "timedMsg()">
  20.   </form>
  21. </body>
  22.  
  23. </html>

Anyways, after much playing around I finally figured it out. Providing a function name (I'm assuming this is like C++ and is actually the memory location of the function??) ended up solving my problem:

Expand|Select|Wrap|Line Numbers
  1. <html>
  2. <head>
  3.   <script type="text/javascript">
  4.     function timedMsg()
  5.     {
  6.       var t=setTimeout(delayedHelloWorld,2000);
  7.     }
  8.     function delayedHelloWorld()
  9.     {
  10.       alert('2 second delayed Hello World!')
  11.     }
  12.   </script>
  13. </head>
  14.  
  15. <body>
  16.   <form>
  17.     <input type="button" value="Click Me!" onClick = "timedMsg()">
  18.   </form>
  19. </body>
  20.  
  21. </html>
  22.  
Mar 13 '09 #27

gits
Expert Mod 5K+
P: 5,325
ahhh ... please don't ever use that syntax with strings ... it is just ugly and needs eval to be executed ... the function-reference way is always to prefer ;)
Mar 13 '09 #28

Frinavale
Expert Mod 5K+
P: 9,731
@gits
It is absolutely disgusting and I probably will never use it again. I was working my way through w3c and this is how they tell you to do things. I decided to give it a chance and was surprised to see it worked....it didn't really help me much, so I started trying to pass the function reference instead....hoping it was like c++ in this regard.

@gits
Is eval automatically called in this case?


@gits
So it is passing a memory location then.
Mar 13 '09 #29

gits
Expert Mod 5K+
P: 5,325
puhhh ... personally i don't like w3schools ;) ... and yes ... internaly this style requires to eval the passed string ... there is never a need to use it except one thing: when you need to eval a ajax-json-response ...

kind regards
Mar 13 '09 #30

Post your reply

Sign in to post your reply or Sign up for a free account.