Preview for PDF Documents in Search Results

Often, while inspecting the results of a search, glancing at a preview of the documents helps to better identify the documents wanted rather than clicking on each of them.

This article describes the steps to enable document preview functionality for PDF documents in a standard search in SharePoint 2010. Ultimately, the result will look similar to this:

preview-1

Above you are seeing a customized search webpart that injects a container in the default XSLT which will hold the search preview, rendered at runtime. The webpart supports properties such as:

  • width and height
  • various PDF-related properties (show scrollbars, show toolbars, show navigation pane, show message bar)
  • whether to display the preview inline or in a separate dialog box

On the client side, we need the following:

  • jQuery, needed to alleviate the work in javascript
  • jQuery UI, for the dialog box display
  • PDFObject, for the run-time PDF rendering

Let’s go through all the components, shall we?

The first thing is to register the client-side dependencies. For the purpose of this demonstration, the javascript references are added through the webpart code, but you can choose any other means to inject the references in the page, such as a delegate control or direct referencing from the master page or page layout.

        /// <summary>
        /// Runs when the page is loaded
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            //register all the required components for client-side rendering
            Page.ClientScript.RegisterClientScriptInclude("jQuery", "/_layouts/SearchPreviewPrototype/jquery-1.7.1.min.js");
            Page.ClientScript.RegisterClientScriptInclude("jQueryUI", "/_layouts/SearchPreviewPrototype/jquery-ui-1.8.18.custom.min.js");

            Page.ClientScript.RegisterClientScriptInclude("pdfObject", "/_layouts/SearchPreviewPrototype/pdfobject.js");
            Page.ClientScript.RegisterClientScriptInclude("SearchPreview", "/_layouts/SearchPreviewPrototype/clientscript.js");

            //css link to jQuery's "lightness" theme
            HtmlLink css            = new HtmlLink();
            css.Href                = "/_layouts/SearchPreviewPrototype/themes/ui-lightness/jquery-ui-1.8.18.custom.css";
            css.Attributes["rel"]   = "stylesheet";
            css.Attributes["type"]  = "text/css";
            css.Attributes["media"] = "all";
            Page.Header.Controls.Add(css);
        }

The webpart’s sole task is to alter the original XSL property value and inject the container required for the preview. The container definition is the following:

        /// <summary>
        /// Returns the xml node to be injected in the original transformation.
        /// </summary>
        private XElement PreviewNode
        {
            get
            {
                return new XElement("div", new XAttribute("id", "{concat($currentId,'_preview')}"),
                                           new XAttribute("target", "previewBox"),

                                           new XAttribute("scrollbars", Convert.ToInt16(ShowScrollBars)),
                                           new XAttribute("toolbars",  Convert.ToInt16(ShowToolBars)),
                                           new XAttribute("statusbar",  Convert.ToInt16(ShowStatusBar)),
                                           new XAttribute("documentbar",  Convert.ToInt16(ShowDocumentMessageBar)),
                                           new XAttribute("navigationpane", Convert.ToInt16(ShowNavigationPane)),

                                           new XAttribute("previewwidth", PreviewBoxWidth),
                                           new XAttribute("previewheight", PreviewBoxHeight),

                                           new XAttribute("DialogPreview", Convert.ToInt16(DialogPreview)),

                                           new XAttribute("currentID", "{$currentId}"), 

                                           //note that {url} is a node present in the source xml file fed to the webpart
                                           new XAttribute("fileUrl", "{url}"));
            }
        }

While the actual XSL injection is performed through an override of the original base property:

 /// <summary>
        /// The Xsl used for the transformation of results.
        /// </summary>
        /// <remarks>The custom node is injected at runtime</remarks>
        public override string Xsl
        {
            get
            {
                //automatically called after OnLoad
                if (string.IsNullOrEmpty(base.Xsl))
                    return string.Empty;

                try
                {
                    XDocument xslt = XDocument.Parse(base.Xsl);
                    //will insert the container right after the "Authors" row 
                    XElement metadataNode = (from divNode in xslt.Descendants("div")
                                             let classAttribute = divNode.Attribute("class")
                                             where classAttribute != null && classAttribute.Value == "srch-Metadata2"
                                             select divNode).FirstOrDefault();

                    if (metadataNode != null)
                    {
                        //found the matching node
                        metadataNode.Add(PreviewNode);
                    }

                    return xslt.ToString();
                }
                catch (Exception ex)
                {
                    //implement your own exception handling here
                    return base.Xsl;
                }
            }
            set
            {
                base.Xsl = value;
            }
        }

The code above doesn’t require the customization of the initial XSL property value, but it supports any custom search results achieved through a custom XSL, since it injects the preview containers at runtime, thus decoupling the preview functionality from any potential XSL customizations.

preview-2

The additional properties exposed by the webpart allow further customization of the preview container itself and PDF-specific parameters.

The last option allows the file preview to be rendered in a dialog box which can be a big performance boost since it will get the PDF file from the server on demand, rather than all the files at once.

The solution offers full support for jQuery UI theming and CSS customizations.

Right click to download The SPAW PDF Preview and rename the file in .wsp

Questions and suggestions are welcome!

About these ads

, ,

  1. #1 by Amber on 18 July 2013 - 22:18

    Can you please update the code for jqueryui1.10.3?

Leave a Reply

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

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: