Tuesday, December 23, 2008

Adding "OpenInNewWindow" option to SharePoint Links lists

Tangent: List Templates and Site Definitions

For a super fast overview, when a new SharePoint site is created, one of the first steps you take is to select a template to build out the site. These templates are defined in the file system: C:\Program Files\Common Files\Microsoft Shared\web server extensions\60\TEMPLATE\1033. After selecting a template, SharePoint uses the ONET.XML & SCHEMA.XML file to build out the default lists and adds the default Web Parts to the homepage. The ONET.XML file also contains information about what types of lists can be created once the site has been created. It is within these site definitions and templates where you can create your own OOTB lists for sites and really make some powerful solutions.
For more information on creating your own site defintions, refer to the footnotes.[2]

Overview

So how are we going to implement this “OpenInNewWindow” feature? We’re going to do it the Microsoft recommended way:
  • Part 1: Copy an existing site defintion
  • Part 2: Modify the SCHEMA.XML file in our new site definition using CAML
Let’s get started! All my site definitions that I modify from the originals have “my” in the prefix which is the convention I’ll use in this article.

Part 1: Copy an Existing Site Defintion

This section is a very fast tutorial on how to create a new site defintiion from an existing site definition. For more information and a much more detailed walkthrough step-by-step with screenshots along the way, check out Heather’s Add a Custom List to SharePoint - a foray into CAML article.[2]
Let’s take the most straightforward and common site defintion: Team Site. Create a copy of the the Team Site site definition (C:\Program Files\Common Files\Microsoft Shared\web server extensions\60\TEMPLATE\1033\STS) and name the new folder MYSTS.
Give New Site Definition A Unique Name
Now, we need to alter the ONET.XML file for our new MYSTS site defintion so that it has a unique name in the Template Picking screen… how else do you plan to distinguish it from the existing Team Site? Open the ONET.XML file for MYSTS (C:\Program Files\Common Files\Microsoft Shared\web server extensions\60\TEMPLATE\1033\MYSTS\XML\ONET.XML), find the element (should be line #4), and change it’s Title attribute from “Team Web Site” to “myTeam Web Site”, as shown below:

ONET.XML available for download [a]
Register the New Site Definition
Now we need to tell SharePoint there’s a new site definition available to users when they create a site. This info is found in WEBTEMP*.XML files, located here: C:\Program Files\Common Files\Microsoft Shared\web server extensions\60\TEMPLATE\1033\XML. SharePoint looks at all the WEBTEMP*.XML files in the afore mentioned directory for the list of available site definitions. To tell SharePoint about our new site definition, let’s copy the one used for the “Team Web Site” (STS) site definition and modify it for our purposes. Create a copy WEBTEMP.XML and name it WEBTEMPMYSTS.XML.
Open our new WEBTEMPMYSTS.XML. You’ll see two elements as well as a handful of elements. Since we’re only going to use this new file to define only our new site definition, we can get rid of a lot the XML in this file to define one template with one configuration as follows (again, for more information on the structure of this file, refer to Heather’s article as mentioned above):

WEBTEMPMYSTS.XML available for download [b]
That’s it, we now have our new site definition created and told SharePoint to offer it in the available site definitions to pick from when creating new WSS sites. For this to take effect, run IISRESET.EXE from a command line and provision/extend a new WSS site (that’s the fun part… you have to reset IIS every time you make changes to a site definition or the WEBTEMP*.XML files). When you reach the Template Selection page, you should see our site definition listed in the available options as the following image does (notice the selected template):

Part 2: Modify the SCHEMA.XML File in Our New Site Defintion Using CAML

At this point we have our own site definition which we can customize to our heart’s content. We’re just interested in a specific list template our new site definition: the one containing the Links list. The Links list template is found in the following folder: C:\Program Files\Common Files\Microsoft Shared\web server extensions\60\TEMPLATE\1033\MYSTS\LISTS\FAVORITE.
Refer to Heather’s “SharePoint Site Definitions - Maping files to pages on a SharePoint site[2] article for a list of which folder corresponds with each list template.
The FAVORITE folder contains 5 files. The ASPX files are all used for the various pages used in this template. We’ll ignore these for now as they are outside the scope of this article. What we’re really interested in is the SCHEMA.XML file. This is where the real work begins.
For an in-depth explination of the contents of the SCHEMA.XML file, refer to the MSDN article “Customizing Templates for Microsoft Windows SharePoint Services[2] and Heather’s article “Add a Custom List to SharePoint - a foray into CAML”.[2]
Add New Field “Open In New Window”
The first thing we need is a new boolean field that we’ll use to hole the flag if the link should be opened in a new window. We do this by adding a new element in the section of the SCHEMA.XML file. Look for the line that defines the URL field (on or about line #11) that looks like this (take note the type is URL… we’ll revisit this in a second):

Let’s add a new field just after this line:

The attributes say that this field is of type boolean (the user will be presented with a checkbox), the unique ID of the Field (Name), the friendly display name, and if the field is required on this list. If a field is required, the field can’t be removed from the list.
View the New Item Form With The New Field
Save your changes, reset IIS, and open the WSS site you created using our site definition. Go into the Links list and click New Item. The form should look like this:

Go ahead and add two new records, one opening in a new window, one opening in the same window.
Add New Field to Existing Views (optional)
Now we need to add this field to existing views. Personally I wouldn’t add this field to any of the views, but if you wanted to, it’s very simple. Find the “All Links” view by searching for the opening element that defines that view. For example, search for “All Links”, this should take you down to line #156:

Within this view, there’s a element called (around line #702). It currently contains three fields. To add your new field, you’d just add a new tag and assign the Name attribute the name of your new field. Again, I’m not going to do this here.

Anytime you make chages to this file you’ll need to reset IIS to see your changes take effect.
The Problem with the URL Field Rendering
As you saw above, the URL field is of type URL. When a field of type URL is displayd, SharePoint checks to see if a description was entered for the link. If it was, it renders the URL field as description… otherwise it renders it as URL. While this is all fine and good, this poses a problem for our new field. We won’t be able to use the URL property because to open in a new window, we’d need to add in a target=”_blank” to open the link in a new window. Because the whole anchor tag is rendered by the URL type, we’ll need to roll our own implementatin via a computed field (this is how those fields that provide the roll-over drop-down edit menus in certain lists).
Add A New Computed Field
To add a new field, jump back to the top of the file, where we added the OpenInNewWindow field. Add a new element after the existing “Note” field (the Note field should be on or about line #13):

Attributes to take note of:

Attribute: Description:
Type Computed implies that this field is calculated from existing fields.
ReadOnly This marks the field as not editable by a contributor.
AuthoringInfo Friendly name when a list of fields is displayed (like in the order of the fields presented when editing a view).
Next you need to specify what fields you’re going to use within this computed value. To do this add a element with the necessary elements for each field inside the :

Adding the Rendering Instructions
Now for the big piece: the rendering instructions. Add a element just after the element. I’ll step through this in chuncks as it’s complicated for those not familiar with CAML. What you’re doing is using CAML tags to specify the resulting output.
The first part of the output will be . This is accoplished by this code:




Next we need to determine if the link should be opened in a new window or not. If it is, we need to add target=”_blank” to the anchor tag. Here’s how you do a conditional with CAML (should be fairly straightforward):






Now, close the opening anchor tag:
]]>
To add the text for the link, we need to check one of two properties: and . The WSS SDK explains the two better than I could:


» The Column element is used to return the raw data value for a particular field (as opposed to the formatted version provided by the Field element).
» The Column2 element is used in rendering a hyperlink. In Microsoft Windows SharePoint Services, hyperlinks are stored as two separate values. The actual URL value is stored in one part, and the descriptive text is stored in another. In a Link field, returns the value of the URL, and returns the descriptive text of the hyperlink.

Microsoft WSS SDK[3]
So… we need to check and see if the element has anything in it. If so, we want to use that to show the link to the user. Otherwise, we’ll just use the URL itself:





All that’s left is t he closing anchor tag:
]]>
That completes our computed field… it should now look like this:

Modified SCHEMA.XML available for download [c]
This computed field can now be used in existing or new views as you can see it’s now one of those special options in the field choser within a view settings page (it’s the last one listed in the view below: All Links):

Modify Existing Views to Use The New Computed Column
Now that we have this computed column, we need to make sure the existing views use it when displaying the links. Right now we’re concerned about two different views: the All Links view and the Summary view when the Web Part is placed in a Web Part Zone on a Web Part Page. Let’s first concentrate on the Summary view as the All Links view is a different animal. Look for the Summary view by seaching for this element (should be on or about line #86):

At the end of the element, you’ll see a element (on or about line #177). You will also notice that it contains a single element referring to the URL. Change this to our new computed field: URLNewWinLink. It should look like this:

Modified SCHEMA.XML available for download [c]
Now, save your changes, reset IIS, and refresh the homepage of the WSS site you created. Click on the link list item you added that should open in a new window and watch it work! Do the same for the one that should load in the same window. Cool huh?
One Last Finishing Touch
There’s one last finishing touch that I think should be implemented. The All Links summary view displays a special computed column that displays the drop-down edit menu when the mouse hovers over it. Right now, all links open in the same window. This computed field should be modified to open in a new window if so specified. Fortunately, we’ve already done the hard part!
Jump back to the top of the SCHEMA.XML file and find the URLwMenu element (on or about line #40). Add the OpenInNewWindow element to the element just like we did for the URLNewWinLink computed field. If you don’t do this, we won’t be able to access it within the element. Scroll down to the element where it’s starting to build the anchor tag for the link (on or about line #70). The code currently looks like this:

Original URLwMenu computed field; Modified SCHEMA.XML available for download [c]
We need to modify it to look like the following (the highlighted portion shows the new code… take note some code was removed as it was prematurely closing the opening anchor tag:

Modified URLwMenu computed field; Modified SCHEMA.XML available for download [c]
Save, reset IIS, and refresh your WSS site. Everything works!

Print this post

No comments: