Home > Development > Open PDF files from a Document Library in a New Window

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

About these ads
  1. Oscar
    February 2, 2012 at 15:02 | #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 !!

    • February 10, 2012 at 18:36 | #2

      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

  2. GregR
    March 27, 2012 at 21:45 | #3

    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?

    • March 27, 2012 at 22:22 | #4

      Hi Greg,
      Which version of SharePoint are you using? Do you see any JavaScript errors in the status bar?

      Simon

  3. Michael Hutcheson
    April 30, 2012 at 12:28 | #5

    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

    • June 6, 2012 at 20:31 | #6

      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

    • June 10, 2012 at 20:39 | #7

      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

      • Michael Hutcheson
        June 15, 2012 at 15:49 | #8

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

      • June 15, 2012 at 18:34 | #9

        Hi Michael
        No problem look forward to hearing how you get on.
        Regards
        Simon

      • Murray
        June 21, 2012 at 02:47 | #10

        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?

      • June 21, 2012 at 08:32 | #11

        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

  4. June 10, 2012 at 20:31 | #12

    Reblogged this on iThink SharePoint and commented:

    Updated with SharePoint 2010 Version of Script

    • Murray
      June 26, 2012 at 08:38 | #13

      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…

  5. Juli Reid
    August 21, 2012 at 16:07 | #14

    Can this script be modified to work with xml files?

    • August 23, 2012 at 09:02 | #15

      Juli,
      I dont see why not though it depends on the application that is going to display the XML files. What are you looking to do?

      Regards
      Simon

  6. Mahesh
    September 12, 2012 at 12:29 | #16

    HI Simon,

    The download link for 2010 is broken. Could you please confirm and correct the same?

    THanks
    Mahesh

    • September 17, 2012 at 10:28 | #17

      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

  7. May 1, 2013 at 16:42 | #18

    Hmm is anyone else having problems with the images on this blog loading?
    I’m trying to determine if its a problem on my end or if it’s the blog.
    Any suggestions would be greatly appreciated.

    • May 2, 2013 at 13:23 | #19

      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

  1. No trackbacks yet.

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

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: