In my previous blog (Part 1) I wrote about the Content By Query Web Part (CQWP) and the post showed how to create a custom template in ItemStyle.xsl and how to use CSS for styles. This blog (Part 2) shows how to display the latest 5 news per type of news at the start page and how to extend the web part with jQuery in order to separate different types of news with tabs. In the next part (Part III) I plan to write about how to create a jQuery news roller that loops the news one by one for the CQWP.

Click at the image below to activate the video:

This blog do not cover how to configure the CQWP or to modify ItemStyle.xsl or the other XSL files that describes the CQWP, we´re going straight to the core for the fun stuff which means ItemStyle.xsl, CSS and jQuery. Please read the previous post for more information about options for created date, the count word function and the footer.

Some things to consider when the format is to be built:

  • A site column associated to the content type for the page layout
  • Display the created date and the month abbreviated
  • Count words, the title should be displayed by a max number of words and not be cut off in the middle. If the title is longer than 7 words, three dots should be displayed afterwards
  • Header, with tabs for different types of news
  • Footer, with the link More news

Let’s go!

In this example I have two types of news pages, Internal and External. I added a new site column I called ‘NewsCategory’, a choice type column to the Article Page content type. Finally I added this as a content field into the page layout I used for my news pages in the site collection.

When this is done and you have created some example news and it’s time to open up Itemstyle.xsl and create a new template. You will find the complete templates in the end of this blog. Let’s start with how to create the header with the tabs into the template. I used UL and LI for this.

<!-- First row -->
<xsl:variable name="CurPosition" select="count(./preceding-sibling::*)" />
<xsl:if test="count(preceding-sibling::*)=0"> 
<ul class="CQWP-Header tabs">	
	<li id="NewsLink1"><a href="#">Internal</a></li>
	<li id="NewsLink2"><a href="#">External</a></li>
</ul>
</xsl:if>

We also need to create output for dates and titles. I have separated internal news and external news in two DIVs with different class names, Internal and External. This will be useful when we need to create click events in jQuery for the tabs.

<!-- Internal -->
<xsl:if test="@NewsCategory = 'Internal'">
<div class="Internal CQWP-Content">
		<xsl:value-of select="$Created"/>
		<a href="{$SafeLinkUrl}" target="{$LinkTarget}" title="{@LinkToolTip}" >
			<xsl:call-template name="FirstNWords">
        		<xsl:with-param name="TextData" select="$DisplayTitle"/>
       			<xsl:with-param name="WordCount" select="7"/>
        		<xsl:with-param name="MoreText" select="'...'"/>
      		</xsl:call-template>
		</a>
</div> 
</xsl:if>
<!-- External -->
<xsl:if test="@NewsCategory = 'External'">
<div class="External CQWP-Content">
		<xsl:value-of select="$Created"/>
		<a href="{$SafeLinkUrl}" target="{$LinkTarget}" title="{@LinkToolTip}" >
			<xsl:call-template name="FirstNWords">
        		<xsl:with-param name="TextData" select="$DisplayTitle"/>
       			<xsl:with-param name="WordCount" select="7"/>
        		<xsl:with-param name="MoreText" select="'...'"/>
      		</xsl:call-template>
		</a>
</div> 
</xsl:if>

After this it´s time to create functions for the tabs. When the page loads, only Internal news should be displayed, then we need to take care of the click functions for the tabs. In this example I have used FadeTo as effect for the click. Another challenge is to create a background color for an selected tab, as you may know CSS got no pseudo element for ‘selected’, so in this example I have done this with jQuery by adding a class to an element that have been clicked.

Insert this snippet into your custom master page, don´t forget to include a reference to latest jQuery as well.

<script type="text/javascript">
$(document).ready(function() {
 
 // Show and Hide content
  	$(".Internal").show();
  	$(".External").hide();	
  
 // On Click Event first link
 	$('#NewsLink1').click(function() {
    		$('.Internal').fadeTo("normal",0.95);
    		$('.External').hide();
    	return false; 
  	});
 // On Click Event second link
 	$('#NewsLink2').click(function() {
    		$('.External').fadeTo("normal",0.95);
    		$('.Internal').hide();
    	return false; 
  	});

  // Activate the first tab and add the active class + remove & add the active class
	$("ul.tabs li:first").addClass("active").show(); 
	$("ul.tabs li").click(function() {
		$("ul.tabs li").removeClass("active"); 
		$(this).addClass("active"); 
	});

});
</script>

After this it´s time to set the styles with CSS. Copy these classes and paste them in your custom CSS file attached to the master page.

.CQWP-Header, .CQWP-Archive  { 
color:#333;
font-family:Cambria, Georgia;
border-width:1px;
border-color:#bdbdbd;
}
.CQWP-Header {
width:397px;
height:25px;
padding-top:0px;	
padding-bottom:0px;
padding-left:3px;
font-size:12px;
font-weight:bold;  
border-style:solid none dotted none;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e2e2e2', endColorstr='#ebebeb'); 
background: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#e2e2e2)); 
background: -moz-linear-gradient(top,  #ebebeb,  #e2e2e2);
}
.CQWP-Archive {
width:390px;
height:20px;
margin-top:-1px;		
padding-top:5px;
padding-right:10px;	
padding-bottom:0px;
font-size:11px;
text-align:right;
border-style:dotted none solid none;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ebebeb', endColorstr='#e2e2e2'); 
background: -webkit-gradient(linear, left top, left bottom, from(#e2e2e2), to(#ebebeb));
background: -moz-linear-gradient(top,  #e2e2e2,  #ebebeb);
}
.CQWP-Content {
width:390px;
height:22px;
padding-top:7px;	
padding-bottom:0px;
padding-left:10px;
font-family:Cambria, Georgia;
font-size:11px;
color:#333;
border-style:none none solid none;
border-width:1px;
border-color:#e5e5e5;  
background-color:#fff;  
}
.CQWP-Content a:link, .CQWP-Content a:visited {
padding-left:25px;color:green;
}
#NewsLink1	{float:left;margin-right:6px;list-style: none;}
#NewsLink2	{list-style: none;}

ul.tabs {
list-style: none;
border: 1px solid #fff;
}
ul.tabs li {
float:left;
margin:0;
padding:0;
height:24px;
line-height:24px;
border-top:1px solid #e3e3e3;
overflow:hidden;
}
ul.tabs li a {
text-decoration: none;
color:#000;
display:block;
padding:0px 10px 5px 10px;
border-top:1px solid #e3e3e3;
outline: none;
}
ul.tabs li a:hover {
background:#ccc;
border-top:1px solid #e3e3e3;
}	
ul.tabs li.active, ul.tabs li.active a:hover   {
background:#fff;
border-top:1px solid #e3e3e3;
}

Let’ s put this all together, here’s the complete templates for you:

<!-- Begin the word counter Template -->
<xsl:template name="FirstNWords">
  <xsl:param name="TextData"/>
  <xsl:param name="WordCount"/>
  <xsl:param name="MoreText"/>
  <xsl:choose>
    <xsl:when test="$WordCount &gt; 1 and (string-length(substring-before($TextData, ' ')) &gt; 0 or string-length(substring-before($TextData, '  ')) &gt; 0)">
      <xsl:value-of select="concat(substring-before($TextData, ' '), ' ')" disable-output-escaping="yes"/>
      <xsl:call-template name="FirstNWords">
        <xsl:with-param name="TextData" select="substring-after($TextData, ' ')"/>
        <xsl:with-param name="WordCount" select="$WordCount - 1"/>
        <xsl:with-param name="MoreText" select="$MoreText"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:when test="(string-length(substring-before($TextData, ' ')) &gt; 0 or string-length(substring-before($TextData, '  ')) &gt; 0)">
      <xsl:value-of select="concat(substring-before($TextData, ' '), $MoreText)" disable-output-escaping="yes"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$TextData" disable-output-escaping="yes"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<!-- Begin NewsCategory Template -->
<xsl:template name="NewsCategory" match="Row[@Style='NewsCategory']" 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="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="Created">
		<xsl:value-of select="ddwrt:FormatDateTime(string(@ArticleStartDate) ,1033 ,'dd MMMM')" />
	</xsl:variable>
	<xsl:variable name="LinkTarget">
		<xsl:if test="@OpenInNewWindow = 'True'" >_blank</xsl:if>
	</xsl:variable>
<!-- First row -->
<xsl:variable name="CurPosition" select="count(./preceding-sibling::*)" />
<xsl:if test="count(preceding-sibling::*)=0"> 
<ul class="CQWP-Header tabs">	
	<li id="NewsLink1"><a href="#">Internal</a></li>
	<li id="NewsLink2"><a href="#">External</a></li>
</ul>
</xsl:if>
<!-- Internal -->
<xsl:if test="@NewsCategory = 'Internal'">
<div class="Internal CQWP-Content">
		<xsl:value-of select="$Created"/>
		<a href="{$SafeLinkUrl}" target="{$LinkTarget}" title="{@LinkToolTip}" >
			<xsl:call-template name="FirstNWords">
        		<xsl:with-param name="TextData" select="$DisplayTitle"/>
       			<xsl:with-param name="WordCount" select="7"/>
        		<xsl:with-param name="MoreText" select="'...'"/>
      		</xsl:call-template>
		</a>
</div> 
</xsl:if>
<!-- External -->
<xsl:if test="@NewsCategory = 'External'">
<div class="External CQWP-Content">
		<xsl:value-of select="$Created"/>
		<a href="{$SafeLinkUrl}" target="{$LinkTarget}" title="{@LinkToolTip}" >
			<xsl:call-template name="FirstNWords">
        		<xsl:with-param name="TextData" select="$DisplayTitle"/>
       			<xsl:with-param name="WordCount" select="7"/>
        		<xsl:with-param name="MoreText" select="'...'"/>
      		</xsl:call-template>
		</a>
</div> 
</xsl:if>
<!-- Last row -->
<xsl:if test="count(following-sibling::*)=0">
	<div class="CQWP-Footer">
		<div class="CQWP-Archive">
			<a href="#">More news »</a>
		</div>
	</div>
</xsl:if>
</xsl:template>

Stay tune for part III and please drop a comment if you got any questions, Christian

Advertisements