Pop-under example - OmegaJunior Net

2007-07-31,
2007-09-24
A.E.Veltstra

This example shows how to make a pop-under (or modal dialog) appear, cross-browser. The fact that you can read this, indicates one of two possible situations: either your browser does not have javascript activated, or you dismissed the dialog. Show it again. In the same script, a function is defined that will take specific hyperlinks in an article to convert them to pop-unders as well.

The pop-under is built in javascript, but its contents is placed in an Object element (or in some cases, in an iFrame element). That means the contents can be managed completely independently. The reason that the entire thing is made in javascript is that this way, we don't need any other change in our regular web pages... no extra CSS, no extra DIVs, no nothing apart from the javascript link.

A couple of browser incompatibilities were conquered in making this example:

  1. Browsers like Opera, K-Meleon, Firefox and Mozilla allow setting element styles as a simple attribute using this construct:
    element.setAttribute("style","background-color: white; color: black; font-family: Charcoal, sans-serif;");
    Internet Explorers 6 and 7 do not allow setting the style as a simple attribute like that. Instead they require us to treat Style as an object. None of the tested browsers mind the following rule though (and they shouldn't, since it's part of the DOM 2 Style recommendation), which is why we used it in this example:
    element["style"]["cssText"]="background-color: white; color: black; font-family: Charcoal, sans-serif;";
  2. Browsers that try to comply to the W3 recommendations, like Opera and K-Meleon (and probably Firefox and Mozilla too), know and accept the value "fixed" for style attribute "position". Not so for Internet Explorer 6. Version 7 has no problem with it... but when applied it throws off the automatic calculation of the width and height of child elements, requiring them to be fixed or absolute. Thus, using MSIE Conditional Comments, we assign Internet Explorer the value "absolute", and Safari, Opera, Firefox and other decent browsers get the value "fixed". Absolute positioning however requires us to focus the dialog when using long pages like this one. This is done with the javascript function "focus()".
  3. Most browsers allow the Object element as the holder for external sources, including text/html. Only Internet Explorer fails at this. One method that shows how it can be done, has the problem that it cannot load sources from other domains. To overcome this problem, Internet Explorer will use an iFrame element to load the external source.
  4. Internet Explorer 7 has a big problem in calculating the height of iFrame and Object elements. Setting height to 100% almost never has the desired effect: as high as its parent node, especially when its parent is positioned fixed. We work around that by using an absolute positioning on the element... but this triggers a bug in both Internet Explorer 7 and Firefox 3 when loading an anchor inside an external source (i.e. page.html#anchor), causing the element to grow bigger than its parent node, overlapping other elements in the same node and ignoring their z-index settings. We got around that by moving the title and dismiss button out of that node and into its parent (the overlay). This required a change in positioning of those elements, which still needs testing in MSIE 6.
  5. Most browsers require setting the "class" attribute using the setAttribute() method. Internet Explorer does not. It requires setting the attribute "className". Luckily none of the browsers mind us setting both, so we do that, because it prevents having to sniff for browser vendor. Now we know we don't really need a "class" attribute in this specific sample, but we can imagine you wanting to use some overriding stylesheet, using class names to select the elements.
  6. Browsers like Opera and K-Meleon (and probably Firefox and Mozilla too) allow adding event listeners using the addEventListener() method. Not so in Internet Explorer. It requires us to use its proprietary method attachEvent(). For this reason we test for addEventListener first, and use it if present. Then we test for attachEvent, and use that if present. Finally, if neither are present, we use the following construct, which should work in non-DOM browsers:
    element["on"+eventname]=functionname;
  7. Some W3 recommendation-compliant browsers allow setting a style attribute named "opacity". This is part of the Css3 specification, which no browser has to support yet. Internet Explorer is one browser that refuses to support this attribute. Instead, we have to use its own proprietary attribute: "filter". The other browsers will ignore unsupported attributes, though they may log it in their warning log. So instead of saddling up compliant browsers with proprietary attributes for a non-compliant browser, we chose to get rid of opacity and substitute a repeated transparant background image.
  8. The same pop-under script contains a function defined to loop through all hyperlinks and turn some of them into pop-unders. This loop can take this form in most browsers, but not in Safari 3 Beta for Windows:
    for(var x in c){c[x].addEventListener(...)}
    Instead, specifically for Safari, we had to revert to counting code, like this:
    for(var i=0;i<c.length;i++){c[i].addEventListener(...)}
  9. Some browsers have no clue about the DOM. For those, we added a regression method that opens the pop-under contents in a pop-up window. Obviously the browser still needs to have javascript activated. No javascript, no play. Thus the hyperlinks that would show up in the pop-unders now pop up in their own new window instead (or tab, depending on browser settings)... just like they would do without the script.
  10. Turning normal hyperlinks into pop-unders requires their normal behaviour suppressed. Where under "normal" circumstances this would work using "return false", the unobstrusive javascript methods we employ here refuse to work the same way (except for in Microsoft Internet Explorer). Using standard event cancellations like preventDefault(), stopPropagation(), cancelBubble=true and returnValue=false, refused to work in all tested browsers. This resulted in both the pop-under and the link itself to be followed. To stop this, we had to change the properties of the hyperlink while turning it into a pop-under: we had to set their href attributes to #, and their target attributes to empty. Strangely enough, this leads to Safari 3 Beta showing the pop-unders without their contents... currently we assume this a bug and are looking forward to finding a solution. (It seems this bug goes away if we alert the url of the external source before showing it...)
  11. Safari 3 Beta for Windows interprets the CSS system colours (like ButtonFace, AppWorkspace, ActiveCaption) incorrectly. Both ActiveCaption and CaptionText for instance are rendered black instead of the actual Windows colour settings. This results in an apparant omission of the pop-under title. It's there, but Safari users won't see it. ButtonFace is ignored entirely. Instead, Safari uses its own greyish button colour. What if the ButtonText colour is similarly grey? Yay, Safari usability.

This example was tested on the following browsers on the Windows XP Home, Windows XP Pro, and Windows 2003 Server operating systems:

This example was tested on the following browsers on the MacOS X operating systems:

Valid XHTML 1.0 Transitional We take pride in providing validated (x)html, as this makes other developers' jobs a lot easier.