LearnLearn How: Programmatically Open File Downloads in a New Window with JavaScript

Andrew Chalkley
writes on July 14, 2015

Have you ever wanted a way to update all file download links on your site to have the behavior of opening a new browser window? This is a better user flow than having the user follow the link and then pressing the back button to get to where they were.

In this simple tutorial, I’ll show you how to do it. I’ll also show you another use case; opening a new window when the link is a to an external site. Two tutorials for the price of one!

You can actually do it without JavaScript, but it requires you to be super vigilant when adding links to your site. Your users may be able to insert links and downloads on your site too, and expecting everyone to remember to do it the “right” way isn’t practical. The way you can do it without JavaScript is using the target attribute.

<a href="some.pdf" target="_new">Really Important Document</a>

You may be saying, “Andrew, didn’t you know that target was deprecated with HTML5?”, to which I’d reply “Yes, but then it isn’t again!” and you’d say “That’s good to know!”.

So we’ll use JavaScript to add the target attribute programmatically to the links we want.

How to do it?

So, imagine you have a link somewhere on your site like this:

<a href="some.pdf">Really Important Document</a>

We need to select the link. We’ll just use plain old JavaScript for this.

var pdfAnchors = document.querySelectorAll("a[href$='.pdf']");

We’re using the CSS selector a[href$='.pdf'] meaning all links that end with ($) the extension .pdf. Most modern browsers can use querySelectorAll. Since this behavior is a “nice to have”, I’m not worried if this doesn’t work in an older browser.

Next we can cycle over each link and set the target attribute to "_new". You could put anything here. But you’ll see "_new" used in most places meaning new window. The target attribute is a reference to a window. All links with the same target will be opened up in that window. We could easily do something like "download" instead.

for(var i = 0; i < pdfAnchors.length; i++) {
    pdfAnchors[i].target = "_new";  
}

This works! However, this could break existing links with targets that are supposed to be there for whatever reason. For example loading something in an iframe.

<a href="some.pdf">Really Important Document</a>
<a href="someOther.pdf" target="special_iframe_target">Another Important Document</a>

We can do something like this:

for(var i = 0; i < pdfAnchors.length; i++) {
    pdfAnchors[i].target =  pdfAnchors[i].target || "_new"; 
}

It’ll assign the target‘s value to be the same value if it already exists, or if it doesn’t exist, it’ll assign the target to "_new".

And that’s it.

Dealing with External Links

Another reason you’d want to open up links in a new window is if you’re going to an external site.

This time you want to check all the links on the page. Conveniently there’s a collection of links on the document object. This is available in any browser with even the most basic API for the DOM implemented.


for(var i = 0; i < document.links.length ; i++) {

}

When we cycle over each link we want to compare the host of the link to the host of the window. If they don’t match we want to create the target attribute.

for(var i = 0; i < document.links.length ; i++) {
    var link = document.links[i];
    var linkHost = link.href.split("/")[2];
    if(linkHost !== window.location.host) {
        link.target = link.target || "_external";
    }
}

Even if your links are relative when you access it programmatically they are absolute URLs. The following HTML hosted on example.com…

<a href="/about">About</a>

…would have the href property of http://example.com/about. So if you were to split it on / the 3rd or index number 2 will be the host. Which is handy!

Conclusion

And, there you have it. Here’s how the examples look together:

<!DOCTYPE html>
<html>
    <body>
        <a href="thisisapdf.pdf">This is a PDF</a>
        <a href="thisisapdf.pdf" target="special_iframe_target">This is a PDF opening in an iframe</a>

        <a href="http://duckduckgo.com">An external link</a>

        <a href="http://duckduckgo.com" target="special_iframe_target">This opens in a special iframe</a>

        <iframe width="200px" height="200px" frameborder="0" id="special_iframe_target">

        </iframe>
        <script>
            var pdfAnchors = document.querySelectorAll("a[href$='.pdf']");

            for(var i = 0; i < pdfAnchors.length; i++) {
                pdfAnchors[i].target = pdfAnchors[i].target || "_new";  
            }


            for(var i = 0; i < document.links.length ; i++) {
                var link = document.links[i];
                var linkHost = link.href.split("/")[2];
                if(linkHost !== window.location.host) {
                    link.target = link.target || "_external"    
                }
            }

        </script>
    </body>
</html>

Ideally you’d want to manually have the target set on the links that you need. But with intelligent client-side programming you can add that behaviour without too much headache and progressively enhance the HTML that’s already there.

If you’re interested in what else you can do with the DOM you can try our Interactive Web Pages with JavaScript course.

4 Responses to “Learn How: Programmatically Open File Downloads in a New Window with JavaScript”

  1. [url=http://www.gginza.com/wallet/louisvuitton/index.html]弊社は海外安心と信頼のプラダ 時計 コピーです。2015 新作が満載!皆様を歓迎して当店をご光臨賜ります。ロレックス時計コピー,パネライ時計コピー,ウブロ時計コピー ,ブライトリング時計コピー,IWC時計コピー,フランクミュラー時 計コピー,ショパール時計コピー,フェラーリ時計コピー,グラハム 時計コピー,ハリー ウィンストン時計コピー等。サイトは世界一流ブランド コピー 専門店です。ぜひ一度当店の商品をお試しください。驚きと満足を保証致します。ご利用をお待ちしております。[/url]

  2. A good tutorial. It will help retain visitors on site when they download files. But I really think that you could use regex instead and open all type of file downloads in new links.

    Still a good tutorial 🙂

  3. Seriously, escape your comments or classify which html will be shown in the final comments..

    I was trying to demonstrate the use of the “download” attribute for the anchor link, which is way better than this Javscript nonsense.

Leave a Reply

You must be logged in to post a comment.

Want to learn more about Javascript?

Learn how to use JavaScript to add interactivity to websites.

Learn more