Opening new windows with JavaScript, version 1.1

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

After considering the suggestions made in the comments on my article Using JavaScript instead of target to open new windows and thinking some more about it, I’ve made some changes to the script. For the full story, please read the original article if you haven’t already.

The revised script differs from the original in two ways:

  • It no longer opens a new window if a modifier key is pressed while the link is clicked. Good news for people who like to ctrl/shift/cmd/whatever-click to open links in new tabs.
  • It now checks if the new window was successfully opened. If it was not, it returns true to allow the browser to open the link in the original window.

To enable link styling depending on the type of file being linked to, I have revised the markup to use an additional class name that matches the file type. This has the additional benefit of enabling link styling in browsers with no JavaScript support. Note that I haven’t styled the link in the demo document.

Example markup:

  1. <a href="javascript-target.pdf" class="non-html pdf">A sample PDF file</a>

Try it out in the JavaScript target demo document.

Here is the revised script, which should be included in your common.js or wherever you store your global JavaScript functions:

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

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

You also need to make sure the getNewWindowLinks() function is executed when the document has loaded. Use whichever addEvent() function you prefer using:

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

That line is included in the javascript-target.js file that accompanies this article.

If you have any suggestions for further improvement, please post a comment.

Update: I have updated the script again. More information is available in Opening new windows with JavaScript, version 1.2.

Posted on May 9, 2006 in JavaScript

Comments

  1. Some excellent additions imo!

  2. Checking whether the modifier key is pressed is a great idea.

    I still prefer the rel attribute for this.

  3. When I hold Ctrl while clicking on the link in Firefox, it opens the page twice.

  4. May 9, 2006 by Jeff

    I would think that you should wrap your functions up using object literal notation for safekeeping.

  5. Good changes with this version, very useful.

  6. May 9, 2006 by Roger Johansson (Author comment)

    trovster: I considered the rel attribute, but after reading up on it I’m not convinced that using it for this purpose is correct.

    Jero: Drats, you’re right. It only happens in Firefox for Windows though, so I’m not sure what’s up with that.

    Jeff: I’ll look into that if my brain can understand the concept. I am not OOP compatible.

  7. ctrlkey should be ctrlKey (uppercase K)

    Maybe it’s smart to null newWindow afterward. I’m not sure though if there is any a memory leak.

  8. May 9, 2006 by Roger Johansson (Author comment)

    Ok, it works in Firefox and other browsers that use the Ctrl key to open links in a new tab now. I’d written “ctrlkey” instead of “ctrlKey”. Duh.

  9. I see just beat me to it :-)

  10. May 9, 2006 by Ryan

    Roger have you ever seen this - http://test.newplasticarts.co.uk/flag-offsite-links/ ? I know its not exactly what you were aiming at but has some interesting ideas. :)

    Sorry if this was posted in the last entry.

  11. May 9, 2006 by Roger Johansson (Author comment)

    Ryan: Nope, I missed that one, and it does have some interesting ideas. Thanks!

  12. The last time I had to discuss opening links in a new window with a client, the client tried to click the back button on the new window. I was so tempted to open a bag of “I told you so!”

    What happens if a person has the configuration to launch in new window vs. new tab? Does it still open a new window (i.e. sized window for Flash)?

  13. I was relieved too note that you managed to prevent the double window from ctrl-clicking but your script is still broken.

    When doing a regular click it doesn’t even work for me, it just opens the “popup” in the same window as the page i click it from. Using Firefox 1.5. Might be one of my extensions, but it hasn’t stopped other popups from working.

  14. Ryan: It opened in a new tab for me, I have FF set to open all new links and popups in tabs :)

    Spot on Roger!

  15. May 10, 2006 by Ryan

    Paul Solecki: In that case whats the problem? A new tab is better than a new window, if a site opens pages in a new window instead of a new tab with me I go nuts! heh

    I like the toggle option though, I have to admit I haven’t had a chance to fully look over Roger’s solution so I have no idea if he has a toggle option also.

  16. May 10, 2006 by Roger Johansson (Author comment)

    Ryan: It depends on the browser and how it is configured, if there are any extensions installed etc.

    Raevel: It must be an extension. It works in Firefox here, both Mac OS X and Windows.

    Ryan: This script does not contain a toggle option, but it sounds like a good idea. Maybe in the next version ;-).

  17. Sorry, but why don’t you just use XHTML 1.0 Transitional? at least in the pages where you have to use the target attribute?

    I myself, use Strict mode too, but if I have to use target attribute, I think I’ll use Transitional mode.

    That’s what I’ve done with an old script that uses a form with the “name” attribute. Sure It’s a bit lazy :)

    But, that’s easier and IMHO harmless.

    Thanks.

  18. Ok, i watched the 2 topics about javascript targets for a couple of days. But i cannot see the reason why you should javascript to init a target method.

    On the otherhand why not do this target magic in CSS:

    a[target=”_blank”] {color: #000000}

    Or am i missing the point here?

  19. function blank_magic() {

    var show = document.getElementsByTagName(“a”);

    for ( var j=0; j < show.length; j++ ) {

      var anchor = show[j];
    

    if (anchor.getAttribute(“id”) == “external”)

     anchor.target = "_blank"; 
    
     }
    

    }

    window.onload = blank_magic;

    LINK:

    id=”external”

  20. May 11, 2006 by Roger Johansson (Author comment)

    karim: Because I don’t know which pages will need to open new windows. Clients handle the content through a CMS. So that is not an option.

    Jungsonn: Because it is behaviour.

    I’m not sure what the purpose would be of making all links with target=”blank” black. Care to explain that?

    The script you entered will only work for a single link on a page. Id has to be unique.

  21. Yeah i needed more coffee, those nightly posts :) I got the wrong idea of what you supposed to do.

    The id attribute, if replaced with “rel” would that work for all links? think it does.

  22. Just a sec… “id” does work on all links.

    This time i tested my code:

    a href=”http://www.foo.com” id=”external”

    a href=”http://www.foobar.com” id=”external”

    a href=”http://www.barfoo.com” id=”external”

  23. May 11, 2006 by Roger Johansson (Author comment)

    If it works it is a coincidence. I wouldn’t be surprised if some browsers will only find the first or last link with the same id. Either way it is invalid, which rules it out.

  24. I just made up “id” as atribute for example, do you think that rel=”external” would be valid?

  25. W3c has the following information about rel & id on their website.

    id: “When the name or id attributes of the A element are set, the element defines an anchor that may be the destination of other links.”

    rel: “This attribute describes the relationship from the current document to the anchor specified by the href attribute. The value of this attribute is a space-separated list of link types.”

    So IMHO i think both can be used. I agree on your argument that ‘id’ is very clever chosen, and could produce flaws. So the attribute ‘rel’ should be an alternative.

  26. May 11, 2006 by Michaël Guitton

    Roger, it would seem you’ve made a slight mistake …

    11. if (newWindow) {
    12. if (newWindow.focus) {
    13. newWindow.focus();
    14. return false;
    15. }
    16. }
    

    should read:

    11. if (newWindow) {
    12. if (newWindow.focus) { newWindow.focus(); }
    13. return false;
    14. }
    15. // etc.
    

    It should return false even if focus method is unsupported.

  27. May 11, 2006 by Roger Johansson (Author comment)

    Jungsonn: I am still undecided on the use of the rel attribute. The id can be used, but it is very limited since any id is only allowed once on a page. You cannot have multiple links that share the same id.

    Michaël: Yes it should. Thanks for catching that mistake.

  28. May 13, 2006 by endryou

    IMHO

    var strWarningText;

    is not neccessary. Instead of:

    strWarningText = document.createTextNode(strNewWindowAlert);
    objWarningText.appendChild(strWarningText);

    you can write:

    objWarningText.appendChild(document.createTextNode(strNewWindowAlert));
  29. I found a small problem in that firefox (Win 1.5) fired a javascript warning

    Warning: variable e hides argument
    

    when it encountered the line:

    if (!e) var e = window.event;
    

    To avoid the warning I made a small modification, replacing lines 3 to 5 with:

    if (!e) var e1 = window.event;
    else var e1 = e;
    // Abort if a modifier key is pressed
    if (e1.shiftKey || e1.altKey || e1.ctrlKey || e1.metaKey) {
    
  30. Roger, Did you see this tutorial at Accessify.com? http://accessify.com/features/tutorials/the-perfect-popup/

  31. May 15, 2006 by Roger Johansson (Author comment)

    endryou, james: Thanks, I’ll update the script.

    Marc: Nope, missed that one. I do prefer my approach though ;-).

  32. @Marc

    That script looks much like the one i wrote, although slightly different. Sure you can use this one, just like mine. Although IMO you should see it as “a quick fix”. Roger’s one is more covering.

  33. May 18, 2006 by Ianf

    Nice work, Roger, really enlightening approach to light- weight/ unobtrusive AND fallback- capable JS. Thus I’m happy to report that both versions’ demos open fine (= render to same window) in Blazer 4.3 Mozilla 4.0- compatible browser (accessed through google.com/gwt/n mobile proxy) on a PalmOS Lifedrive PDA with 320x448px viewing area; this browser/ proxy combo otherwise being pretty unforgiving where abuse —or simply excess— of JS is concerned (I was able to preview, but unable to post this comment via the proxy-mt.cgi, though that may be a limitation on MT-comments’ backend; ergo posting it directly.)

  34. May 19, 2006 by John

    Nice script, thanks for sharing!

    I’m trying to extend the script to include custom window properties. I’m a js newbie, so here goes.

    Basically I have a custom function called “openPromo”.

    function openPromo() {
      var p = document.getElementById('promo');
      var config = {status:0,...,target:'_blank'};
      p.onlclick = openInNewWindow
    }
    

    My question is, how do you pass the “config” variable into the “openInNewWindow” function. I guess the “e” parameter is confusing me as I don’t know where it comes from.

    Thanks!

  35. May 22, 2006 by john

    Answered my question above. For anyone who may be curious.

    function setOpenInNewWindow(config) {
      return function openInNewWindow(e) {
        /* Rogers function with Michaël Guitton suggestions */
      }
    }
    
    var config = [window settings]
    element.onclick = setOpenInNewWindow(config);
    

    See Michaël Guittons comment

  36. sorry for cross-post, but I believe this to be relevant for this entry too: previous comment

  37. Thanks for code.

    Trying to get the pdf to open in a new window with “target=blank” worked on my own machine but not when I uploaded to my site. And I only wanted it for one of a number of links on the page.

    Keep up the good work.

  38. I use this which is the bare minimum, consider accessibility and warn users on the new window:

    <a href=”cat.jpg” onclick=”this.target=’_blank’” onkeypress=”this.onclick” title=”Cat photo (New Window)”>View the cat</a>

    If Javascript is disabled the image opens in the current window, I believe there are no alternatives if you want to stay with Strict doctype.

    This is an extreme shortcut if you don’t want to load other pieces of javascript which will introduce more accessibility warnings…

  39. Hello,

    I am opening the Excel, Word and PDF documents from my ASP .NET script.

    Whenever I open a document, it’s displaying the modal Open Save Cancel.

    I would like to open the documents by suppresing the dialog.

    Here is the code.

    function popdocument(itemCode,dir) { document.execCommand(‘SaveAs’,false,itemCode) }

    Any help in suppressing the dialog will be greatly appreciated.

    Thanx,

    J

  40. This is why I love jQuery for things like this…

    $(“a.newWindow”).attr({target: “_blank”});

    Only 1 short line of code.

  41. October 18, 2006 by Roger Johansson (Author comment)

    Eric: Yeah, one line of code plus an entire script library…

  42. Roger: Yes if you are only using jQuery to open a new window otherwise extremely good if like me, you use it for other reasons.

  43. How can I change the script to open the window in a new TAB (IE 7.0 and Latest Firefox)?

    Is there a special attribut I have to set?

  44. February 1, 2007 by Roger Johansson (Author comment)

    How can I change the script to open the window in a new TAB

    Not possible as far as I know.

  45. How can I change the script to open the window in a new TAB

    That would be a user-side preference for what behaviour the visitor chooses of the web client.

  46. Great script!

    A small remark: the comments in the downloadable sample script say that it uses the class name new-window, but it tests for non-html.

Comments are disabled for this post (read why), but if you have spotted an error or have additional info that you think should be in this post, feel free to contact me.