Customized Documents Folder Web Part

                 

 
Special Edition Using Microsoft SharePoint Portal Server
By Robert  Ferguson

Table of Contents
Chapter  16.   Using WebDAV Protocol to Create Web Parts


In this section, we are going to use the WebDAV PROPFIND method to create a Web Part from the content of the Documents folder in the Document Library dashboard. Figure 16.4 shows the final form of the Web Part.

Figure 16.4. Documents Folder Web Part.

graphics/16fig04.jpg

This Web Part retrieves all the subfolders and some properties of documents in the Documents folder of the SPSBook workspace, and applies different XSLT files to present them in a tree view format, as you see in Figure 16.4.

This Web part uses three small images, with +, -, or square icons in front of each item. You can click on + to expand or “ to collapse a node in the tree, and a square sign represents nodes without children. At the leaves of the tree, you will see the display name of documents, which are in the form of hyperlinks . To see the document in your dashboard, you can click on the name of the document.

Using this Web Part, users will be able to navigate through lists of folders to locate and view the content without leaving the home dashboard.

Let's walk through the code and see what the major building blocks of this Web Part are.

Using PROPFIND to Query the /Documents/ Folder

Along with the PROFIND that is identified in the request header is following line:

 DAVRequest.open "PROPFIND", strURL, False, strUser, strPassword 

We send the list of properties that we want to retrieve in the form of XML, as shown in Listing 16.12.

Listing 16.12 The Body of the Request That Is Sent to the Web Server in XML Format
 <?xml version='1.0'?> <D:propfind xmlns:D='DAV:' xmlns:o='urn:schemas-microsoft-com:office:office'>     <D:prop>         <D:displayname/>         <D:href/>         <D:getlastmodified/>         <D:isfolder/>         <D:iscollection/>         <D:haschildren/>         <D:uid/>         <D:parentname/>         <o:author/>         <o:title/>     </D:prop> </D:propfind> 

To retrieve all subfolders and documents up to the last leaf of the Document folder, we use the infinity value for the depth in the request header, and send the request.

 DAVRequest.setRequestHeader "Depth", "infinity"  DAVRequest.send strXMLRequest 

Then we create a DOMDOCUMENT object to store the response in the xmlBody object, as shown here:

 Set xmlBody = CreateObject("MSXML2.domdocument")  xmlBody.async = False xmlBody.load DAVRequest.responseXML 

Now we have all the contents, and we just need to reformat them and present them.

Using XSLT to Transform the Response to XML

For the purpose of simplification, I have used two different XSL files. The first XSL file does some cleaning, ordering, and adds some required elements for tracking parent/child relationships. The second XSL file uses these additional elements and converts the new XML document to an HTML format that is represented in the Web Part.

Let's look at some of the main elements of this XSL file (xslt41.xsl).

We create a new root for the new XML file as <content>, apply a template for all elements with status code 200 (OK), and sort all the elements based on their URL as defined in the href property. Listing 16.13 shows the code:

Listing 16.13 The Code Segment of XSL to Filter Only the Responses That Have Status Code 200 (OK)
 <content> <xsl:apply-templates select="a:multistatus/a:response/a:propstat[a:status='HTTP/1.1 200 graphics/ccc.gif OK']"> <xsl:sort select="a:prop/a:href"/> </xsl:apply-templates> </content> 

First of all, because we are trying to retrieve a wide range of properties, we will see <a:status>HTTP/1.1 404 Resource Not Found</a:status> in the returned initial XML document. The reason for 404 error codes arises from the fact that folders and documents in the WSS have different schemas and properties, so when we try to retrieve properties that are defined in the request body (Listing 16.12), those properties will not be found in WSS. Then through XSL, we can filter out those elements by the following code line in the XSL file:

 select="a:multistatus/a:response/a:propstat[a:status='HTTP/1.1 200 OK']"> 

One additional element that we have included is <filetype>, which represents the type of document, based on their extensions (such as DOC, HTM, XLS).

 <filetype>    <xsl:variable name="filetype">   <xsl:value-of select="a:displayname"/>   </xsl:variable>   <xsl:value-of select="substring-after ($filetype, '.')"/> </filetype> 

