Open PDF files from a Document Library in a New Window

Update: 10th June 2012

A few people have posted comments about the script not working for SharePoint 2010. This code was built for SharePoint 2007. However I have been through the code and an updated version can be found below.

Apologies that it has taken a while to respond.

The SharePoint 2010 Code version works slightly differently and uses the jQuery Live method and JavaScript OnMouseOver event to update the PDF’s a tags.

Introduction

One of our clients wanted a way to ensure that Adobe PDF’s did not open in the current browser window.

By default a PDF opened into Adobe Acrobat will open in the current browser window.

This presents a usability problem as user’s lose the reference to the site they were in also other applications, such as Word and Excel, do not behave in this way.

How Acrobat opens a document is controlled within the Acrobat client. Unfortunately to change this through a mechanism such as Group Policy is not a simple task and hence did not meet their timescales.

Just so you know, Acrobat’s PDF browser behaviour is adjusted here :-

  • Open Acrobat Reader (C:\Program Files (x86)\Adobe\Reader 10.0\Reader\acrord32.exe)
  • Click Edit->;;Preferences
  • Choose Internet (down the left-hand side)
  • Unselect “Display PDF in Browser”
  • Click OK

acrobat-browsersetting

;

Unfortunately this was not possible for the client, so I started to look at alternative solutions. First thing is that the client wanted something that was quick (the fix was required in a day) as they had committed to launching the internal site quickly. The requirement was for a single page and therefore the solution did not need to scale.

The idea that I came up with was to use jQuery to find the PDF hyperlinks on the page and then add a target attribute with a value of “_new”.

This was pretty straightforward and using a content editor web part the JavaScript was quickly added to the page to prove the approach.

simpleopeninnewwindowjscode

;

Of course its never as simple as that and when this approach was tried then it worked well for a standard document library but the page had views that were grouping content by certain columns and the jQuery could not find the ; link to bind to.

When the grouping function is used on a view then the content within a group is lazy loaded using JavaScript functions within the init.js SharePoint library. So therefore the jQuery will not find the ; tags because they don’t exist yet.

One option I thought of was to try and run the code as late as possible. So I starting to look into how SharePoint JavaScript function were called. One thing I had noticed was how the content within a group was loaded in after the document had loaded.

Looking at the SharePoint JavaScript files I found init.js. SharePoint seems to add functions to an array called ‘_spBodyOnLoadFunctionNames’ using the function _spBodyOnLoadFunctionNames.push(). This array is passed into a function called “ProcessDefaultOnLoad()” within init.js. These functions are then called one at a time by looping through the array.

So another line within the $(document).ready() function was added :-

_spBodyOnLoadFunctionName.push(refreshPDFLinks());

However, this still didn’t work.

The grouping function when it expands a node updates the html to display these links to the various documents, so I wanted to find a way to bind to an event which would be called when changes to the html were made. After some more research I couldn’t find a way to throw an event which would work in IE and Firefox.

I then thought we’ll why don’t we delay the call to look for the PDF links by a second or two. The important thing was that the delay was an asynchronous call that did not block the other scripts from running.

In the end the setTimeout() JavaScript function was used. This function was bound to all the expanders for the document library. Fortunately with jQuery the binding was pretty straightforward with the line:-

$(documentLibExpGroup).bind('click', function(){
refreshPDFLinkTimeOut = setTimeout("refreshPDFLinks()",1500);
});

This approach works though it is not great for the following reasons :-

  • it is not scalable and need to be added to each page that the functionality is required for.
  • the timeout needs to be long enough to load the PDFs but not so long so that the link is not updated in time.

Anyway with those caveats in mind here is:-

The SharePoint 2007 Source Code.

<script src="http://ajax.microsoft.com/ajax/jQuery/jquery-1.4.4.min.js">
</script>
<script language"javascript" type="text/javascript">
/* PDF Link to new window function */
$(document).ready(function () {

    var refreshPDFLinkTimeOut=null;
    //bind function to document library expand events
    bindToDocumentLibraryEvents();
    //_spBodyOnLoadFunctionNames.push(&quot;refreshPDFLinks&quot;);
    refreshPDFLinks();
});

