Using OrdinalPosition to create self wrapping blocks

Tridion allows your authors to add as many Components to each Page of your website as they like, in any order, using any combination of the templates you provide.

For example:

Article teaser
Article teaser
Download with thumbnail
Download with thumbnail
Download with thumbnail

This represents a page containing five Components using two ComponentTemplates. There is nothing wrong with this until you want to do something radical like surround the Download Components with their own wrapper div tag.

<div id="downloads">
{THE DOWNLOADS GO HERE}
</div>

To achieve this, you could put some specific logic in the Page Template so that whenever it encounters a group of Download Components it knows to put the wrapper div around them. The downside of this kind of approach is that you end up with a Page Template peppered with these kinds of exceptions.

Use your OrdinalPosition, dummy

A far better way is to handle this within the Component Templates themselves, so they are intelligent enough to surround themselves with extra markup if necessary.

The Tridion Object Model contains a property called OrdinalPosition. This is the index of each ComponentPresentation on the Page.

Using OrdinalPosition we can check whether the Component Template at the current index is different to the previous (or next) one.

Then all we need is a little logic to insert some HTML before and after the group of ComponentPresentations, thereby wrapping the group automagically.

Below is a function WrapComponentPresentation() which does exactly that. It should be used as follows:

WrapComponentPresentation(Page, ComponentPresentation, "<li>I am a Component</li>", "<ul>", "</ul>")

The function should be called from within the Component Template that forms the group of items – in this case our ‘Download with thumbnail’ template.

Then you can add multiple Components to the Page, all using the same template, and the first/last Components will intelligently prepend/append code where necessary.

Job done!

Function WrapComponentPresentation(objPage, objComponentPresentation, strComponentPresentation, strBefore, strAfter)
Dim strTemp, numPosition, numOfCPsOnPage
numPosition = objComponentPresentation.OrdinalPosition
numOfCPsOnPage = objPage.ComponentPresentations.Count
Dim boolStartOfBlock, boolEndOfBlock
boolStartOfBlock = false
boolEndOfBlock = false
if numPosition = 1 Then
boolStartOfBlock = true
End if
if numPosition = numOfCPsOnPage Then
boolEndOfBlock = true
End if
if boolStartOfBlock = false Then
Dim objPreviousComponent
Set objPreviousComponent = objPage.ComponentPresentations(numPosition-1)
if objPreviousComponent.ComponentTemplate.ID <> ComponentTemplate.ID Then
boolStartOfBlock = true
End if
Set objPreviousComponent = Nothing
End if
if boolEndOfBlock = false Then
Dim objNextComponent
Set objNextComponent = objPage.ComponentPresentations(numPosition+1)
if objNextComponent.ComponentTemplate.ID <> ComponentTemplate.ID Then
boolEndOfBlock = true
End if
Set objNextComponent = Nothing
End if
if boolStartOfBlock = true Then
strTemp = strTemp & strBefore
End if
strTemp = strTemp & strComponentPresentation
if boolEndOfBlock = true Then
strTemp = strTemp & strAfter
End if
WrapComponentPresentation = strTemp
End Function