Embedding and Sharing Video in SharePoint

Introduction

The solution described here allows to embed video hosted on YouTube into SharePoint. The same approach may be applied for embedding video from another video hosting sites, for example from Vimeo.

The main idea here to store embedded video properties and not the embedded code itself.
For storing embedded video properties we will use Custom  List, see implementation section for description. Page for Video Links list (default view with embedded player)  is shown below

Usage

In order to embed a video into SharePoint:

  • On YouTube site click the Share button located under the video.
  • Click the Embed button.
  • Copy at least src attribute value provided in the expanded box (see table 1 for supported attributes).

  • Create new Video Link item  and paste attribute values for embedded code into Video Links item. Save it.

Table 1. Mapping between embedded code iframe attributes and Video Link item

Attribute name Video Links field name
src URL
width Video Width
height Video Height
allowfullscreen Allow Fullscreen
frameborder Frame Border

Video Links implementation

As was mentioned earlier only properties for embedded video code are stored and not the embedded code itself. For storing embedded video code properties is used Custom List that extends OOB Links List (TemplateType = 103)

For embedded video properties we create Video Link Content Type that inherits from Link CT (0x0105)

where we define the following fields

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Field Type="Number"
DisplayName="Frame Border"
Required="FALSE"
EnforceUniqueValues="FALSE"
Group="Media Columns"
ID="{594e551f-180d-47ec-90e5-9195225c5932}"
StaticName="FrameBorder"
Name="FrameBorder"
Percentage="FALSE"
Hidden="FALSE"
SourceID="http://schemas.microsoft.com/sharepoint/v3">
<Default>0</Default>
</Field>
<Field Type="Number"
DisplayName="Video Height"
Required="FALSE"
EnforceUniqueValues="FALSE"
Group="Media Columns"
ID="{a1e94df1-eb6e-4fd2-aef7-bf0cc175c760}"
StaticName="VideoHeight"
Name="VideoHeight"
Percentage="FALSE"
Hidden="FALSE"
SourceID="http://schemas.microsoft.com/sharepoint/v3"/>
<Field Type="Number"
DisplayName="Video Width"
Required="FALSE"
EnforceUniqueValues="FALSE"
Group="Media Columns"
ID="{e0406eee-7432-47d8-9080-8c1c4db23170}"
StaticName="VideoWidth"
Name="VideoWidth"
Percentage="FALSE"
Hidden="FALSE"
SourceID="http://schemas.microsoft.com/sharepoint/v3"/>
<Field Type="Boolean"
DisplayName="Allow FullScreen"
EnforceUniqueValues="FALSE"
Group="Media Columns"
ID="{b6ba6c8f-81d6-478a-a303-3b18687ec934}"
StaticName="AllowFullScreen"
Name="AllowFullScreen"
Required="FALSE"
Hidden="FALSE"
SourceID="http://schemas.microsoft.com/sharepoint/v3">
<Default>0</Default>
</Field>
<Field Type="Choice"
DisplayName="Embedding Mode"
Required="FALSE"
EnforceUniqueValues="FALSE"
Format="Dropdown"
FillInChoice="FALSE"
Group="Media Columns"
ID="{5836ef4c-c440-4cb8-a471-0ee918bfc710}"
StaticName="EmbeddingMode"
Name="EmbeddingMode"
Hidden="FALSE"
SourceID="http://schemas.microsoft.com/sharepoint/v3">
<Default>IFrame</Default>
<CHOICES>
<CHOICE>IFrame</CHOICE>
<CHOICE>Object</CHOICE>
</CHOICES>
</Field>
<Field
ID="{C1D8C50A-2146-41f6-80CC-02C7691392A3}"
Type="Computed"
Name="EmbeddedVideoOnForm"
StaticName="EmbeddedVideoOnForm"
DisplaceOnUpgrade="TRUE"
ShowInNewForm="FALSE"
ShowInDisplayForm="FALSE"
ShowInEditForm="FALSE"
ShowInFileDlg="FALSE"
DisplayName="Embedded Video"
SourceID="http://schemas.microsoft.com/sharepoint/v3/fields"
Sealed="TRUE"
Sortable="FALSE"
Filterable="FALSE">
<FieldRefs>
<FieldRef Name="URL" />
<FieldRef Name="FileLeafRef" />
<FieldRef Name="FileRef" />
<FieldRef Name="FSObjType" />
<FieldRef Name="EmbeddingMode" />
<FieldRef Name="VideoWidth" />
<FieldRef Name="VideoHeight" />
<FieldRef Name="FrameBorder" />
</FieldRefs>
<DisplayPattern>
<IfEqual>
<Expr1>
<Column Name="EmbeddingMode" />
</Expr1>
<Expr2>IFrame</Expr2>
<Then>
<HTML><![CDATA[<iframe width=']]></HTML>
<Field Name="VideoWidth"/>
<HTML><![CDATA[' height=']]></HTML>
<Field Name="VideoHeight"/>
<HTML><![CDATA[' src=']]></HTML>
<Field Name="URL"/>
<HTML><![CDATA[' frameborder=']]></HTML>
<Field Name="FrameBorder"/>
<HTML><![CDATA[' allowfullscreen']]></HTML>
<HTML>
<![CDATA['></iframe>]]>
</HTML>
</Then>
<Else>
<HTML>
<![CDATA[Not supported yet]]>
</HTML>
</Else>
</IfEqual>
</DisplayPattern>
</Field>
</Elements>

Pay attention, for rendering YouTube player Computed Field EmbeddedVideoOnForm is intended.
For rendering of a field on a List View the following XSLT style sheet is used

And finally, we create List Definition Video Links from Content Type Video Link. List schema and Template files for Video Links including whole project  may be found on GitHub.

References

  • Video Links project on GitHub
  • How to embed Vimeo player see here
  • How to embed YouTube player  see here
  • How to customize the rendering of a field in List View see here

Rendering Content Query Web Part results in Table Layout

It is known that OOB Content Query Web Part (CQWP)  renders results using Lists for arranging items as shown below

In ASP.NET WebForms for Web Control DataList there is a possibility to specify layout rendering mode using property RepeatLayout, what if the similar functionality would be available in CQWP?

So, our  goal to extend CQWP, i.e. in addition to List Layout rendering mode, lets implement functionality for rendering Content Query Web Part results in Plain Old Table Layout.
In this approach, we would like to achieve the following options:

  • Possibility to easily arrange results in columns
  • Specify items direction (horizontal or vertical)

Solution Structure

Content Query Web Part Class

using System;
using System.ComponentModel;
using System.Security.Permissions;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint.Publishing.WebControls;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.WebPartPages;
namespace CQWPWithTableLayout.WebControls
{
[ToolboxItem(false)]
public class CBQTableLayout : ContentByQueryWebPart
{
#region Control Lifecycle
protected override void CreateChildControls()
{
try
{
base.CreateChildControls();
}
catch (Exception ex)
{
throw;
}
}
protected override void ModifyXsltArgumentList(ArgumentClassWrapper argList)
{
argList.AddParameter("RepeatDirection", string.Empty, RepeatDirection);
argList.AddParameter("RepeatColumns", string.Empty, RepeatColumns);
base.ModifyXsltArgumentList(argList);
}
/// <summary>
/// Return the tool panes that configure this <see cref="T:Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart"/> object..
/// </summary>
[SharePointPermission(SecurityAction.Demand, ObjectModel = true)]
public override ToolPart[] GetToolParts()
{
return new ToolPart[3]
{
new ContentByQueryToolPart(),
new WebPartToolPart(),
new CBQTableLayoutToolPart()
};
}
#endregion
#region Properties
[Category("TableLayout")]
[Personalizable(PersonalizationScope.Shared), DefaultValue(3), WebBrowsable(true)]
public int RepeatColumns { get; set; }
[Category("TableLayout")]
[Personalizable(PersonalizationScope.Shared), DefaultValue(RepeatDirection.Horizontal), WebBrowsable(true)]
public RepeatDirection RepeatDirection { get; set; }
#endregion
}
}

Tool Part Class Implementation with the ability to specify Table Layout properties

using System;
using System.Globalization;
using System.Web.UI.WebControls;
namespace CQWPWithTableLayout.WebControls
{
public class CBQTableLayoutToolPart : Microsoft.SharePoint.WebPartPages.ToolPart
{
public CBQTableLayoutToolPart()
{
Init += InitToolPart;
}
private void InitToolPart(object sender, EventArgs e)
{
Title = "Table Layout Settings";
_targetWebPart = ParentToolPane.SelectedWebPart as CBQTableLayout;
if (_targetWebPart == null)
throw new Exception("Wrong web part type error");
}
protected override void CreateChildControls()
{
CreateTableLayoutSection();
PopulateTableLayoutSection();
base.CreateChildControls();
}
public override void ApplyChanges()
{
this.ApplySettingsSectionChanges();
base.ApplyChanges();
}
private void CreateTableLayoutSection()
{
_columnsBox = new TextBox {MaxLength = 2};
_directionBox = new DropDownList();
var mainTable = new Table { CellPadding = 2, CellSpacing = 2 };
mainTable.Style["border-collapse"] = "collapse";
//Repeat Columns
AddRepeatColumnsProperty(mainTable);
//Repeat Direction
AddRepeatDirectionProperty(mainTable);
Controls.Add(mainTable);
}
private void AddRepeatColumnsProperty(Table section)
{
var rowHeader = new TableRow();
var cellHeader = new TableCell { Text = "Repeat Columns" };
rowHeader.Cells.Add(cellHeader);
section.Rows.Add(rowHeader);
var rowItem = new TableRow();
var cellItem = new TableCell();
cellItem.Controls.Add(_columnsBox);
rowItem.Cells.Add(cellItem);
section.Rows.Add(rowItem);
}
private void AddRepeatDirectionProperty(Table section)
{
var rowHeader = new TableRow();
var cellHeader = new TableCell { Text = "Repeat Direction" };
rowHeader.Cells.Add(cellHeader);
section.Rows.Add(rowHeader);
var rowItem = new TableRow();
var cellItem = new TableCell();
cellItem.Controls.Add(_directionBox);
rowItem.Cells.Add(cellItem);
section.Rows.Add(rowItem);
}
private void PopulateTableLayoutSection()
{
_columnsBox.Text = _targetWebPart.RepeatColumns.ToString(CultureInfo.InvariantCulture);
var directions = Enum.GetValues(typeof(RepeatDirection));
_directionBox.DataSource = directions;
_directionBox.DataBind();
_directionBox.Text = _targetWebPart.RepeatDirection.ToString();
}
protected void ApplySettingsSectionChanges()
{
_targetWebPart.RepeatColumns = int.Parse(_columnsBox.Text);
_targetWebPart.RepeatDirection = (RepeatDirection)Enum.Parse(typeof(RepeatDirection), _directionBox.Text);
}
private TextBox _columnsBox;
private DropDownList _directionBox;
private CBQTableLayout _targetWebPart;
}
}

Web Part manifest file

<?xml version="1.0" encoding="utf-8"?>
<webParts>
<webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
<metaData>
<type name="CQWPWithTableLayout.WebControls.CBQTableLayout, CQWPWithTableLayout, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f96554baea0809a2" />
<importErrorMessage>Cannot import this Web Part.</importErrorMessage>
</metaData>
<data>
<properties>
<property name="Title" type="string">Content Query (Plain Old Table Layout)</property>
<property name="Description" type="string">Displays a dynamic view of content from your site.</property>
<property name="ChromeType">TitleOnly</property>
<property name="ChromeState">Normal</property>
<property name="ItemLimit" type="int">15</property>
<property name="SortBy" type="string">{8c06beca-0777-48f7-91c7-6da68bc07b69}</property>
<property name="SortByDirection" type="Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart+SortDirection,Microsoft.SharePoint.Publishing,Version=14.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c">Desc</property>
<property name="GroupStyle" type="string">DefaultHeader</property>
<property name="ItemStyle" type="string">Default</property>
<property name="ServerTemplate" type="string"></property>
<property name="MainXslLink" type="string" >/Style Library/XSL Style Sheets/ContentQueryMainTableLayout.xsl</property>
<property name="RepeatColumns" type="int">0</property>
<property name="RepeatDirection" type="System.Web.UI.WebControls.RepeatDirection, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">Vertical</property>
</properties>
</data>
</webPart>
</webParts>

Pay attention that we provide custom XSLT for processing of the CQWP, for more details see How to: Customize XSL for the SharePoint Content By Query Web Part.

Main XSLT style sheet for rendering results in Table Layout

<xsl:stylesheet
version="1.0"
exclude-result-prefixes="x xsl cmswrt cbq"
xmlns:x="http://www.w3.org/2001/XMLSchema"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:cmswrt="http://schemas.microsoft.com/WebPart/v3/Publishing/runtime"
xmlns:cbq="urn:schemas-microsoft-com:ContentByQueryWebPart">
<xsl:output method="xml" indent="no" media-type="text/html" omit-xml-declaration="yes"/>
<xsl:param name="cbq_isgrouping" />
<xsl:param name="cbq_columnwidth" />
<xsl:param name="Group" />
<xsl:param name="GroupType" />
<xsl:param name="cbq_iseditmode" />
<xsl:param name="cbq_viewemptytext" />
<xsl:param name="cbq_errortext" />
<xsl:param name="SiteId" />
<xsl:param name="WebUrl" />
<xsl:param name="PageId" />
<xsl:param name="WebPartId" />
<xsl:param name="FeedPageUrl" />
<xsl:param name="FeedEnabled" />
<xsl:param name="SiteUrl" />
<xsl:param name="BlankTitle" />
<xsl:param name="BlankGroup" />
<xsl:param name="UseCopyUtil" />
<xsl:param name="DataColumnTypes" />
<xsl:param name="ClientId" />
<xsl:param name="Source" />
<xsl:param name="RootSiteRef" />
<xsl:param name="CBQPageUrl" />
<xsl:param name="CBQPageUrlQueryStringForFilters" />
<xsl:param name="RepeatDirection" />
<xsl:param name="RepeatColumns" />
<xsl:variable name="BeginTable" select="string('&lt;table class=&quot;dfwp-list&quot;&gt;')" />
<xsl:variable name="EndTable" select="string('&lt;/table&gt;')" />
<xsl:variable name="BeginTableRow" select="string('&lt;tr&gt;')" />
<xsl:variable name="EndTableRow" select="string('&lt;/tr&gt;')" />
<xsl:variable name="BeginTableCell" select="string('&lt;td class=&quot;dfwp-item&quot;&gt;')" />
<xsl:variable name="EndTableCell" select="string('&lt;/td&gt;')" />
<xsl:template match="/">
<xsl:call-template name="OuterTemplate" />
</xsl:template>
<xsl:template name="OuterTemplate">
<xsl:variable name="Rows" select="/dsQueryResponse/Rows/Row" />
<xsl:variable name="RowCount" select="count($Rows)" />
<xsl:variable name="IsEmpty" select="$RowCount = 0" />
<div id="{concat('cbqwp', $ClientId)}" class="cbq-layout-main">
<xsl:if test="$cbq_iseditmode = 'True' and string-length($cbq_errortext) != 0">
<div class="wp-content description">
<xsl:value-of disable-output-escaping="yes" select="$cbq_errortext" />
</div>
</xsl:if>
<xsl:choose>
<xsl:when test="$IsEmpty">
<xsl:call-template name="OuterTemplate.Empty" >
<xsl:with-param name="EditMode" select="$cbq_iseditmode" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="OuterTemplate.Body">
<xsl:with-param name="Rows" select="$Rows" />
<xsl:with-param name="FirstRow" select="1" />
<xsl:with-param name="LastRow" select="$RowCount" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</div>
<xsl:if test="$FeedEnabled = 'True' and $PageId != ''">
<div class="cqfeed">
<xsl:variable name="FeedUrl1" select="concat($SiteUrl,$FeedPageUrl,'xsl=1&amp;web=',$WebUrl,'&amp;page=',$PageId,'&amp;wp=',$WebPartId,'&amp;pageurl=',$CBQPageUrl,$CBQPageUrlQueryStringForFilters)" />
<a href="{cmswrt:RegisterFeedUrl( $FeedUrl1, 'application/rss+xml')}">
<img src="\_layouts\images\rss.gif" border="0" alt="{cmswrt:GetPublishingResource('CbqRssAlt')}"/>
</a>
</div>
</xsl:if>
</xsl:template>
<xsl:template name="OuterTemplate.Empty">
<xsl:param name="EditMode" />
<xsl:if test="$EditMode = 'True' and string-length($cbq_errortext) = 0">
<div class="wp-content description">
<xsl:value-of disable-output-escaping="yes" select="$cbq_viewemptytext" />
</div>
</xsl:if>
</xsl:template>
<xsl:template name="OuterTemplate.Body">
<xsl:param name="Rows" />
<xsl:param name="FirstRow" />
<xsl:param name="LastRow" />
<xsl:value-of disable-output-escaping="yes" select="$BeginTable" />
<xsl:choose>
<xsl:when test="$RepeatDirection = 1">
<xsl:call-template name="OuterTemplate.CallVerticalLayoutTemplate">
<xsl:with-param name="Rows" select="$Rows" />
<xsl:with-param name="FirstRow" select="$FirstRow" />
<xsl:with-param name="LastRow" select="$LastRow" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:for-each select="$Rows">
<xsl:variable name="CurPosition" select="position()" />
<xsl:call-template name="OuterTemplate.CallHorizontalLayoutTemplate">
<xsl:with-param name="CurPosition" select="$CurPosition" />
<xsl:with-param name="LastRow" select="$LastRow" />
</xsl:call-template>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
<xsl:value-of disable-output-escaping="yes" select="$EndTable" />
</xsl:template>
<xsl:template name="OuterTemplate.CallVerticalContainerTemplate">
<xsl:param name="RowPosition" />
<xsl:param name="RowsCount" />
<xsl:param name="ColsCount" />
<xsl:if test="$RowPosition &lt;= $RowsCount">
<xsl:value-of disable-output-escaping="yes" select="$BeginTableRow" />
<xsl:variable name="CurPosition" select="$RowPosition" />
<xsl:variable name="AllRows" select="/dsQueryResponse/Rows/Row" />
<xsl:for-each select="$AllRows">
<xsl:variable name="ColPosition" select="position()" />
<xsl:choose>
<xsl:when test="$ColPosition != 1 and $ColPosition &lt;= $ColsCount">
<xsl:variable name="CurPositionAbs" select="$CurPosition + $RowsCount * ($ColPosition – 1)" />
<xsl:if test="$CurPositionAbs &lt;= (count($AllRows))">
<xsl:call-template name="OuterTemplate.CallItemTemplate">
<xsl:with-param name="CurPosition" select="$CurPositionAbs" />
</xsl:call-template>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:if test="$ColPosition &lt;= $ColsCount">
<xsl:call-template name="OuterTemplate.CallItemTemplate">
<xsl:with-param name="CurPosition" select="$RowPosition" />
</xsl:call-template>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<xsl:value-of disable-output-escaping="yes" select="$EndTableRow" />
</xsl:if>
<xsl:if test="$RowPosition &lt;= $RowsCount">
<xsl:call-template name="OuterTemplate.CallVerticalContainerTemplate">
<xsl:with-param name="RowPosition">
<xsl:value-of select="$RowPosition + 1"/>
</xsl:with-param>
<xsl:with-param name="RowsCount">
<xsl:value-of select="$RowsCount"/>
</xsl:with-param>
<xsl:with-param name="ColsCount">
<xsl:value-of select="$ColsCount"/>
</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="OuterTemplate.CallHeaderTemplate">
<xsl:apply-templates select="." mode="header">
</xsl:apply-templates>
</xsl:template>
<xsl:template name="OuterTemplate.CallVerticalLayoutTemplate">
<xsl:param name="Rows" />
<xsl:param name="FirstRow" />
<xsl:param name="LastRow" />
<!–Calc Cols & Rows–>
<xsl:choose>
<xsl:when test="$RepeatColumns = 0 or $RepeatColumns = 1">
<xsl:variable name="ColsCount" select="1" />
<xsl:variable name="RowsCount" select="$LastRow" />
<xsl:call-template name="OuterTemplate.CallVerticalContainerTemplate">
<xsl:with-param name="RowPosition" select="1" />
<xsl:with-param name="RowsCount" select="$RowsCount" />
<xsl:with-param name="ColsCount" select="$ColsCount" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="ColsCount" select="$RepeatColumns" />
<xsl:variable name="RowsCount" select="floor(($LastRow + $RepeatColumns – 1) div $RepeatColumns)" />
<xsl:call-template name="OuterTemplate.CallVerticalContainerTemplate">
<xsl:with-param name="RowPosition" select="1" />
<xsl:with-param name="RowsCount" select="$RowsCount" />
<xsl:with-param name="ColsCount" select="$ColsCount" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="OuterTemplate.CallHorizontalLayoutTemplate">
<xsl:param name="CurPosition" />
<xsl:param name="LastRow" />
<xsl:choose>
<xsl:when test="$RepeatColumns = 0">
<xsl:if test="$CurPosition = 1">
<xsl:value-of disable-output-escaping="yes" select="$BeginTableRow" />
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:if test="$CurPosition mod $RepeatColumns = 1">
<xsl:value-of disable-output-escaping="yes" select="$BeginTableRow" />
</xsl:if>
</xsl:otherwise>
</xsl:choose>
<xsl:call-template name="OuterTemplate.CallItemTemplate">
<xsl:with-param name="CurPosition" select="$CurPosition" />
</xsl:call-template>
<xsl:choose>
<xsl:when test="$RepeatColumns = 0">
<xsl:if test="$CurPosition = $LastRow">
<xsl:value-of disable-output-escaping="yes" select="$EndTableRow" />
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:if test="$CurPosition mod $RepeatColumns = 0">
<xsl:value-of disable-output-escaping="yes" select="$EndTableRow" />
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="OuterTemplate.CallItemTemplateDummy">
<xsl:param name="CurPosition" />
<xsl:value-of disable-output-escaping="yes" select="$BeginTableCell" />
<xsl:value-of disable-output-escaping="yes" select="$CurPosition" />
<xsl:value-of disable-output-escaping="yes" select="$EndTableCell" />
</xsl:template>
<xsl:template name="OuterTemplate.CallItemTemplate">
<xsl:param name="CurPosition" />
<xsl:value-of disable-output-escaping="yes" select="$BeginTableCell" />
<xsl:choose>
<xsl:when test="@Style='NewsRollUpItem'">
<xsl:apply-templates select="." mode="itemstyle">
<xsl:with-param name="EditMode" select="$cbq_iseditmode" />
</xsl:apply-templates>
</xsl:when>
<xsl:when test="@Style='NewsBigItem'">
<xsl:apply-templates select="." mode="itemstyle">
<xsl:with-param name="CurPos" select="$CurPosition" />
</xsl:apply-templates>
</xsl:when>
<xsl:when test="@Style='NewsCategoryItem'">
<xsl:apply-templates select="." mode="itemstyle">
<xsl:with-param name="CurPos" select="$CurPosition" />
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="/dsQueryResponse/Rows/Row[position() = $CurPosition]" mode="itemstyle">
</xsl:apply-templates>
<!–<xsl:value-of disable-output-escaping="yes" select="$CurPosition" />–>
</xsl:otherwise>
</xsl:choose>
<xsl:value-of disable-output-escaping="yes" select="$EndTableCell" />
</xsl:template>
<xsl:template name="OuterTemplate.CallFooterTemplate">
</xsl:template>
<xsl:template name="OuterTemplate.GetSafeLink">
<xsl:param name="UrlColumnName"/>
<xsl:if test="$UseCopyUtil = 'True'">
<xsl:value-of select="concat($RootSiteRef,'/_layouts/CopyUtil.aspx?Use=id&amp;Action=dispform&amp;ItemId=',@ID,'&amp;ListId=',@ListId,'&amp;WebId=',@WebId,'&amp;SiteId=',$SiteId,'&amp;Source=',$Source)"/>
</xsl:if>
<xsl:if test="$UseCopyUtil != 'True'">
<xsl:call-template name="OuterTemplate.GetSafeStaticUrl">
<xsl:with-param name="UrlColumnName" select="$UrlColumnName"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="OuterTemplate.GetTitle">
<xsl:param name="Title"/>
<xsl:param name="UrlColumnName"/>
<xsl:param name="UseFileName" select="0"/>
<xsl:choose>
<xsl:when test="string-length($Title) != 0 and $UseFileName = 0">
<xsl:value-of select="$Title" />
</xsl:when>
<xsl:when test="$UseCopyUtil = 'True' and $UseFileName = 0">
<xsl:value-of select="$BlankTitle" />
</xsl:when>
<xsl:otherwise>
<xsl:variable name="FileNameWithExtension">
<xsl:call-template name="OuterTemplate.GetPageNameFromUrl">
<xsl:with-param name="UrlColumnName" select="$UrlColumnName" />
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$UseFileName = 1">
<xsl:call-template name="OuterTemplate.GetFileNameWithoutExtension">
<xsl:with-param name="input" select="$FileNameWithExtension" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$FileNameWithExtension" />
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="OuterTemplate.FormatColumnIntoUrl">
<xsl:param name="UrlColumnName"/>
<xsl:variable name="Value" select="@*[name()=$UrlColumnName]"/>
<xsl:if test="contains($DataColumnTypes,concat(';',$UrlColumnName,',URL;'))">
<xsl:call-template name="OuterTemplate.FormatValueIntoUrl">
<xsl:with-param name="Value" select="$Value"/>
</xsl:call-template>
</xsl:if>
<xsl:if test="not(contains($DataColumnTypes,concat(';',$UrlColumnName,',URL;')))">
<xsl:value-of select="$Value"/>
</xsl:if>
</xsl:template>
<xsl:template name="OuterTemplate.FormatValueIntoUrl">
<xsl:param name="Value"/>
<xsl:if test="not(contains($Value,', '))">
<xsl:value-of select="$Value"/>
</xsl:if>
<xsl:if test="contains($Value,', ')">
<xsl:call-template name="OuterTemplate.Replace">
<xsl:with-param name="Value" select="substring-before($Value,', ')"/>
<xsl:with-param name="Search" select="',,'"/>
<xsl:with-param name="Replace" select="','"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="OuterTemplate.Replace">
<xsl:param name="Value"/>
<xsl:param name="Search"/>
<xsl:param name="Replace"/>
<xsl:if test="contains($Value,$Search)">
<xsl:value-of select="concat(substring-before($Value,$Search),$Replace)"/>
<xsl:call-template name="OuterTemplate.Replace">
<xsl:with-param name="Value" select="substring-after($Value,$Search)"/>
<xsl:with-param name="Search" select="$Search"/>
<xsl:with-param name="Replace" select="$Replace"/>
</xsl:call-template>
</xsl:if>
<xsl:if test="not(contains($Value,$Search))">
<xsl:value-of select="$Value"/>
</xsl:if>
</xsl:template>
<xsl:template name="OuterTemplate.GetSafeStaticUrl">
<xsl:param name="UrlColumnName"/>
<xsl:variable name="Url">
<xsl:call-template name="OuterTemplate.FormatColumnIntoUrl">
<xsl:with-param name="UrlColumnName" select="$UrlColumnName"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="cmswrt:EnsureIsAllowedProtocol($Url)"/>
</xsl:template>
<xsl:template name="OuterTemplate.GetColumnDataForUnescapedOutput">
<xsl:param name="Name"/>
<xsl:param name="MustBeOfType"/>
<xsl:if test="contains($DataColumnTypes,concat(';',$Name,',',$MustBeOfType,';'))">
<xsl:value-of select="@*[name()=$Name]"/>
</xsl:if>
</xsl:template>
<xsl:template name="OuterTemplate.GetPageNameFromUrl">
<xsl:param name="UrlColumnName"/>
<xsl:variable name="Url">
<xsl:call-template name="OuterTemplate.FormatColumnIntoUrl">
<xsl:with-param name="UrlColumnName" select="$UrlColumnName"/>
</xsl:call-template>
</xsl:variable>
<xsl:call-template name="OuterTemplate.GetPageNameFromUrlRecursive">
<xsl:with-param name="Url" select="$Url"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="OuterTemplate.GetPageNameFromUrlRecursive">
<xsl:param name="Url"/>
<xsl:choose>
<xsl:when test="contains($Url,'/') and substring($Url,string-length($Url)) != '/'">
<xsl:call-template name="OuterTemplate.GetPageNameFromUrlRecursive">
<xsl:with-param name="Url" select="substring-after($Url,'/')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$Url"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="OuterTemplate.GetGroupName">
<xsl:param name="GroupName"/>
<xsl:param name="GroupType"/>
<xsl:choose>
<xsl:when test="string-length(normalize-space($GroupName)) = 0">
<xsl:value-of select="$BlankGroup"/>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="$GroupType='URL'">
<xsl:variable name="Url">
<xsl:call-template name="OuterTemplate.FormatValueIntoUrl">
<xsl:with-param name="Value" select="$GroupName"/>
</xsl:call-template>
</xsl:variable>
<xsl:call-template name="OuterTemplate.GetPageNameFromUrlRecursive">
<xsl:with-param name="Url" select="$Url"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$GroupName" />
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="OuterTemplate.CallPresenceStatusIconTemplate">
<xsl:if test="string-length(@SipAddress) != 0">
<span class="presence-status-icon">
<img src="/_layouts/images/imnhdr.gif" onload="IMNRC('{@SipAddress}')" ShowOfflinePawn="1" alt="" id="{concat('MWP_pawn_',$ClientId,'_',@ID,'type=sip')}"/>
</span>
</xsl:if>
</xsl:template>
<xsl:template name="OuterTemplate.GetFileNameWithoutExtension">
<xsl:param name="input"/>
<xsl:variable name="extension">
<xsl:value-of select="substring-after($input, '.')"/>
</xsl:variable>
<xsl:choose>
<xsl:when test="contains($extension, '.')">
<xsl:variable name="afterextension">
<xsl:call-template name="OuterTemplate.GetFileNameWithoutExtension">
<xsl:with-param name="input" select="$extension"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="concat(substring-before($input, '.'), $afterextension)"/>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="contains($input, '.')">
<xsl:value-of select="substring-before($input, '.')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$input"/>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

Results

Below is shown Web Part configured  to display results in 4 columns and horizontal mode layout

CBQTableLayoutHorizontal2