In a World where everything moves, even static information needs changes. And since jQuery appeared a lot of information on the web became more interactive. (At least for developers it is way easier to implement nice graphical add-ons). For the most of us jQuery is a way to give some more user experience in the things you develop. In this first post on this blog there will be a step by step guide of how to apply jQuery to a standard SharePoint content query (in the example we will make a accordion style to a list). Examples of this in plain HTML can be found on http://jquery.bassistance.de/accordion/demo/
And a few screenshots how it will look in MOSS:


To understand the working of the ContentQuery Webpart we first have to take a look at a standard CQWP with grouping activated:
<div class="groupheader item medium">Header</div>
<div id="linkitem" class="item link-item">
<a href="#" target="" title="">Link</a>
</div>
However to use jQuery and especially the accordion function we need to tidy up the HTML a bit, and apply some minor fixes so the final result will look like:
<ul class="groupheader item medium">
<li>
Header
<ul class="item link-item">
<li>Link</li>
<ul>
<li>
<ul>
This will allow the jQuery engine to automatically hide or unhide the items within the First <ul>.
To fix this there are several changes on the itemstyle.xsl, the headerstyle.xsl and the contentquerymain.xsl, and to do so some basic experience of xHTML / CSS and xsl(t) can come in handy.
The First step is to create a new header template that displays the header as a link (obviously that should be done in the headerstyle.xsl).
<xsl:template name="HeaderStyle" match="*" mode="header">
<xsl:param name="CurPosition" />
<a href="#" class="head">
<xsl:call-template name="OuterTemplate.GetGroupName">
<xsl:with-param name="GroupName" select="@*[name()=$Group]"/>
<xsl:with-param name="GroupType" select="$GroupType"/>
</xsl:call-template>
</a>
</xsl:template>
And for the itemstyle we need to create another itemstyle template that displays each item as a <li>.
<xsl:template name="ListLink" match="Row[@Style='ListLink']" mode="itemstyle">
<xsl:param name="CurPos" />
<xsl:variable name="SafeLinkUrl">
<xsl:call-template name="OuterTemplate.GetSafeLink">
<xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="DisplayTitle">
<xsl:call-template name="OuterTemplate.GetTitle">
<xsl:with-param name="Title" select="@Title"/>
<xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="LinkTarget">
<xsl:if test="@OpenInNewWindow = 'True'" >_blank</xsl:if>
</xsl:variable>
<li>
<a href="{$SafeLinkUrl}" target="{$LinkTarget}" title="{@LinkToolTip}" >
<xsl:value-of select="$DisplayTitle" />
</a>
</li>
</xsl:template>
Again we make a new template, this time in the ContentQueryMain.xsl where all the action will take place:
<xsl:template name="OuterTemplate.BodyWoonbronContact">
<xsl:param name="Rows" />
<xsl:param name="FirstRow" />
<xsl:param name="LastRow" />
</xsl:template>
First thing to fix in this template is a reference to the javascript we are going to use. These scripts can be found on http://docs.jquery.com/Downloading_jQuery and http://bassistance.de/jquery-plugins/jquery-plugin-accordion/ . Besides these scripts there is a minor ‘hardcoded’ javascript that should be done, but it isn’t much.
<script type="text/javascript" src="/_layouts/1043/jquery.js"></script>
<script type="text/javascript" src="/_layouts/1043/jquery.accordion.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$('.contactgegevens').accordion({
autoheight: false,
alwaysOpen:false,
active: false,
header: '.head'
});
});
</script>
Make sure the references to jquery and jquery.accordion are correct, and the scripts can be found from wherever your webpart might be.
Then we can write the headers and elements for each item and its header. They will of course start with a <ul> class. A little note here is that the first <ul> class should correspond to the described class in the little piece of JavaScript we wrote, so that jQuery knows what to do with the list.
The next step is a matter of 4 checks to make sure each header starts with an <ul>, and ends with it whenever the last item in it is written. First thing is a check to close any headers (if there is one). Next thing is a new list item (in this case a header), then a corresponding <ul> that will contain all the items that belongs to the header. And finally if there are no more items everything will be closed properly.
<ul class="contactgegevens">
<xsl:for-each select="$Rows">
<xsl:variable name="CurPosition" select="position()" />
<xsl:if test="($CurPosition >= $FirstRow and $CurPosition <= $LastRow)">
<xsl:variable name="StartNewGroup" select="@__begingroup = 'True'" />
<xsl:variable name="StartNewColumn" select="@__begincolumn = 'True'" />
<xsl:choose>
<xsl:when test="$StartNewGroup">
<xsl:if test="$CurPosition != $FirstRow">
<xsl:text disable-output-escaping="yes">
<![CDATA[
</ul>
</li>
]]>
</xsl:text>
</xsl:if>
<xsl:text disable-output-escaping="yes">
<![CDATA[
<li>
]]>
</xsl:text>
<xsl:call-template name="OuterTemplate.CallHeaderTemplate">
<xsl:with-param name="CurPosition" select="$CurPosition" />
</xsl:call-template>
<xsl:text disable-output-escaping="yes">
<![CDATA[
<ul>
]]>
</xsl:text>
</xsl:when>
</xsl:choose>
<xsl:call-template name="OuterTemplate.CallItemTemplate">
<xsl:with-param name="CurPosition" select="position()" />
<xsl:with-param name="LastRow" select="$LastRow" />
</xsl:call-template>
</xsl:if>
<xsl:if test="$CurPosition = $LastRow">
<xsl:text disable-output-escaping="yes">
<![CDATA[
</ul>
</li>
]]>
</xsl:text>
</xsl:if>
</xsl:for-each>
</ul>
After all these changes (make sure you publish a major version of the files in order to let others see your changes), are done you can use the corresponding Header- and itemstyle in any ContentQuery Webpart, and choose for Group.