Using JavaScript instead of target to open new windows

Update: The technique described here is not ideal. Read why in New windows with JavaScript and the target attribute.

In my recent post about The target attribute and opening new windows, I stated that when I am faced with no other choice but to open a link in a new window, I prefer using unobtrusive JavaScript instead of the target attribute. The reason is that I always use a strict doctype, which does not allow the target attribute.

What I did not say was exactly how the script I use is constructed, but I guess I should have. A few people commenting on the post thought that I was suggesting the use of JavaScript to insert the invalid target attribute simply to hide it from the W3C Markup Validator. Cheating to pass validation is not what I am proposing.

After a bit of searching I wasn't able to find a detailed description of this kind of script, so I thought I'd write one. It isn't a very complicated script, so it's hardly groundbreaking, but I hope somebody will find it useful.

For the script to work you need to edit your markup just a little, since the script needs to be able to tell which links it should affect. Some use the rel attribute for that, but I prefer using the class attribute since it allows me to style the links that will open a new window. The script looks for links with a class name of non-html, and allows multiple class names.

I think the class name non-html also serves as a good reminder that one of the few times it may be ok to make a link open a new window is when its target is a document in a non-HTML format. Common examples are PDF files and Word documents.

The user should always be warned when links will open new windows, so the script also adds a text with some information about the link's behaviour. To make it stand out a bit more to people browsing with CSS off and JavaScript on, the text is wrapped in an em element.

Example markup:

  1. <a href="" class="non-html">The website</a>

Try it out in the JavaScript target demo document.

To use the script, make sure these two functions are included in your common.js or wherever you store your global JavaScript functions:

  1. /*
  2. Create the new window
  3. */
  4. function openInNewWindow() {
  5. // Change "_blank" to something like "newWindow" to load all links in the same new window
  6. var newWindow ='href'), '_blank');
  7. newWindow.focus();
  8. return false;
  9. }
  10. /*
  11. Add the openInNewWindow function to the onclick event of links with a class name of "non-html"
  12. */
  13. function getNewWindowLinks() {
  14. // Check that the browser is DOM compliant
  15. if (document.getElementById && document.createElement && document.appendChild) {
  16. // Change this to the text you want to use to alert the user that a new window will be opened
  17. var strNewWindowAlert = " (opens in a new window)";
  18. // Find all links
  19. var objWarningText;
  20. var strWarningText;
  21. var link;
  22. var links = document.getElementsByTagName('a');
  23. for (var i = 0; i < links.length; i++) {
  24. link = links[i];
  25. // Find all links with a class name of "non-html"
  26. if (/\bnon\-html\b/.exec(link.className)) {
  27. // Create an em element containing the new window warning text and insert it after the link text
  28. objWarningText = document.createElement("em");
  29. strWarningText = document.createTextNode(strNewWindowAlert);
  30. objWarningText.appendChild(strWarningText);
  31. link.appendChild(objWarningText);
  32. link.onclick = openInNewWindow;
  33. }
  34. }
  35. objWarningText = null;
  36. }
  37. }

Thanks to Robert Nyman for looking over the script for me and pointing out a couple of mistakes I'd made.

Either copy and paste from here or download my sample javascript-target.js file, which contains all the JavaScript you need to use this.

Be aware that if you use XHTML served as application/xhtml+xml, document.createElement() will not work in all browsers. In that case you should take a look at Simon Willison's createElement() function, described in Javascript, the DOM and application/xhtml.

After that you need to make sure the getNewWindowLinks() function is executed when the document has loaded so it can insert the onclick event handlers. Use your favourite addEvent() function. There are many different addEvent() functions floating around, but the winner of PPK's addEvent() recoding contest should be a good choice. Once you have an addEvent() function in your JavaScript library, the following will load the getNewWindowLinks() function.

  1. addEvent(window, 'load', getNewWindowLinks);

I suggest putting that line can be at the end of common.js.

So what are the benefits of opening new windows this way?

  • You can keep the strict doctype, which makes it easier to keep track of any presentational markup that sneaks its way into the markup.
  • The script is unobtrusive, meaning that for users with no JavaScript support links will open normally (in the same window).
  • People who use tabbed browsers can still choose to open the link in a new tab.
  • It doesn't interfere with extensions like Tab Mix Plus that let Firefox be configured to open links that open new windows in a new tab instead. Update: It apparently does interfere with Tab Mix Plus under certain circumstances. See comment #1 on this page.

Of course this function could be extended to accept a whole lot of parameters like window size and such, but I've deliberatly kept it as simple as possible.

And again, don't forget that opening new windows should generally be avoided.

Update: After considering the suggestions made in the comments I have made some changes to the script. Please use the updated script as described in Opening new windows with JavaScript, version 1.2 instead of this version.

Posted on May 2, 2006 in JavaScript