Поделиться через


More: Avoiding Popup Windows in Your Web Apps

Scott Isaacs shares some additional "best practices" points on dealing with popup windows and popup blockers:

Always program window.open() very defensively...

Always try catch any calls to window.open() and if you are retaining a reference to the window (e.g., var w = window.open(…)), always make sure the “w” is a valid object (and again try catch your first attempt to leverage the window). 

Last, it was recently discovered that Symantec’s internet products have a popup blocker that actually augments the web page with their own custom script. This script disables any calls to window.open() that may occur before the onload event of the page. Therefore, if the user quickly clicks a hyperlink that calls window.open before the page loads, the user will see either nothing happen or receive a script error. 

I heartily agree.  The variable assigned the return value of window.open() ("w" above) is particularly obnoxious.  It can fail to be initialized if the window.open() failed or took an unexpected detour due to popup blockers.  Once the popup window is up and running, the "w" variable will again be at risk when the user closes the popup window.  The "w" variable will be unusable after the window it refers to is closed - it's almost as though the object it refers to has been garbage collected out from under the variable.  Any reference to the variable will raise an exception.  Testing for typeof w == "undefined" isn't entirely reliable across browsers because for the brief period while the window is closing "w" may be unusable but not undefined.

For the Windows Live Contacts web control we ultimately solved these quasi state problems with the popup window variable once and for all by eliminating the variable!  Instead of having the main page hold onto a variable pointing to the popup window so that the main window code could check the state of what's going on in the popup, we turned everything inside out so that the popup calls or writes back to the main window.  This arrangement allows the main window to create the popup, set a state variable to indicate that the popup is up, and then forget about it.  When the popup is closed, it will call back to the main page to clear the state variable and set the result of the operation.

Another thing to watch out for when you have multiple windows in your web app:  Firefox 1.x does not do well with executing script while a window is closing.  If the popup window is in the process of closing and calls into a JavaScript method on the main page which fires off a new XMLHttpRequest, chances are high that the XMLHttpRequest will implode in its onReadyStateChanged event.  Accessing any field or method of the XMLHttpRequest object will throw an exception, and all subsequent XMLHttpRequests (even new instances) will be fried.  The only way to clear this state appears to be to reload the main page.  I don't recall offhand if this has been fixed already in Firefox 2.0, but it's a known, logged issue in Firefox 1.x

The best solution is to avoid the problem by not initiating an XMLHttpRequest in a call chain started by a window close event.  Use a short timer to decouple the closing popup window's call context from the desired XMLHttpRequest action.

Comments