function bindToDocumentLibraryEvents() {

    var documentLibExpGroup=$("a[onclick*='ExpCollGroup']");
    $(documentLibExpGroup).bind('click', function(){
        refreshPDFLinkTimeOut = setTimeout("refreshPDFLinks()",2000);
    });
    alert"Bound to " + documentLibExpGroup.length + " Document Lib Group Switch");
    return true;
}

function refreshPDFLinks() {
    fixPDFUrls();
    //var pdfTags = getPDFUrls();
    //updatePDFUrls(pdfTags);
    //alert(&quot;Found &quot; + pdfTags.length + &quot; PDF Links&quot;);
    return true;
}

function getPDFUrls() {
    var pdfUrlTags = $"a[onclick*='DispEx'][onfocus*='OnLink'][href*='pdf']");

    var fixTags = new Array();
    for (var i = 0; i <;; pdfUrlTags.length; i++) {
            fixTags.push($(pdfUrlTags[i]));
    }

    return fixTags;
}

function fixPDFUrls() {
    var pdfUrlTags = $("a[onclick*='DispEx'][onfocus*='OnLink'][href*='pdf']");
    alert("Found " + pdfUrlTags.length + " PDF Links");
    $(pdfUrlTags).live('click', function() {updatePDFUrls(this);});
    return true;
}

function updatePDFUrls(pdfUrlTags) {
    for (var i = 0; i <;; pdfUrlTags.length; i++) {
        $(pdfUrlTags[i]).attr('target','_new');
    }

    return true;
}

function updatePdfTargetUrl(e) {
    $(e).attr('target','_new');
    return false;
}

/* PDF Link to new window function */
</script>

The SharePoint 2010 Source Code

<script type="text/javascript" src="http://ajax.microsoft.com/ajax/jQuery/jquery-1.7.1.min.js">
</script>;
<script type="text/javascript" language="javascript">
/*

/* PDF Link to new window function */
$(document).ready(function () {

    var refreshPDFLinkTimeOut=null;
    //bind function to document library expand events
    bindToDocumentLibraryGroupByEvents();
    refreshPDFLinks();
});

function bindToDocumentLibraryGroupByEvents() {

    var documentLibExpGroup=$("a[onclick*='ExpCollGroup']");
    $(documentLibExpGroup).live('mouseover', function(event){
        refreshPDFLinkTimeOut = setTimeout("refreshPDFLinks()",2000);
    });
    //alert("Bound to " + documentLibExpGroup.length + " Document Lib Group Switch");
    return true;
}

function refreshPDFLinks() {
	fixPDFUrls();
    return true;
}

function fixPDFUrls() {
    var pdfUrlTags = $"a[onclick*='DispEx'][onfocus*='OnLink'][href*='pdf']");
    $(pdfUrlTags).live('mouseover', function (event) { updatePdfTargetUrl($(this)); });
    return true;
}

//updates the tag, adding the _new property to the target to open new window
// and disabling the SharePoint DispEx onclick function to stop the pdf from being opened in the current browser window.
function updatePdfTargetUrl(e) {
    $(e).attr('target', '_new');
    $(e).prop('onclick', null).attr('onclick',null);
	return false;
}

/* PDF Link to new window function */
</script>

Usage

To use this piece of JavaScript do the following:-

  • Download the Source code JavaScript file
  • Browse to the SharePoint page that you wish to add the PDF functionality to.
  • Edit the SharePoint Page
  • Add a Content Editor Web Part to the page
  • Edit the Content Editor Web part and open its source view
  • Open the source code file, copy the contents of the javascript
  • Paste the contents in the Content Editor Web part’s source.
  • Save the Web part and the Page
  • Test out the functionality.
  • If nothing happens then check that the jQuery library can be accessed as it uses the Microsoft AJAX site to get the appropriate version.

Links

29 Comments

  1. Great !!!

    But the pdf is still open in the sharepoint window, and of course in a new window . I have change a little bit your code to solve this issue:

    function updatePDFUrls(pdfUrlTags) {
    for (var i = 0; i < pdfUrlTags.length; i++) {
    $(pdfUrlTags[i]).removeAttr('onclick').attr("target","_blank");
    }

    return true;
    }

    This new code works fine for me.

    Thks !!

    Reply

    1. Thanks for your comments and taking the time to post your alternative script. I dont remember the script opening two version of the PDF but then I haven’t tested this in SP2010 for a while!
      I will take a look at your change over the weekend.

      Regards
      Simon

      Reply

  2. Why is such a basic feature not part of the standard options?

    I’ve followed the discussion above and have the jquery file and the script in a ‘ScriptLibrary’ folder but when I go into my document library and double-click on a PDF it still opens in the same window.

    What am I missing?

    Reply

  3. Hi All
    I can’t get this to work in in SP 2010 when PDF’s are grouped. Works fine when not grouped. Has anyone been able to achieve this?

    Regards,
    Michael

    Reply

    1. Hi Michael,
      Thanks for taking the time to post this issue. I haven’t looked at the code recently and have a bit of time this week and will look at the approach that I have taken for SharePoint 2010. This code was originally released for SharePoint 2007. I will update the post and be in touch when I have updated the code for SharePoint 2010.

      Regards
      Simon

      Reply

    2. Hi Michael,
      I have taken a look at this for SharePoint 2010 and have updated the source code to work slightly differently now. Can you try again with the new version and let me know how you get on.

      Regards
      Simon

      Reply

      1. Hi Simon,
        Thanks for looking into this – I will take a look and let you know.
        Regards,
        Michael

      2. Hi Simon – where is this new code you speak of? And one comment you made has me confused:
        “If nothing happens then check that the JQuery library can be accessed as it uses the Microsoft AJAX site to get the appropriate version.”
        My question is HOW do I do this – the code above doesn’t work for me so maybe this is the issue?

      3. Hi Murray
        There are two versions of the code the older SharePoint 2007 version and the new SharePoint 2010 version.
        If you re read the post you will see that the two different code bases are marked.

        The code uses a copy of the jQuery library which is hosted by Microsoft on their Ajax site.
        This is the line that has the line

        If the machine that you are trying this out on is on a corporate network with strict policies then the machine might not be able to access the site.
        If that’s the case then you will need to store a copy of the jQuery on your SharePoint farm. I suggest this is a path under the /_layouts folder such as /_layouts/jquery.js so that it can be shared. The script link should then be updated to point to that local location.

        Hope that helps

        Regards
        Simon

    1. Hi Simon – did you get my email to simon@ithinksharepoint I sent last week? I had to send there as I could not paste screenshots into this forum…

      Reply

    1. Hi Mahesh,
      Thanks for taking the time to let me know. Looks like its back up, looks like there was an issue with my other hosting provider but all up and running now. Let me know if you need any further help.

      Regards
      Simon

      Reply

    1. Hi thanks for taking the time to post a comment about the issue with images. When I checked last night it all seemed to be working fine.
      Please let me know if you are still having troubles.

      Regards
      Simon

      Reply

    1. Hi,
      do you mean document sets? I haven’t tried the script on those. I would imagine it would work with a bit of tweaking.
      Can’t promise that I will look immediately but will try and take a look over the next couple of weeks.
      Regards
      Simon

      Reply

      1. Yes Simon, I am looking for document sets also.
        Present script is not working for files in document sets. I will be waiting for new script.

        Regards,
        Venkat

      2. Hi Venkat,
        Like I said in previous comment, you might be waiting a while. Why not have a go and see if you can tweak the script to what you want?

        Regards
        Simon

  4. Hi Simon,

    Thanks a lot for this excellent post. I was wondering if you could tweak the script to work with SharePoint 2013 ?

    Thanks
    Paul

    Reply

  5. A small tip, if you’re using JQuery version over 1.7, method “.live()” was deprecated for versions over 1.7. JQuery suggest use “.on()” method instead of.

    Reply

  6. Hello, I am using SP2013 and got a Document Library filled up with .docx and .pdf > currently the docx are opening either in edit or read mode but the pdf opens straight in the current browser – which is ok if the library is opened as a full page but I use the dialog box option and is very irritating. I tried the code but did not work in my case 😦 suggestions?

    Reply

Thoughts? Comments about this post? Please leave them here..

This site uses Akismet to reduce spam. Learn how your comment data is processed.