I am (still) do heaps of work in SharePoint (MOSS) 2007 search which means I am (still) do heaps of work in XSL. An interesting task I had this week was to show and hide a body of text - however a brief summary of the text needed to be shown first, with the capability to expand the text to see more information. As there was no summary text per se, this meant the actual text needed to be shown partially, and when a link to show more is clicked, show it in it's entirety. Also, as part of keeping this all looking professional, the summary should not have any words chopped off.
Basically for the javascript show/hide we already had an existing bit of script I used, however if you need to try this out I thought I'd share this anyway:
<script type="text/javascript">
function toggleLayer( whichLayer )
{
var elem, vis;
if (document.getElementById) // this is the way the standards work
elem = document.getElementById( whichLayer );
else if( document.all ) // this is the way old msie versions work
elem = document.all[whichLayer];
else if( document.layers ) // this is the way nn4 works
elem = document.layers[whichLayer];
vis = elem.style;
// if the style.display value is blank we try to figure it out here
if(vis.display==''&&elem.offsetWidth!=undefined&&elem.offsetHeight!=undefined)
vis.display = (elem.offsetWidth!=0&&elem.offsetHeight!=0)?'block':'none';
vis.display = (vis.display==''||vis.display=='block')?'none':'block';
}
</script>
In order to specify the number of characters I was trimming initially, I added this as a simple XSL parameter to my XSL page ie:
<xsl:param name="AbstractSummaryLength">400</xsl:param>
Next I created an XSL method called 'trim' which basically works by recursively calling itself to continue to trim until it reaches a space, and hence the end of a word.
<xsl:template name="trim">
<xsl:param name="in"/>
<xsl:choose>
<xsl:when test="substring($in, string-length($in), 1)=' '">
<xsl:value-of select="$in"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="trim">
<xsl:with-param name="in"
select="substring($in, 1, string-length($in)-1)"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
In order to get the summary of text (for a specified length) the substring method in XSL is great (assuming the field with our data is called 'abstract').
<xsl:variable name="summaryabstract" select="substring($abstract, 1, $AbstractSummaryLength)"/>
We can then pass this value to the trim method to ensure we get an entire word at the end of the summary:
<xsl:variable name="summaryabstracttrimmed">
<xsl:call-template name="trim">
<xsl:with-param name="in" select="$summaryabstract"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="abstractstartposition" select="string-length($summaryabstracttrimmed)"/>
Finally, we just put together our variables and HTML, and we have a nice little piece of code to show and hide our full summary:
<!--Start of abstract-->
<div>
<xsl:attribute name="id">AbstractSummary<xsl:value-of select="id"/></xsl:attribute>
<xsl:value-of disable-output-escaping="yes" select="$summaryabstracttrimmed"/>
[<a title="Show Abstract">
<xsl:attribute name="href">
javascript:toggleLayer('Abstract<xsl:value-of select="id"/>');
javascript:toggleLayer('AbstractSummary<xsl:value-of select="id"/>');
</xsl:attribute>more...</a>]
</div>
<div style="display:none">
<xsl:attribute name="id">Abstract<xsl:value-of select="id"/></xsl:attribute>
<!-- Remainder of abstract-->
<!--<xsl:value-of disable-output-escaping="yes" select="substring($abstract, $abstractstartposition)"/>-->
<!-- Full abstract-->
<xsl:value-of disable-output-escaping="yes" select="$abstract"/>
[<a title="Hide Abstract">
<xsl:attribute name="href">
javascript:toggleLayer('Abstract<xsl:value-of select="id"/>');
javascript:toggleLayer('AbstractSummary<xsl:value-of select="id"/>');
</xsl:attribute>Hide</a>]
</div>
</xsl:if>