Friday, September 9, 2011

Direct link to a certain version of a document

In an order form I want to show a link to a document that contains the standard specifications of the goods. These specifications will change once in a while so it is important to know on what version of this document the order was based.
I can make use of a standard hyperlink field to add the shortcut to the document, that is the current version at that time. After the order is processed and archived to read-only, I want to be able to click the link to open the right version of the document, even though there are newer versions of it. The url of prior versions of a document is like: site/_vti_history/512/Documents/Specifications.pdf
The version is multiplied with the factor 512, so version 1.0 is 512, 2.0 is 1024, etc. With this knowledge I am able to reconstruct the url of the right version if I save the version number as well. But what if this version is still the current version? The reconstructed url doesn't work, because it should be: site/Documents/Specifications.pdf
Within a HTML <IMG> tag I can make use of the onError event to switch over to an alternative source, like I described in my part about adding icons to the refinement panel in SharePoint 2010. Unfortunately this trick will not work with href to a document. So I searched for an other way, and I found one: Checking if a file(url) exists using Javascript (AJAX). So all I have to do is turn the url into something like: href=javascript:check_file(url). The javascript code will then redirect me to the valid path of the document.

<script language="javascript" type="text/javascript">

http_check = getHTTPObject();

function getHTTPObject(){ 
  //Create a boolean variable to check for a valid Internet Explorer instance.
var xmlhttp = false;
//Check if we are using IE.
 try {
  //If the Javascript version is greater than 5.
  xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
 } catch (e) {
  //If not, then use the older active x object.
  try {
  //If we are using Internet Explorer.
  xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
 } catch (E) {
//Else we must be using a non-IE browser.
xmlhttp = false;
 }
}
//If we are using a non-IE browser, create a javascript instance of the object.
 if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
 xmlhttp = new XMLHttpRequest();
 }
  return xmlhttp;
}

function check_file(path_of_file) 
{
    http_check.open("HEAD", path_of_file);
    http_check.onreadystatechange = handleHttpResponse_check;
    http_check.send(null);

    function handleHttpResponse_check()
    {
        if(http_check.readyState == 4){
            if (http_check.status == 200) {
                window.open(path_of_file);
            }else if (http_check.status == 404) {
                window.open(other_path_of_file);
            }
        }
    }
}
</script>
With the help of a workflow after submitting the form I want to modify the value of the hyperlink field to include the part: javascript:check_file(url). This doesn't seem to work in the browser.
So I am going to use a calculated column to compose the HTML code, to be rendered by the TextToHtml script from PathtoSharePoint.

Formula:
="<a href='javascript:' onclick="&CHAR(34)&"check_file('http://www.sharepointserver.eu/site/_vti_history/"&VALUE(LEFT(DocVersion;1))*512&"/Documents/Specifications.pdf')"&CHAR(34)&">Standard specifications</a>"

The javascript code with the redirect to the alternative -fixed- url of the current version:
function check_file(path_of_file) 
{
    http_check.open("HEAD", path_of_file);
    http_check.onreadystatechange = handleHttpResponse_check;
    http_check.send(null);

    function handleHttpResponse_check()
    {
        if(http_check.readyState == 4){
            if (http_check.status == 200) {
                window.open(path_of_file);
            }else if (http_check.status == 404) {
                window.open('http://www.sharepointserver.eu/site/Documents/Specifications.pdf');
            }else {
                window.open('http://www.sharepointserver.eu/site/Documents/Specifications.pdf');
            }
        }
    }
}
Somehow the "else if (http_check.status == 404)" doesn't work for the version url, so I use the "if anything else" to redirect to the url of the current version.

Now let's modify the user interface to put all the pieces together:
Add a CEWP to the NewForm.aspx (?toolpaneview=2) of the list and enter the link to the document, so the users can open the current version to read the specs.


Lookup the version number of the document by a workflow and add the value to a hidden (Allow management of content types, set Column Settings to Hidden) text field DocVersion, that is used in the formula of the calculated column.


Add a CEWP to the DispForm.aspx and/or the list view (display the calculated column) and paste the javascripts in the Source Editor. In this way the text in the calculated column is rendered as HTML and the javascript function check_file is executed on click of the link.
In this way there will be a redirect to the valid path of the right version.