(Note: This page will attempt to use a javascript based in-window pop-up system to illustrate some of the points it makes. However, some assistive technologies (such as screen readers) and/or user style sheet settings may render the result unusable. This page is not dependent on that javascript system and it can be disabled by using this link to re-loading the page with the dynamic display aspects of the page disabled (assuming it is operating now).)
A barrage of undesirable and unwanted pop-up advertising windows has resulted in an increasingly widespread implementation of pop-up restricting mechanisms in web browsers and the introduction and use of external pop-up blocking software with browsers that do not offer the facility natively.
I have seen survey results suggesting a 1400% increase in the use of pop-up blocking from 2003 to 2004, and the diversity of pop-up blocking mechanisms makes handling their use extremely difficult. Detecting the operation of pop-up blockers difficult, they cannot reliably be defeated and users may not be willing to risk undergo another barrage of unwanted advertising just to use a web site that has been written to require pop-up windows.
The following are some of my thoughts on the subject of pop-up blockers, pop-up windows and the alternatives.
It is not uncommon for computer software GUIs to employ multiple windows, and/or sub windows. So it is not surprising that the authors of web applications should want to use multiple windows for their GUIs. Showing modal dialogs, data entry forms (or sub-forms), control panels, item specific help, showing images or source code listing. and the like.
It used to be relatively simple to open a new window on a web browser,
though few scripts in common use even considered the possibility that
the browser in use did not support the window.open function
(as is the case on some small, embedded browsers), nor, often, the
consequences of javascript being disabled or unavailable on the client.
This lead to new windows being employed in browser-based GUIs. They were
never really well suited to some of the task that they were put to;
browser windows are not good at being, for example, modal, and
communication between windows is complicated by browsers having differing
ideas about what constitutes an opener and the risk that the
user will close a significant intermediate window.
Browsers are better suited to a GUI that operates entirely within a single window, changing pages to operate a web application instead of windows. These are easier to design because they are largely sequential (though the user may elect to open a second+ window to the web site/application anyway) and they are reliable because they will not be subject to the influence of pop-up blocking.
However, there remain circumstances where some sort of pop-up window type GUI component would still be desirable. An example might be the thumbnail gallery of images, with no desire to re-load the gallery whenever a full-sized image was viewed. There are certainly other examples.
So the question is; what can be done, either about pop-up blocking or as an alternative to opening new windows?
There are broadly three types of pop-up blocking mechanism in use:-
window.open calls and TARGET attributes
in the HTML.The level of sophistication of pop-up blocking offered by web browsers varies from Internet Explorer, which offers no pop-up blocking facility (as of version 6), through crude on-off settings for the opening of new windows, to the sophistication of the latest versions of Mozilla and Opera, which are in a position to recognise a notion of " requested" pop-ups and offer the user highly configurable control of the facility.
Browsers make the best pop-up blockers; for the user because they are
in the best position to make an informed judgement about what is to be
allowed in the way of new windows (to recognise the notion of a
"requested" pop-up), and for the web author as they are usually
happy to give a clear indication that they have acted by returning either
a reference to null from the call to window.open, or
returning a genuine window object reference, but with its
closed property set to true.
Proxies sit between the browser and the Internet and may modify web
content as it passes through them. They use a number of techniques to
prevent pop-up windows. The crudest of which is to seek instances of
the character sequence "window.open" and replace it, but that
is easily subverted. Usually they act by inserting scripts into a web
page that initially replace the window.open function with
an alternative that will not open windows, or controls/modifies their
opening. Possibly replacing the function when the page has finished
loading, or installing additional test functions so that windows may
be opened under some circumstances (timing user clicks and only allowing
a window to be opened immediately following a user interaction (another
notion of "requested" pop-up).
These replacement window.open functions are usually not very skilfully
written and can be detected and subverted with work (and considerable
research). Their action is also difficult to detect because they attempt
to return objects from the calls to window.open that
resemble real window references; some even just return a reference
to the current window.
Most external pop-up blockers monitor the OS and detect attempts to open additional browser instances. Others are designed as add-ons for web browsers. Because they operate independently and asynchronously they are difficult to detect as they may act by closing a newly opened window after any script has finished successfully interacting with it.
External pop-up blockers often have a very literal notion of a "requested" pop-up. They, for example, allow the user to hold down the control key during an action that opens a new window so that the user can indicate that they do not want to window blocked. This requires that the user understand that the action will attempt to open a new browser window, or that the pop-up blocker gives some indication when it blockes a window (something like issuing a sound) so that the user can re-attempt the action with the control key pressed (this is only useful if the script is capable of coping with the consequences of the failure of its first attempt to open the window).
Requested pop-ups are either pop-ups directly resulting from user interactions with the browser, or literally requested by the user having to take some positive action to allow the pop-up. This makes them distinct from unrequested pop-ups, which are opened using inline code, the onload or onunload event handlers, from time outs or indirectly from some other code in response to conditions outside of user control. Unrequested pop-ups are used extensively to push unwanted advertising at users and are commonly regarded as unwelcome by users.
The most modern browsers with pop-up blocking built in are quite good at recognising when a window opening attempt is the direct result of user action, such as clinking on a link or button, but the older browser pop-up blocking implementations tended to block all pop-ups or none.
Content inserting proxies can facilitate a recognition of requested
pop-ups. If they are going to attempt to make the distinction between
window opening resulting from user actions and unrequested pop-ups
they need to insert quite large blocks of code and hope that this code
functions property. More commonly proxies just block inline attempts
to open windows as a page loads and attempts made during the onload
and onunload events. More simple proxy implementations just block
all new windows regardless of the user's action or the context of
the window.open call.
People often cite circumstances where the most advanced pop-up blocking techniques would regard a window opening attempt as requested and so allow it as circumstances under which it is acceptable to employ a new window. They are circumstances under which the influence of pop-up blocking mechanisms is reduced, but not all users are using one of the more capable browsers and the other blocking techniques are not nearly as good at recognising the distinction.
The action of many of the pop-up blocking mechanisms built into
(at least the more modern) browser is relatively easy to detect as
the return value from the call to window.open is
null instead of a reference to a window object.
Content inserting/re-writing proxies usually attempt to conceal their
operation from scripts and return either a dummy object instead of a
window reference, which may be detectable because of a lack of normal
window properties and method (thought a good dummy would require quite
a bit of testing as it may also dummy many of those properties and methods), or
they return a reference to the current window. The current window is a
window so it will have all of the features of a window object, but it will
also equal the new window reference if tested with == or ===.
External pop-up blockers are the ones that render the detection task
impossible (it is only potentially difficult with proxies) because they
act asynchronously. So a call to window.open should return
a reference to a window object and that reference could pass any tests
for null or expected window properties and methods, and so
seem to have been successfully opened, but then be closed by the pop-up
blocker after the completion of the tests.
That leaves a pop-up blocker detection strategy relying on attempting to
open a new window (after testing that the browser implements a
window.open function in the first palace) with the page
loaded into that new window reporting its arrival back to the window
that opened it. If it arrives successfully then it can reasonably be
assumed that it was not blocked. However, inferring that the failure of
page that should have been loaded into a pop-up to report its arrival is
the result of the window.open call being blocked is not
necessarily valid as there are many other factors influencing that
situation.
One problem is deciding how long to give it to open, A slow modem
connection, when the server and intervening network is heavily loaded,
might necessitate quite a long wait before it was safe to assume that
the page was not going to load. And when a page doesn't show up in the
allotted time span it is still not possible to tell whether it was
because of the actions of a pop-up blocker or whether the user closed
the window before it had time to load the page (Alt-F4 and
the like).
That timing issue moves the problem on to deciding how to react to evidence of a pop-up blocker preventing window opening. A sensible fall-back in the face of a failure to open a new window might be to navigate the current window to the requested URL. But a UI that waits for long enough to be certain that the attempt to open a new window has failed before it does anything will not feel responsive to the user.
Having detected the actions of a pp-up blocker (or at least inferred them from the lack of success in attempting to open a new window) it might be the desire of the web author to inform the user that they should disable their pop-up blocker in order to use the site. The user may not want to do that, so the site looses visitors as a result.
But it has been my observation, from various sorts of related error reports on Usenet, that users are often unaware that they are using a pop-up blocker, especially when it is part of a firewall or Internet security program (they see an offer to stop advertising and say yes without any comprehension of the consequences, assuming that the offending software doesn't just default to pop-up blocking), and if they don't know they are running one they are not going to know how to turn it off (or give any specific site permission to open new windows.
I imagine that all of the people who think that barraging their site visitors with unwanted pop-up advertising windows is a good idea are looking for a something that would reliably defeat pop-up blockers. Fortunately they are not going to find it. The pop-up blokers use such diverse techniques that no general approach will be found and the few pop-up blockers that could be subverted by specific actions on the part of page script authors would be trivial to update so that they became invulnerable, or replace with totally reliable alternatives.
Even if page authors started to actively try to defeat the less robust pop-up blocking techniques, that would just motivate the pop-up blocker authors to tighten up their code, and if that lead to an arms race the pop-up blocker running on the client computer would always be in a position to bring bigger guns to bear and so ultimately win. It is probably best to accept that the pop-up window is no longer a viable option in Internet scripting and consider what can be done as an alternative.
Completely avoiding the influence of pop-up blocking mechanisms can only be done by not attempting to open new windows. However, that does not mean that window like behaviour cannot be used in a browser bases UI. Much of what can be done with new windows can also be done with "In-window" pop-ups.
To create an in-window pop-up a section of the HTML (usually a
DIV element and its contents) is scripted to behave
like a window or dialog. Appearing as if it was a pop-up when
needed to allow interaction with its contents and dismissed upon
completion (or via the use of a "close" button).
The extent to which the DIV could reproduce window like behaviour is largely up to the script author, but for something acting like a modal dialog, positioning it in the middle of the viewport and providing a mechanism for dismissing it would probably be all that was required.
Additional possibilities include re-positioning by dragging, re-sizing by dragging a corner, scrolling the content vertically and/or horizontally if it overflowed a suitable area, and so on.
More complex systems may wish to handle multiple "windows", considering things like z-index stacking, handling the problems relating to form controls (which cannot be covered by a DIV element on all browsers).
Unfortunately, in-window pop-ups are not without some problems; accessibility is certainly one issue because screen readers may not be in a position to reasonably handle a section of an HTML page suddenly becoming visible in the middle of the window. But text browsers usually do not support javascript so window opening attempts using scripts always resulted in accessibility issues anyway.
However, because in-window pop-ups can be implemented as the manipulation of HTML content that appears in a web page some action can be taken to mitigate some accessibility issues.
Because this page attempts to extensively employ an in-window pop-up system it is also in a position to demonstrate how the content presented in those in-window pop-ups can be made available to the users of screen readers, text browsers and javascript disabled and or unsupporting browsers. This is because it is based on the manipulation of the underlying HTML and that gives the script a path of clean degradation to leave the otherwise manipulated content in its original context on the page.
This can be demonstrated for the users of javascript enabled and supporting browsers by using a link that would re-load the page, appending the query string value that the script detects as a signal that it is not to attempt to act.
When the in-window pop-ups are intended to display content then degrading to leave that content in the HTML makes sense. Links that would otherwise open in-window pop-ups can fall back to navigating within the page. This is also a viable fall back strategy for data entry forms, as a link with an appropriate fragment identifier will result in the browser scrolling to the form when the in-window pop-up cannot be used.
But for some actions, such as many modal dialog type interactions, it makes more sense for the content of the "window" to not be available in the HTML in its degraded form.
A DIV element scripted and positioned to act as a
pop-up window will not always cover all types of HTML page
content. IFRAMEs, applets and plug-ins, and
especially form controls will often show through DIVs.
Various strategies have been devised to handle various of these
conditions, using CSS to hide elements that would be overlaid
by a DIV, using IFRAMES to hold in-window
pop-up content or as a screening layer that will not allow other
page content to show through. Exactly which strategy is implemented
(if any) would depend on the context.
This page uses CSS and collision detection to hide the contents of the "windows" that display form controls. This is one of the factors that argues against the creation of truly generalised code, the additional code needed for this facility, or any of the alternative strategies, does not need to be downloaded unless the context of their use makes them necessary. A suitably modular script design should allow functionality to be omitted when it is not needed.
Magenta Icosahedron
/* Emulate getElementById on document.all only browsers. */ if((!document.getElementById) && document.all){ document.getElementById = function(id){ var tempEl = null, el = document.all[id]; if(el){ //document.all returned something. if((!el.id)||(el.id != id)){ /* Either this is a collection or the only element available under the property name provided as the - id - parameter is a named element: */ if(el.length){ //assume it is a collection. /* But it might be an element with a NAME corresponding with the id parameter that has collection-like behaviour such as a form or a select element so proceed with caution: */ for(var c = 0;c < el.length;c++){ if((el[c].id)&&(el[c].id == id)){ /* Set tempEl to the first match and break out of the - for - loop: */ tempEl = el[c]; break; } } /* el will be set to null if the loop did not find an element with the corresponding ID because the default null value of tempEl will not have changed: */ el = tempEl; }else{ //only a named element is available for id. /* getElementById should not return named elements only an IDed element so set el to null: */ el = null; } } //else we have our element (the ID matches). }else{ //el is undefined so make it null; el = null; } /* The returned value will be the first element confirmed as having the corresponding ID or it will be null: */ return el; }; }
Pop-up help would consist of a text explanation of some aspect of a web page/application interface that was too long to sensibly be made available as closely related text on a page.