Opening Popup Windows with no extra markup

This article was first published on (08-05-2005).

Popup windows are a hot topic among the web designers' community. People who are new to the trade struggle to customize them while seasoned web designers argue about their very use.

(It should be noted that these arguments are not limited to usability and accessibility, but often involve a choice of DTD Declarations.)

This article does not discuss what designers should do regarding popup windows, markup and such. It is just about adding a tool to the box. It's up to you whether or not you find it useful.

Doing the Windows

A little recap about the most common ways to popup Windows (with their caveat):


<a href="" target="_blank">W3C Validator</a>

<a href="#" onclick="'');return false;">W3C Validator</a>


<a href="'');void(0)">W3C Validator</a>
<a href="" onclick=";return false;" onkeypress=";return false;">W3C Validator</a>

Standards-Compliant Popups

Newer - better - methods rely on scripts that parse the document and apply the behavior to the anchors accordingly. These solutions use attributes of the A element (target, class or rel) as a "hook" (a marker).

Most of these methods style the links too (using some icons like this one for example), to warn the user about the particular behavior attached to the links.

(When a class is used, it is important that the author makes sure the links are not styled in JS-challenged browsers or if Javascript is disabled, otherwise it could be confusing for the user.)

The 2 scripts below go one step further, setting the markup free of anchor's attributes.

Popups for External Links:

// Copyright 2005 | Thierry Koblentz
function TJKpop() { // v1.0 |
  var e = document.getElementById('wrapper');
  if (e) {
      var a = e.getElementsByTagName('a');
      for (var i = 0; i < a.length; i++) {
          if (a[i].getAttribute('href') != null && a[i].getAttribute('href').indexOf("://") >= 0 && a[i].getAttribute('href').toLowerCase().indexOf(document.domain.toLowerCase()) == -1) {
              a[i].className += a[i].className ? ' outlink' : 'outlink';
              a[i].title += ' (opens in new window)';
              // a[i].target='_blank';
              // spawns multiple windows, but works fine with popup blockers
              a[i].onclick = function() {
                  newWin =, 'TJKWin');
                  if (window.focus) {
                  return false;
              // ONKEYPRESS
              // a[i].onkeypress=function(){,'TJKWin');if(window.focus){newWin.focus()} return false;}
window.onload = function(){if(document.getElementById) TJKpop();}

What does this script do?

  1. using the href value of the anchors, it finds the "external" links inside a given element.
  2. it applies a style to the links (applies a class or appends a class name to an existing class attribute's value)
  3. it attaches a title attribute to the links (or appends a string to the existing title attribute's value)
  4. it applies the behavior to each one of these links (through the onclick event handler)

Note that you may use any available element you want. For example, if your markup does not include a "wrapper", you may use "body" instead; in this case, you'd use the following:
var e = document.getElementsByTagName('body')[0];

What are the main advantages of this method?

How it works

function TJKpop(){
var e = document.getElementById('wrapper');

Find "wrapper" in the document and set it to "e".

if (e){

If "e" contains an object reference, it is worth looking past this opening bracket.

var a=e.getElementsByTagName('a');

Creates a collection ("a") of all a found in "wrapper".

for (var i=0;i>a.length;i++){

We are using a for loop to go through all the anchors. Between the parentheses, we have an Initialization statement (we could have used "var i=1;i<=a.length;i++" as well), a Condition (as long as “i” is less than the number of elements in the array, the statements inside the for loop are executed) and an Updation statement (that adds 1 to the variable “i”).

if (a[i].getAttribute('href') != null && a[i].getAttribute('href').indexOf("://") >= 0 && a[i].getAttribute('href').toUpperCase().indexOf(document.domain.toUpperCase()) == -1){

We cannot assume to find a "href" attribute with every A element, so we start by checking for this first. Then we use getAttribute() to get the value of the named attribute on the current node to verify that this value contains the "://" string.

That would be enough if the value returned was always a perfect match with the value from the source code; unfortunatley - in some browsers - the value returned is always an absolute path. This is why we need to check for the presence of another string, to make sure we exclude links that point to our own domain.

a[i].className+=a[i].className?' outlink':'outlink';

The DOM attribute className is used to set a class for that node; if there are previously existing current classes then it appends the string " outlink".

a[i].title+=' (opens in new window)';

We do the same with title. If there is a previously existing title, it appends the string " (open in new window)".

a[i].onclick=function(){,'TJKWin');if(window.focus){newWin.focus()} return false;}

Now we use the onclick event handler to attach the behavior to the links. "this.href" passes the href value found in the markup to the function; the string "TJKWin" is the name we give to the popup so these links do not spawn multiple windows. Then, by switching "focus" between the parent window and the popup we prevent the popup from disappearing behind the opener if the user selects another link. To finish, we use "return false" to make sure that Javascript enabled browsers ignore the href value in the markup.

To prevent issues with popup blockers, you may want to test for before running the script or you can simply replace the onclick statement with the following:
a[i].target='_blank'; (this will spawn multiple windows though...)

// a[i].onkeypress=function(){,'TJKWin');if(window.focus){newWin.focus()} return false;}

This line is commented and thus ignored. The WAI guidelines (checkpoint 9.3) says one should implement a redundant mechanism (i.e., onclick/onkeypress), but - as far as I know - this recommendation makes tabbing navigation impossible in Gecko browsers and Opera.

Read the end of this article to find out about a workaround…


Time to close all the brackets we’ve opened.

window.onload = function(){if(document.getElementById) TJKpop();}

document.getElementsById is used here to make sure the method is available and that we can run the script.

We’re using the window.onload handler to call the function, but there are better solutions (see Simon Willison’s solution).

Custom Popups for specific links:

Because the script looks for links within a particular element, it is easy to take advantage of this and mark up your pages accordingly. For example, one could use a DIVision to contain thumbnail images linked to larger ones and let the script do the work (applying the behavior only to the thumbnails inside that DIV).

Another possibility is to use this method to target files inside a specific folder; to use another example involving thumbnails and larger images, imagine using a folder's name ("bigpic" for example)...

This would be the markup:

<a href="img/bigpic/superman.jpg" title="Click to see larger image"><img src="img/superman.jpg" alt="Superman" /></a>

To create this thumbnail:

This would be the script to create custom popup windows only for files within this directory:

function TJKpopFolder(){ // v1.0 |
  var e = document.getElementById('wrapper');
  if (e){
    var a=e.getElementsByTagName('a');
    for (var i=0;i<a.length;i++){
    if (a[i].getAttribute('href') != null && a[i].getAttribute('href').toUpperCase().indexOf("BIGPIC") >= 0){
        a[i].className+=a[i].className?' popup':'popup';
        a[i].title+=' (opens in new window)';
        a[i].onclick=function(){,'TJKWin','location=no,menubar=no,status=no,toolbar=no,width=755,height=200');if(window.focus){newWin.focus()} return false;}
window.onload = function(){if(document.getElementById) TJKpopFolder();}

Let's not forget PDF files:

function TJKpopAppPdf(){ // v1.0 |
var zA=document.getElementsByTagName("a");
  for (var i=0;i<zA.length;i++){
  // if the type value contains "application/pdf" or if the href value contains "PDF" or if the file is in a "PDF" folder then we have a winner
    if (zA[i].getAttribute("href") != null && (zA[i].getAttribute("type") == "application/pdf" || zA[i].getAttribute("href").toUpperCase().indexOf(".PDF") >= 0 || zA[i].getAttribute("href").toUpperCase().indexOf("PDF/") >= 0)){
    zA[i].title+=" (opens in new window)";
    zA[i].className+=zA[i].className?" pdfFile":"pdfFile";
    // This spawns multiple windows, but works fine with popup blockers
    // zA[i].target="_blank";
    // This opens a unique window and brings it in front of the opener each time the user clicks on the link
    // Note that the new window opens without a toolbar. This is to avoid further conusion for the visitor
    zA[i].onclick=function() {,"TJKWin","toolbar=no");if( window.focus){newWin.focus()} return false;}

Et voilà!

This article is about selecting a particular set of links inside a document without extra markup, it does not take into consideration all issues related to popups.

Special thanks to Adam Smith, Ben Curtis, Andrew Krespanis and Gary White for their valuable feedback.

For further reading visit the following URIs

On the subject of popups:

On solutions to open popups

On the subject of events