Unobtrusive Javascript Popup Windows

Written February 9. 2004, at 12:17 GMT.

Have you ever wanted to use accessible popup windows without cluttering your content with ugly HTML code full of target="" and onclick="" attributes? If so, then look no further. This article explains possibly the cleanest, simplest and most elegant way to do popups - one that seperates link content from it's behavioural presentation. Enjoy!

I've long dreamt of applying the principles of unobtrusive javascript design to the programming of popup windows on web pages. I feel that wheather or not a link opens in a new window is purely a presentational issue, and should as such be seperated from the HTML content of every site - just like visual presentation is seperated from content by the use of Cascading Style Sheets (CSS).

I've now prepared a seperate a working example of how this may be accomplished, and below I'll try to explain a bit how to apply the code.

[Note: Feel free to copy this code and use and abuse it any way you like. No strings attached. However, a link back to this page would be much appreciated - thanks!]

Step 1: Save this code

Copy and paste the following javascript functions into a file:

window.onload = initPage;  
// Make sure that no other javscripts assign a fuction to window.onload
// There can be only one window.onload at a time

function initPage() {
  initPopupLinks();
  // place here any other code you wish to run when the page loads.
}

function initPopupLinks()
{
  if (!document.getElementsByTagName) return true;
  var pageLinks = document.getElementsByTagName("a");
  for (var i = 0; i < pageLinks.length; i++) 
  {
    if (((pageLinks[i].className != null) && 
         (pageLinks[i].className != "")) ||
        ((pageLinks[i].parentNode.className != null) && 
         (pageLinks[i].parentNode.className != "")))
    {
      var linkClass = " " + pageLinks[i].className + " ";
      if ((linkClass == "  ") && (pageLinks[i].parentNode.className != ""))
      {
        linkClass = " " + pageLinks[i].parentNode.className + " ";
      }
      for (var theKey in popupLinkConfig) 
      {
        if (linkClass.indexOf(" " + theKey + " ") > -1)
        {
          if ((pageLinks[i].target == "") || (pageLinks[i].target == null))
          {
            pageLinks[i].target = (popupLinkConfig[theKey][0] != "") ? popupLinkConfig[theKey][0] : theKey;
          }
          pageLinks[i].settings = popupLinkConfig[theKey][1];
          pageLinks[i].onclick = popUp;
        }
      }
    }
  }
  return true;
}

function popUp()
{
  newWin = window.open(this.href, this.target, this.settings);
  newWin.focus();
  return false;
} 

Save the file as "popups.js and link to it from within the <head> block of your web pages using the following HTML tag:

<script type="text/javascript" language="Javascript" src="popups.js"></script>

Step 2: Choose your styles (configuration)

Copy the following lines of popup configuration code, either into your javascript file, or inside a seperate .js file if you'd like a clean seperation between your site preferences and the code that uses them.

var popupLinkConfig = new Array;
// Delete/copy/modify the following lines to configure your popup windows.
popupLinkConfig["popup"] = new Array ( "", "width=350,height=450,scrollbar=yes,menubar=yes");
popupLinkConfig["glossary"] = new Array ( "help", "width=550,height=350,resizable=no,scrollbars=no");

The above example uses the keywords "popup" and "glossary" to define two different types of popup links used on the demo page.

Each link-type has two properties:

The first is an optional window-target name, which is equilvalent to the target attribute traditionally in HTML for popup links. The target porperty is optional, as the popUp() function uses the link class-name (e.g. "popup", "glossary") as a default target name.

The second property is a string with all the optional settings used for the new window - e.g. its width and height, etc. The example javascript file popups.js contains a full list of the available settings.

Step 3: Write your links

Now all you have to do is to write ordinary <a href=""> links and apply a class attributes to them to control their visual appearance and also their on-click behaviour.

If the class value of the link matches a name specified in your popupLinkConfig array (see "Step 2" above), the link will automatically open in a popup window.

Writing the HTML is as easy as this:

Lorem ipsum <a href="http://www.yahoo.com/" class="popup">dolor</a> sit...

Look Ma, no onclick or target attributes, and no inaccessible javascript: URLs or other such crud!

Obviously, this method makes it possible for you to change which types (classes) of links open in seperate windows and how large these poup windows are, without changing the actual content of your site. This is an important step in the process of future-proofing your content.

Check out the example page to see these unobtrusive popup links in full action.


More like this: English Entries, .


Reader Comments (26)

  1. Tóró replies:

    Really cool, I will 'steal' this idea next time I have to create a pop-up window :)

    [Edit: removed an offtopic comment about a one-off CSS bug in this site, caused by an outdated browser cache. -- Már]

    February 9. 2004 kl. 15:21 GMT | #

  2. Ólafur Sverrir replies:

    Good job, one question tho. Why do you change the "href" of the link to # ? I, for one, am very suspicious of URIs that end in a single # and would be less annyoed if the statusbar would display the URI that would open in a popup window, instead of something which gives no hint about it.

    February 9. 2004 kl. 16:41 GMT | #

  3. egill replies:

    [English translation:] I believe your script may cause conflicts with other onLoad event handlers that may have been set.

    I also happen to have a similarily unobtrusive javascript that colors every other line in an HTML <table>. Would you be interested in that?

    [Icelandic original:] Smá galli, nenni ekki ađ skrifa á ensku :) Ţetta yfirskrifar hugsanleg onLoad script sem eru til fyrir, ef ég skil ţetta rétt a.m.k. Og ţú ert međ ţetta skemmtilega copy/paste vandamál í IE, ţannig ađ ţađ er ekki hćgt ađ gera copy/paste á ţessu :) Annars á ég skemmtilegt script sem útfćrir zebra á töflur eftirá, ef ţú hefur áhuga á ađ fá ţađ?

    February 9. 2004 kl. 17:28 GMT | #

  4. Már Örlygsson replies:

    Good call, Ólafur. I've now updated the script and removed the two lines where I assigned the value of the href attribute to a new attribute pophref and set the href to "#". Those were the remains of an early debugging experiment and never should have left the factory. Me bad.

    Egill, do you think the window.onload issue is likely to cause confusion? Hmmm... any suggestions on how to make this more drool-proof?

    P.S. Egill, please feel free to share your color-every-other-line-in-an-HTML-table script. If you don't want to publish it yourself: you can e-mail it to me and we can publish it here if you like. The world needs more examples of unobtrusive javascripts! ;-)

    February 9. 2004 kl. 18:30 GMT | #

  5. Ólafur Sverrir replies:

    You can get around the onload "limit" by using addEvent, a [crossbrowser event-handler][cbs-events] by Scott Andrew. It looks like it is pretty the standard in hooking functions to onload, see [sorttable][] by Stuart Langridge and [easytoggle][] by Simon Willison.

    [cbs-events]: http://www.scottandrew.com/weblog/articles/cbs-events
    [sorttable]: http://kryogenix.org/code/browser/sorttable/
    [easytoggle]: http://simon.incutio.com/archive/2003/11/06/easytoggle
    

    February 9. 2004 kl. 22:33 GMT | #

  6. Már Örlygsson replies:

    Thanks for the pointers Ólafur. I've known about Scott Andrew's addEvent for a while, but never bothered to use it for my own projects. I guess it's just perfect for small stand-alone utilities like this one.

    I've updated the script to use Scott's elegant addEvent function instead of the old window.onload command.

    However, my inclusion of addEvent, may still cause conflicts with other javascripts that may be using another instance of the function. In those cases, the user must use his/her brain and delete all instances of addEvent except one. I hope they'll manage. ;-)

    February 10. 2004 kl. 00:26 GMT | #

  7. Ólafur Sverrir replies:

    I did a quick google search for problems with redefining functions. Didn't find anything, and a small test showed no errors in the JavaScript console of Firefox, or in IE. So it seems like redefining functions is OK in JavaScript. Thus your script should not interfere with other scripts that use addEvent.

    This makes adding unobtrusive JavaScript easy, since you just include the script and add the class/ID or whatever it is to mark the tag that is to be changed. You only need to make sure that the init function has a specific name.

    February 10. 2004 kl. 15:10 GMT | #

  8. Jósi replies:

    Er...

    All the example links load in the parent window here on my mom´s laptop...

    February 10. 2004 kl. 21:26 GMT | #

  9. Ólafur Sverrir replies:

    Because of something, god only knows what, IE doesn't handle the addEvent correctly when attaching events to the click event of the links. To correct this, simply go back to setting the onclick method of each link to the popUp handler. Since it is highly unlikely it will cause any conflicts, it should be a-okay.

    February 10. 2004 kl. 22:57 GMT | #

  10. Már Örlygsson replies:

    Ólafur, I just noticed that in Mozilla too. Something wasn't working the way it should. I've reverted back to using pageLinks[i].onload and while I was at it I moved most of the code out of the popUp() function into initPopupLinks()

    Makes more sense to have it that way. Today I'll do some testing on the Mac browsers and see if Jósi can tell me if the problem he had on his mothers computer persists after the last set of changes.

    Jósi, what type of system/browser is your mother running?

    February 11. 2004 kl. 05:56 GMT | #

  11. Már Örlygsson replies:

    Hmm... I've reverted back to using window.onload all around, and I've removed all references to addEvent().

    Reason: It doesn't work in IE5/Mac which is unacceptable given the sad fact that most Macintosh users still use IE for their browsing.

    Bah, so much for elegant handling of events...

    February 11. 2004 kl. 12:19 GMT | #

  12. Ólafur Sverrir replies:

    It looks like IE5/Mac doesn't support any kind of event handlers (). So once again, incompetent browsers stop logical coding, sigh.

    February 12. 2004 kl. 10:37 GMT | #

  13. Jósi replies:

    Mom´s laptop uses IE 6.0 on Win 98

    oh, and the popups work now...

    February 12. 2004 kl. 18:27 GMT | #

  14. Andri Sigurđsson replies:

    Even though IE5/mac has an issue, it would not stop me from using the script.

    Another Stuart Langridge script : NiceTitles

    I use this (modified version) on my own page, so sweet :)

    February 12. 2004 kl. 21:06 GMT | #

  15. Már Örlygsson replies:

    Andri, for me it depends on the script. For something completely superfluous like Nicetitles, I couldn't care less if it works in IE5/Mac or not, but for something pretty basic, like popup windows, I think the poor IE5/Mac using sods deserve a nice treatment.

    February 12. 2004 kl. 21:24 GMT | #

  16. Arnór replies:

    Jćja tala ţá bara ensku..

    This is vierd, when i open a link, it doesn´t work in the first but it works in second attempt....

    Yes you heard me :) Always when i load a site, the first picture that i click on, will open in blank window but when i click again.... that works fine.

    Here i can show you two pages, other one (1) uses a ordinary popup javascript but (2) uses a Unobtrusive Javascript: Popup Window.

    (1)

    (2)

    This work perfectly on moxilla and Opera but in IE, i need to refresh the window and also click on 1-2-3 links when i finally work..

    Now i cleared all caches in the browser and it didn´t work until i was clicking on the fourth window.. and that seem pretty misterious :)

    I´m no javaguru but, can´t this be fixed with some body> onload function?

    February 13. 2004 kl. 15:45 GMT | #

  17. Arnór replies:

    [English translation:] I tried to restart my computer and then the popups started working in IE (= bad, bad browser!).

    [Icelandic original] Já heyrđu, ég prófađi ađ restarta tölvunni og hreinsa allt cache og temporary og ţá fyrst virkar glugginn alveg í fyrsta og virkar alveg vel. Ţađ var eitthvađ sem ég prófađi ekki í dag. Ţetta sannar ađeins eitt, og ţađ er IE er međ hređjartak á vinnsluminni tölvunnar. Ţađ virđist bara ekki vera nóg ađ hreinsa cache međ ctrl+f5 eđa hreinsa temporary folder.... ţađ ţýđir ekkert annađ en restart.

    P.s. Mozilla gerir allt eins og ég vil ađ hún gerir og sannar ţađ ágćti vafrans, annađ en IE ţessa daganna.

    February 14. 2004 kl. 03:42 GMT | #

  18. Daniel replies:

    I'm not JavaScript savy, so I didn't understand all of the discussion above, but I want to point out that in my environment, Windows version of Firefox 0.8 (with Tab Browsing Preferences set to open links in a new tab instead of a new window) #1 and #2 of your example links end up in both a pop up and in a new tab, thus opens in two instances.

    Sorry if that was redundant.

    February 25. 2004 kl. 12:13 GMT | #

  19. Mary replies:

    About the window.onload thing.

    Instead of this:

    window.onload = initPage;  
    // Make sure that no other javscripts assign
    // a function to window.onload . There can 
    // be only one window.onload at a time
    
    function initPage() {
      initPopupLinks();
      // place here any other code you wish to run 
      // when the page loads.
    }
    

    Why not like this? :

    window.onload = function() {
      // place here any other onload functions
      initPopupLinks();
    }
    

    Maybe?

    March 18. 2004 kl. 22:15 GMT | #

  20. Már replies:

    Good suggestion, Mary. Using an unnamed function or even a direct window.onload=initPopupLinks, may be more than sufficient for a simple tutorial like this one

    However, it's an old habit of mine to use a named init-function because I've learned that it makes my life a little easier when working on large projects with shared javascript files and many different people contributing, occationally overloading the window.onload event with their own javascripts.

    March 19. 2004 kl. 10:15 GMT | #

  21. Már replies:

    Hi Daniel of #18 and sorry for the late answer!

    I believe this double opening behaviour is caused by a bug in the Tab Browsing Preferences in Firefox.

    It may be that the code that suppresses the popup is overlooking the possibility of the [object].onclick syntax being set used to define 'onClick' events instead of just by adding an onclick="" attribute on the HTML tag.

    March 21. 2004 kl. 02:42 GMT | #

  22. dave replies:

    It would be nice if you could apply an entire element (div, ul, p, etc) and its child href tags would popup. e.g. A ul with the class "popup" would cause all links within it to popup.

    May 14. 2004 kl. 16:23 GMT | #

  23. Már replies:

    Dave, I've added that kind of functionality to another version of this function, that I use in my professional projects, and it works very nicely. However, this demo was mainly intended as an example of how the philosophy of unobtrusive DHTML applies to popup links, and not as feature-full software.

    Feel free to create (and publish if you will) a customized version of my code.

    May 20. 2004 kl. 18:57 GMT | #

  24. Sjur replies:

    I have made a popup function myself and just put it in the page that needs it. I would like to move it over to a .js file since i use the funciton in several pages, but didnt realy folow how your script was called.

    My questions are: 1. Why does the function popUp() get called when your class="something" is in that array? I didnt quite follow that, I myself would have called the function directly from the

    May 21. 2004 kl. 15:16 GMT | #

  25. Sjur replies:

    I have made a popup function myself and just put it in the page that needs it. I would like to move it over to a .js file since i use the funciton in several pages, but didnt realy folow how your script was called.

    My questions are: 1. Why does the function popUp() get called when your class="something" is in that array? I didnt quite follow that, I myself would have called the function directly from the

    May 21. 2004 kl. 15:54 GMT | #

  26. Matt replies:

    Hi,

    First, I have to say that I absolutely love this popup script. However, when going through your code, I don't understand the purpose of:

    (pageLinks[i].parentNode.className != null) && (pageLinks[i].parentNode.className != "")

    Excuse my ignorance, but what's the point of this? I understand what it's doing, just not sure why. Any feedback is greatly appreciated.

    thanks, m.

    January 19. 2005 kl. 21:25 GMT | #

Ţessum svarhala hefur veriđ lokađ. Kćrar ţakkir til ţeirra sem tóku ţátt í umrćđunni.


 

Flakk um vefsvćđiđ



 

Nýleg svör frá lesendum

  • Rich (Req.js - javascript lazy-loading and dependency managment made easy)
  • Rich (Req.js - javascript lazy-loading and dependency managment made easy)
  • Rich (Req.js - javascript lazy-loading and dependency managment made easy)
  • Már (Req.js - javascript lazy-loading and dependency managment made easy)
  • Rich (Req.js - javascript lazy-loading and dependency managment made easy)
  • Már (Req.js - javascript lazy-loading and dependency managment made easy)
  • Dinesh (Req.js - javascript lazy-loading and dependency managment made easy)
  • Már (Taubleyjur í nútímanum - lítill leiđarvísir handa hrćddri ţjóđ)
  • Ada (Taubleyjur í nútímanum - lítill leiđarvísir handa hrćddri ţjóđ)
  • notandi (Taubleyjur í nútímanum - lítill leiđarvísir handa hrćddri ţjóđ)
  • Geir (Lausnin á efnahagsvandanum)
  • Jenný (Lausnin á efnahagsvandanum)
  • Óli Jens (Lausnin á efnahagsvandanum)
  • Már (Lausnin á efnahagsvandanum)
  • Kjartan S (Lausnin á efnahagsvandanum)

 

 

Yfirlit yfir ţetta skjal

(Atriđin í listanum vísa á ákveđna kafla ofar á síđunni.)