The Perfect Pop-up (Updated 20 March 2007)

This is an update of the article that was originally posted in November 2002]. This update demonstrates methods that use unobtrusive JavaScript and CSS to trigger the pop-up, and all references to inline event handlers have been removed.

Posted on: 20 March 2007.

If you believe the likes of Jakob Neilsen and his supporters, nothing is more evil than pop-up windows. And in many ways, this is correct. Why? Well, we'll list the reasons soon enough, but in a nutshell it's because they are nearly always poorly implemented or simply not needed. This tutorial will show that, with the right thought, pop-up windows can be used without upsetting anyone - particularly the person browsing your site.

Problems with pop-ups

The common faults with pop-up windows are:

  • If scripting is disabled, or if the browser does not support JavaScript, the pop-up will not work
  • Search engines cannot follow links to pop-up windows (scripted elements are ignored)
  • Pop-ups present accessibility problems
  • Site management tools (e.g. DreamWeaver) cannot update links to pop-ups if you move the destination page to another section of your site
  • Many people have pop-up killers running that close the window the moment they are opened
  • In many browsers, the default option is now to stop pop-ups opening in the first place

Phew. That's quite a list ... and you could probably add your own to this list. So, how do we address these?

Start with a Basic Link

The first thing to do is to assume that your pop-up will not work. With so many possible reasons for this, you would be unwise to think anything else. So, just use the right markup for the job - you need to link to something, so just create a link:

<a href="file.htm">Here is my link</a>

But you want the people who can use pop-ups to get that effect right? So how do you identify that this link is going to generate a pop-up window for those who can get it? You have a few choices, but I'm going to suggest that you use the rel attribute. You could simply use a class attribute and attach the JavaScript behaviours to that, but I'm going to suggest that you use the rel attribute and within that you can stack up a number of alternative attributes that will affect the way the link appears/behaves. In effect, you'll use the class attribute as a hook from which we can hang the visual style (CSS) and rel for the behaviour (JavaScript). Here's a very basic example of the markup required:

<a href="file.htm" rel="popup">Here is my link</a>

Seeking out the Pop-ups

So you've got a simple link, given it a rel of popup - now it's time for the JavaScript to kick in and add in the behaviour. As is the way of doing things these days, we'll be using some nice unobtrusive JavaScript to achieve this - that's to say no inline event handlers (e.g. a onclick="foo()") and so on but instead it all goes into an external .js file. For this to work, we'll also require an addevent function (addevent.js).

The JavaScript starts working immediately after page load by calling a function that trawls through the page seeking out all a elements that have the rel attribute of popup:

addEvent(window, 'load', findPopUps, false);

In the findPopUps function, if the correct rel attribute is found, the script attaches a behaviour (which we'll see defined shortly) and also applies some background/padding effects to visually indicate that this is a pop-up; in addition, it automatically appends a title attribute to signify that it is a pop-up.

function findPopUps()
{
var popups = document.getElementsByTagName("a");
for (i=0;i<popups.length;i++)
 {
 if (popups[i].rel.indexOf("popup")!=-1)
  {
  // attach popup behaviour
  popups[i].onclick = doPopUp;
  // add popup indicator
  if (popups[i].rel.indexOf("noicon")==-1)
  //more of the 'no icon' thing in a moment ...
   {
   popups[i].style.backgroundImage = "url(pop-up.gif)";
   popups[i].style.backgroundPosition = "0 center";
   popups[i].style.backgroundRepeat = "no-repeat";
   popups[i].style.paddingLeft = "15px";
   }
  // add info to title attribute to alert fact that it's a pop-up window
  popups[i].title = popups[i].title + " [Opens in pop-up window]";
  }
 }
}

You may be wondering why the styles are applied using popups[i].style rather than applying a class - this is just to avoid overriding an existing class that may be present (you could adapt the script such that classes are strung together rather than replaced, however).

So we've found the pop-ups, given them a visual lick to make it clear that they are pop-ups and have attached the behaviour. But what is this behaviour?

Adding the Pop-up Behaviour

We just saw how the pop-up links are identified and then given a function to run when activated (by click or press):

popups[i].onclick = doPopUp;

So, what exactly does doPopUp do? Well, it let's you specifiy a few parameters about the pop-up window, for starters.

At its very basic level, all you need to do is state that the link is a popup by using rel="popup". However, in reality, you'll probably want to affect the appearance of it a bit more than that, for example setting the:

  • height
  • width
  • presence of toolbars

The usual kind of stuff. Thankfully, the script can accept such optional attributes:

rel="popup type width height noicon"

... but they must be in that order (and without any ommissions from the middle) . If none are specified, the script can use some defaults, which you could obviously set according to your audience.

[The noicon attribute is there to avoid some unsightly effects that may occur in certain circumstances. For example, while it might be good to have the pop-up indicator showing for links in the body of the page, should you need to add a pop-up link elsewhere, like a navigation bar for example, it may be a bit jarring; the noicon attribute lets you override the script's default behaviour for styling pop-up links.]

Here's the function in full:

function doPopUp(e)
{

//set defaults - if nothing in rel attrib, these will be used
var t = "standard";
var w = "780";
var h = "580";

//look for parameters
attribs = this.rel.split(" ");
if (attribs[1]!=null) {t = attribs[1];}
if (attribs[2]!=null) {w = attribs[2];}
if (attribs[3]!=null) {h = attribs[3];}

//call the popup script
popUpWin(this.href,t,w,h);

//cancel the default link action if pop-up activated
if (window.event)
 {
 window.event.returnValue = false;
 window.event.cancelBubble = true;
 }
else if (e)
 {
 e.stopPropagation();
 e.preventDefault();
 }
}

Note that there is one last thing going on here - this function calls one last function called popUpWin. This should be much more familiar territory, as it takes the values passed in to create the typical pop-up window.open method:

function popUpWin(url, type, strWidth, strHeight){

closeWin();
//calls function to close pop-up if already open,
//to ensure it's re-opened every time, retainining focus

type = type.toLowerCase();

if (type == "fullscreen"){
 strWidth = screen.availWidth;
 strHeight = screen.availHeight;
 }
var tools="";
if (type == "standard") tools = "resizable,toolbar=yes,location=yes,scrollbars=yes,menubar=yes,
  width="+strWidth+",height="+strHeight+",top=0,left=0";
if (type == "console" || type == "fullscreen") tools = "resizable,toolbar=no,
  location=no,scrollbars=no,width="+strWidth+",height="+strHeight+",left=0,top=0";
newWindow = window.open(url, 'newWin', tools);
newWindow.focus();
}

Some example pop-up links

So, stringing it altogether, here are some examples using the different parameters available in the rel attribute. You can see the visual effect of the pop-up image being added to these links (except for the one wher the noicon attribute has been applied)

Closing the pop-up

Once the pop-up is opened, we might rely on people to use the browser/operating sytem controls to close the newly opened window:

Window controls - minimise, maximise, close

But people don't always do this! So we should provide a link (or button, if you prefer) in the pop-up window itself to close it. However, let's assume that our user has scripting disabled, and that the page did not load in a new window. The 'close this window' link that you so thoughtfully provided will prompt a not very friendly dialogue like this:

Windows dialogue: reads 'Do you want to close this window? [yes] [no]'

Or at least it will for IE6 users - other browsers may have variations on this theme. To get around this problem, you should write the 'close' link to the web page using JavaScript, and check to see if the window was opened as part of a window.open() method. That way, if it is a true pop-up, the link appears and the close() method will work; if it is not a true pop-up window, the link does not appear. Try the link again, and see for yourself:

This is my pop-up (fixed mode)

The final perfect pop-up script

The complete scripts for this technique can be copied from the files linked to below (right-click and choose 'Save Link As', or whatever your browser of choice words it as):

You'll need to link to these files in the head of your document like so:

<script type="text/javascript" src="/path-to/add-event.js"></script>
<script type="text/javascript" src="/path-to/popup.js"></script>

The syntax for creating the links in your markup is as shown in the previous section. But we can do one better than that:

Conclusion

Hopefully this tutorial has demonstrated that pop-up links can be accessible, search-engine friendly and non-invasive. With browser support for these scripting techniques being so good, you should find the technique works well in almost every modern browser you try it on - and for those that don't carry out the script, you're still left with a basic link to follow, so nobody has to miss out. However, even if you follow all of this advice you should still ask yourself if you really need to open a new window.

Remember:you can use the Pop-up Window Generator, which uses the script detailed in this article.

Tutorial written by Ian Lloyd.