Friday 12 April 2013

Adding page-specific icons to a SharePoint page


I was building a news function for SharePoint 2007 that is a bit more sophisticated than the OOTB Announcements list. I figured I could make each news story a new page, then use Content Types to hold the metadata for each page that identify the news stories by type (ie, Business, Community, HR), the position they'd appear on on the Home page and whether they were a critical story that needed to be held in a DVWP listing so it wouldn't drop off people's radar.

The reason I wanted to use Content Types (as opposed to simply adding columns to the Pages directory) was I wanted the end-users to be able to set the metadata values on the same page that they would add the headline, summary, body text and picture on.
This arrangement allows the end-users to set
metadata for the news detail page that determines
how the news articles will appear in other web parts
around the site

All this seemed pretty easy ... and I don't want to cover the process here in detail, as you can find how to do this on any number of other sites.


But a problem arose when I had a further requirement to set icons for each news story depending on which company values related to the subject matter of the story.

So I set up a Content Type for the icons ("StrategicLevers") and made it a tickbox choice so the end users could tick a box to make that icon appear on the page.

Next I added a Data View Web Part to the page template that looked at the Pages directory where the news detail pages would be stored, and called the values from the Content Type I'd already set up to hold the values for the icon images.

Then I had to find a way of identifying the current page in the DVWP that would display the correct icons. This at first appeared to be a pretty easy task. I would just use the in-built SharePoint parameter for the page URL called, with customary Microsoft creativity, "PageURL".

So I set a binding up for the PageURL parameter and then called the parameter further down the page, like this:

<ParameterBinding Name="PageURL" Location="Postback;Connection;CAMLVariable/>

in the ParameterBindings section, then added the Parameter further down the page, like this: 

<xsl:param name="PageUrl" />

at the top of the StyleSheet section.

After that, you should be able to use the PageURL Parameter return a value for the current page within the page ... 

In my case I was going to use the parameter to filter out all the values that weren't the current page. So I set up a a test using Choose/When, like this:

<xsl:choose>
<xsl:when test="@FileRef = $PageURL">
</xsl:when>
</xsl:choose>

What this does is that the DVWP iterates through all the pages in the Pages directory, comparing each page URL with the current page's URL and only displaying when there's a positive match. So far, so good ... except this is the point where I should have checked what value is being returned by this filtering process, perhaps by inserting:

<xsl:value-of select="@StrategicLevers">

to see what value came back. But I didn't. I pressed on and started adding the Choose/When statements that would display the icons according the values set in the StrategicLevers Content Type.

The way I wanted the function to work was that the icon would appear greyed out if the tickbox was unticked and in full effect if the box was ticked. So I did this:

<xsl:choose>
<xsl:when test="contains(@StrategicLevers, 'Solutions')">
<img src="/newsImgs/4_Creative_on.png"/>
</xsl:when>
<xsl:otherwise>
<img src="/newsImgs/4_Creative_off.png"/>
</xsl:otherwise>
</xsl:choose>

for each icon. In this case, "Solutions" is the value of that icon's tickbox. You'd have to change that value for each icon.

Next step, do a test. So I saved the template then opened a news detail page in my browser and ticked a couple of the icon tickboxes, but all the icons remained stubbornly greyed-out.

What followed was two days of frustrating trouble-shooting until I stumbled across a solution.

Even though I could see a value for the PageURL parameter in the Design view of Sharepoint Designer (SPD), the value wasn't displaying in the browser. I couldn't think of any reason why that would be so, but in the end accepted that it was so and started looking for another way to call the value for the current page so I could use it as a filter value.

By blind luck, I found a mention on Marc Anderson's blog about a Server variable that did the same thing.

So I got rid of the PageURL parameter binding and replaced it with this one:

<ParameterBinding Name="PageAddr" Location="ServerVariable(URL)" DefaultValue=""/>

...replaced the parameter further down the page with the new one, like this:

<xsl:param name="PageAddr" />

... and amended the parameter name in the first Choose/When routine:

<xsl:choose>
<xsl:when test="@FileRef = $PageAddr">
</xsl:when>
</xsl:choose>

Success! This worked fine in the browser, but perversely, didn't work at all in SPD Design view ... I still have no idea why Microsoft thought this was a good idea.