Wednesday, August 7, 2013

CQWP for image or content sliders

Sharepoint 2010 's Content Query webpart is my favorite webpart of all the webparts in the world.

Out of the box it can do a lot of things and you can easily customize display styles. Unfortunately applying css or using jquery in CQWP becomes quite painful. 

For a recent project we had a requirement to pull News Pages from all subsites and display them using CQWP in a content slider. 

I modified ContentQueryMain.xsl, Header.xsl and Item.xsl to get the results I need

Link to modified ContentQueryMain-modified.xsl file

  1. ContentQueryMain.xsl - Removed Columns, Removed assignment of <li> to an item and added it to the ItemStyle.xsl file, added styles to Group header depending on a group name.

    lines modified in the original ContentQueryMain.xsl file:
    Line 32: replaced dfwp-list with header-column for the class
    Line 34: removed BeginListItem replaced with StartGroupStyle- prints out <li class="
    Line 35: removed EndListItem replaced with EndGroupStyle - prints out </li>
    Line 36: added endlistitemclass - prints out "> to close <li class="

    Line 83: replaced class dfwp-column dfwp-list with listings clearfix
    Line 84: removed %&quot; - this was printing  % at the end of the calculated column width (1, 2. 3 columns in the CQWP settings)
    Line 85: removed $cbq_columnwidth, this was calucated width of the column, useless

    modifications to CallHeaderTemplate - Line 140

    <xsl:template name="OuterTemplate.CallHeaderTemplate">
            <xsl:value-of select="$StartGroupStyle" disable-output-escaping="yes"/>
            <xsl:value-of select="translate(@*[name()=$Group],translate(@*[name()=$Group], &#39;abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789&#39;,&#39;&#39;),&#39;&#39;)"/>
            <xsl:value-of select="$endlistitemclass" disable-output-escaping="yes"/> 
    
            <xsl:apply-templates select="." mode="header">
            </xsl:apply-templates>
          <xsl:value-of disable-output-escaping="yes" select="$BeginList" />
        </xsl:template>

    after calling the template name I added variable declared on line 34 which will give us start of list item - $StartGroupStyle
    next value is the Name of the group spaces removed
    finishing up with $enndlistitemclass
    so the above will generate header as a list item with nested unordered list

    Line 148: removed $BeginListItem since the list item will be assigned to the item template
    Line 170: removed $EndListItem

    Modifications to CallFooterTemplate - Line 172
    <xsl:template name="OuterTemplate.CallFooterTemplate">
          <xsl:value-of disable-output-escaping="yes" select="$EndList" />
         <xsl:value-of select="$EndGroupStyle" disable-output-escaping="yes"/>
        </xsl:template>
    Replaced $EndListItem with $EndGroupStyle

  2. Header.xsl
    Default header style is generating <li> Header</li> this is no longer needed

    Updated Default Header Template
    <xsl:template name="DefaultHeader" match="*" mode="header">
          <xsl:call-template name="OuterTemplate.GetGroupName">
            <xsl:with-param name="GroupName" select="@*[name()=$Group]"/>
            <xsl:with-param name="GroupType" select="$GroupType"/>
          </xsl:call-template>
      </xsl:template>
    

  3. ItemStyle.xsl
    Make sure you go through all Item template and add <li class="YOURCLASS"> after last variable declaration and </li> right before </xsl:call-template>
    This is will not take much time but at the end you will be able to assign your own classes to each item style.

    Item template for the page display will have the following structure

    I will use default fields available in the page content type:
    Rollup Image
    Title
    Page Content
    you can use Comments field instead of Page Content, it depends on your presentation
    <xsl:template name="News-Articles" match="Row[@Style='News-Articles']"
            mode="itemstyle">
            <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="bodyContent">
                <xsl:call-template name="removeMarkup">
                    <xsl:with-param name="string" select="@PublishingPageContent"/>
                </xsl:call-template>
            </xsl:variable>
    
            <li class="News-Articles">
                <xsl:value-of select="@PublishingRollupImage" disable-output-escaping="yes"/>
                    <a href="{$SafeLinkUrl}">
                        <xsl:value-of select="@Title"/>
                    </a>
                    <xsl:value-of select="substring($bodyContent,1,100)"/> 
                <a href="{$SafeLinkUrl}" mce_href="{$SafeLinkUrl}" title="{@Title}">READ MORE</a>  
            </li>
        </xsl:template>
        <xsl:template name="removeMarkup">
            <xsl:param name="string"/>
            <xsl:choose>
                <xsl:when test="contains($string, '&lt;')">
                    <xsl:variable name="nextString">
                        <xsl:call-template name="removeMarkup">
                            <xsl:with-param name="string" select="substring-after($string, '&gt;')"/>
                        </xsl:call-template>
                    </xsl:variable>
                    <xsl:value-of select="concat(substring-before($string, '&lt;'), $nextString)"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="$string"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:template>

    Add your own styles and that's pretty much it.


As for the content slider you can use any plugin available that auto generates item indicators and prev. next arrows such as http://v3.bxslider.com/

Add CQWP to the page point to the site you need to get content from, set your filters add grouping - grouping generates css class for the list items, below is the generated code from a test CQWP

<ul class="listings">
  <li class="ABOUTUS">ABOUT US
    <ul class="header-column">
      <li class="Vol-Opps"> <a href="#">About Us</a><br>
        
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras sodales urna turpis. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam egestas risus sed justo blandit tincidunt. Cras cursus enim a massa commodo commodo. 
        ( <a title="About Us" href="#">...</a> ) </li>
      <li class="Vol-Opps"> <a href="#">Publications</a><br>
    
       Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras sodales urna turpis. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam egestas risus sed justo blandit tincidunt. Cras cursus enim a massa commodo commodo. 
        ( <a title="Publications" href="#">...</a> ) </li>
      <li class="Vol-Opps"> <a href="#">Newsroom</a><br>
        
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras sodales urna turpis. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam egestas risus sed justo blandit tincidunt. Cras cursus enim a massa commodo commodo. 
        ( <a title="Newsroom" href="#">...</a> ) </li>
    </ul>
  </li>
</ul>

you can hide the group title by using empty Group Header style.

to activate content slider on the above list: (make sure you have .js, .css on your page )

<script type="text/javascript">
  $(document).ready(function(){
    $('.ABOUTUS>ul').bxSlider();
  });
</script>