The other element that we added is the position of each element in the XML document, and this is accomplished through

 <posit>   <xsl:value-of select="user:folderh()"/> </posit> 

where folderh() is a user-defined function shown in the following code, and returns a sequential number for each element.

 var ii = 0;  function folderh() {     ii += 1;     return (ii); } 

The other task of this XSL file is assigning a value for each element in the hierarchical XML document, so we can create the appropriate tree. This element is called <level>. For calculating the level of each element, I have used the flevel function, which accepts the parent name of the element, and determines the level of the specific folder or document based on number of "/" occurrences in the URL.

 <level>     <xsl:value-of select="user:flevel(concat(a:parentname,' '))"/> </level> function flevel(a) {     var cnt = 0;     var StrIndex = a.match(/\//g);     cnt = StrIndex.length-4;   return (cnt); } 

Reformatting XML Documents to HTML Format

The second XSL file has two main client-side JavaScript functions:

The addheading() function adds a dynamic HTML function to the client for managing expand and collapse of the nodes in the tree view. The second function is indentCategory(), which provides the appropriate indentation for each element in the tree. The amount of the indentation is determined based on the level and type of the element (folder or document).

NOTE

Based on the file type of documents, I have assigned an image file that represents the file type. For example, if a file is MS Word with the DOC extension, a Word icon will be shown. In each SPS workspace, there is a subfolder called DocTypeIcons, which is located in the hidden portal/resources folder. This subfolder has most images that are used for the presentation of different document types. The paths for the images used in the Documents Web Part are relative paths that point to the DocTypeIcons subfolder.


You can find the complete source code of this Web Part and related XSL files at the end of this chapter.

Listing 16.14 Xslt41.xsl File
 '--------------------------------------------------------------- <?xml version="1.0"?> <xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn: graphics/ccc.gif schemas-microsoft-com:xslt" xmlns:a="DAV:" xmlns:d='urn:schemas-microsoft-com:office: graphics/ccc.gif office' xmlns:user="http://www.compaq.com/userfunctions" version = "1.0">   <msxsl:script language="JavaScript" implements-prefix="user">     var ii = 0;     function folderh() {         ii += 1;         return (ii);     }     function flevel(a) {         var cnt = 0;         var StrIndex = a.match(/\//g);         cnt = StrIndex.length-4;       return (cnt);     }   </msxsl:script> <xsl:output method="xml" omit-xml-declaration="yes" indent="no" /> <xsl:template match="/"> <content> <xsl:apply-templates select="a:multistatus/a:response/a:propstat[a:status='HTTP/1.1 200 graphics/ccc.gif OK']"> <xsl:sort select="a:prop/a:href"/> </xsl:apply-templates> </content> </xsl:template> <xsl:template match="a:propstat">    <xsl:for-each select="a:prop">       <xsl:variable name="status">       <xsl:value-of select="a:status"/>       </xsl:variable>       <xsl:element name="folder">       <xsl:attribute name="id">       <xsl:value-of select="a:uid"/>       </xsl:attribute>     <foldername>       <xsl:variable name="target">       <xsl:value-of select="a:href"/>       </xsl:variable>       <xsl:value-of select="substring-after ($target, 'Content/')" />     </foldername>     <posit>      <xsl:value-of select="user:folderh()"/>     </posit>     <filetype>       <xsl:variable name="filetype">       <xsl:value-of select="a:displayname"/>       </xsl:variable>       <xsl:value-of select="substring-after ($filetype, '.')"/>     </filetype>     <displayname><xsl:value-of select="a:displayname"/></displayname>     <href><xsl:value-of select="a:href"/></href>     <isfolder><xsl:value-of select="a:isfolder"/></isfolder>     <iscollection><xsl:value-of select="a:iscollection"/></iscollection>     <haschildren><xsl:value-of select="a:haschildren"/></haschildren>     <level>        <xsl:value-of select="user:flevel(concat(a:parentname,' '))"/>     </level>     <title><xsl:value-of select="d:title"/></title>     <author><xsl:value-of select="d:author"/></author>     <parentname><xsl:value-of select="a:parentname"/></parentname>     <getlastmodified><xsl:value-of select="a:getlastmodified"/></getlastmodified>     </xsl:element> </xsl:for-each> </xsl:template> <xsl:template match="a:href"> </xsl:template> </xsl:stylesheet> 
Listing 16.15 Xslt42.xsl File
 <?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="uri:xsl">     <xsl:script><![CDATA[ function addheading() { var heading = ""; heading +="        function makedisplayed(a, b, c) \n"; heading +="        { \n"; heading +="           if (a.style.display=='none'){\n"; heading +="                a.style.display='';\n"; heading +="                b.style.display='';\n"; heading +="                c.style.display='none';\n"; heading +="            }\n"; heading +="            else {\n"; heading +="                a.style.display='none';\n"; heading +="                b.style.display='none';\n"; heading +="                c.style.display='';\n"; heading +="            }\n"; heading +="        }\n"; return heading; }     ]]</xsl:script> <xsl:template match="/">     <HEAD>     <SCRIPT LANGUAGE='JavaScript'>     <xsl:eval>addheading()</xsl:eval>     </SCRIPT>     </HEAD>         <TABLE>             <xsl:for-each select="content">                 <xsl:apply-templates match="folder" />             </xsl:for-each>         </TABLE> </xsl:template>     <xsl:template match="folder">        <xsl:eval no-entities="true">indentCategory(this)</xsl:eval>     </xsl:template> <xsl:script><![CDATA[ var IndexOffset = 0; function indentCategory(e)    { if (e){     var href = e.selectSingleNode("href");     var dname = e.selectSingleNode("displayname");     var dfolder = e.selectSingleNode("isfolder");     var fileicon = e.selectSingleNode("filetype").text;     var currLevel = e.selectSingleNode("level").text;     var hasChildren = e.selectSingleNode("haschildren").text;     var hrefText = "";     var dnameText = "";     var dfolderText = "";     var dfolderText = dfolder.text;     var id = e.selectSingleNode("@id").text;     if (fileicon.length > 1) {       fileicon ="DocTypeIcons\" + fileicon + "16.gif";     }     else {       fileicon ="DocTypeIcons\DET16.gif";     }     var pos = e.selectSingleNode("posit").text;     pos = Math.abs(pos)+1;     var m = e.parentNode.childNodes.length     if (pos <= m){         eval('var g = e.parentNode.selectSingleNode(\"/content/folder[posit=" + pos +"]\ graphics/ccc.gif ");');         var isFolder = g.childNodes.item(5).text;         var nexthasChildren = g.childNodes.item(7).text;         var nextLevel = g.childNodes.item(8).text;     }     else {        var isFolder = 1;        var hasChildren = 0;     }     if (href){         hrefText = "href=\"" + href.text + "\" ";     }     if (dname){         dnameText = dname.text;     }     var cat = e.selectSingleNode("displayname");     if (cat){     } else {         return hrefText + " " + dnameText;     }     var catTxt = cat.text;     var spaces = "";     var retStr2 = "";     var cnt = currLevel;     var ahref = "";     for (var i=0; i<currLevel-1; i++) {         spaces += "&nbsp;&nbsp;";     }     for (var j=1; j<cnt+1; j++){         var test = ""; //"  haschildren="+hasChildren+"  isFolder"+isFolder;         if (cnt == j) {             if (1 == dfolderText) {                if (1 == hasChildren) {                   ahref = "JavaScript:makedisplayed(document.all.item(\"tr"+id+ "\"), graphics/ccc.gif document.all.item(\"m"+id+"\"), document.all.item(\"p"+id+"\"))";                   retStr2 += "<TR><TD>&nbsp;</TD>\n" +                   "<TD width=\"100%\" valign=\"top\" align=\"left\">" +  spaces +                   "<A href='"+ ahref +"'><IMG border=0 src=\"blueplus.jpg\" graphics/ccc.gif id='p"+id+"'></IMG><IMG border=0 src=\"blueminus.jpg\" style=display:'none' graphics/ccc.gif id='m"+id+"'></IMG></A>" + "&nbsp;" + dnameText +test+"</TD></TR>";                   retStr2 += "<TR  style=display:'none' id='tr"+ id +"'> <TD>&nbsp;</ graphics/ccc.gif TD><TD><TABLE>";                }                else {                   retStr2 += "<TR><TD>&nbsp;</TD>\n" +                   "<TD width=\"100%\" valign=\"top\" align=\"left\">" +  spaces graphics/ccc.gif + "<IMG border=0 src=\"empty.gif\" id='p"+id+"'></IMG>" +                        "&nbsp;" + dnameText +test+"</TD></TR>";                }             }             else {               retStr2 += "<TR><TD>&nbsp;</TD>\n" +               "<TD width=\"100%\" valign=\"top\" align=\"left\">" +               spaces  +  "<IMG align = 'center' border=0 src='" + fileicon +"'/>"                + "&nbsp;&nbsp;" +"<A " + hrefText +">"+ dnameText+test+"</A> </TD></TR>";                      if (1==isFolder && currLevel > 0 && 0==dfolderText){                          retStr2 += "</TD></TABLE></TR>";                                  }                     if ((cnt>2) && (1==isFolder) && (currLevel-1>nextLevel)){                         retStr2 += "</TD></TABLE></TR>";                     }                      if ((cnt>2) && (0==isFolder) && ( graphics/ccc.gif currLevel>nextLevel)){                         retStr2 += "</TD></TABLE></TR>";                     }               }             }                 }                if ((1==isFolder) && (1==dfolderText) && (cnt>1) && (currLevel > graphics/ccc.gif nextLevel)){             retStr2 += "</TD></TABLE></TR>";                            }         return retStr2;         } else {             return "";         }     } ]]</xsl:script> </xsl:stylesheet> 
Listing 16.16 Function GetContent()
 Function getContent(XML) Dim strServer Dim strWorkspace Dim strFolder Dim strURL Dim strUser Dim strPassword Dim DAVRequest Dim strXMLRequest strServer = "dianatr" strWorkspace = "spsbook" strFolder = "Documents" strUser = "dianatr0\spsuser" strPassword = "spspw" strURL = "http://" + strServer + "/" + strWorkspace + "/" + strFolder strURL = Replace(strURL, " ", "%20") strXMLRequest = "" + _  "<?xml version='1.0'?>" + _  "<D:propfind xmlns:D='DAV:' xmlns:o='urn:schemas-microsoft-com:office:office'>" + _  "<D:prop>" + _  "<D:displayname/>" + _  "<D:href/>" + _  "<D:getlastmodified/>" + _  "<D:isfolder/>" + _  "<D:iscollection/>" + _  "<D:haschildren/>" + _  "<D:uid/>" + _  "<D:parentname/>" + _  "<o:author/>" + _  "<o:title/>" + _  "</D:prop>" + _  "</D:propfind>" Set DAVRequest = CreateObject("MSXML2.xmlhttp") DAVRequest.open "PROPFIND", strURL, False, strUser, strPassword DAVRequest.setRequestHeader "Content-Type", "text/xml; charset=""UTF-16""" DAVRequest.setRequestHeader "Depth", "infinity" DAVRequest.send strXMLRequest Set xmlBody = CreateObject("MSXML2.domdocument") xmlBody.async = False xmlBody.load DAVRequest.responseXML Set displayss4 = CreateObject("MSXML2.domdocument") displayss4.async = False displayss4.Load "E:\Projects\SharePointBook\Chapter 16\xslt41.xsl" strBody = xmlBody.transformNode(displayss4) Set xmlBody42 = CreateObject("MSXML2.domdocument") xmlBody42.async = False xmlBody42.loadxml strBody Set displayss42 = CreateObject("MSXML2.domdocument") displayss42.async = False displayss42.Load "E:\Projects\SharePointBook\Chapter 16\xslt42.xsl" strBody = xmlBody42.transformNode(displayss42) getContent = strBody End Function 

                 
Top


Special Edition Using Microsoft SharePoint Portal Server
Special Edition Using Microsoft SharePoint Portal Server
ISBN: 0789725703
EAN: 2147483647
Year: 2002
Pages: 286

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net