Creating your own Content Slider for SharePoint

I wanted to add a little bling to a site I was creating and thought I’d create a content slider. Normally this would just be a list of announcements but since space was a concern, a full list wasn’t going to really work. Surely I thought this was a common enhancement that people have done, so I started Binging. I saw many references to image sliders with limited support for making them work for list items. The only other list based content sliders I saw were server licensed products from companies like Bamboo.

So being the hack programmer I am, I thought to myself, “Build your own content slider you dummy.” Surprisingly, it isn’t that difficult, even for hacks like myself.

This article will show you how to create a content slider based on an Announcements list. This can easily be tailored to fit any custom list with a little tweaking. Interested? No? Well it works in both 2007 and 2010, free and server based products. Interested now? I thought so, let’s get started.

Checklist of what’s needed:

So let’s get started. Download jQuery, SPServices and the jShowOff files and store them in your document library on your SharePoint site. If you already have a scripting center in place, you’ll just need to reference the files that exist there and can add jShowOff into those assets. Where ever they’re stored, get the URLs for those files, it’s time to start script building. I’ll break it out into chunks so I can explain what’s happening, then provide a fill script at the end. Jump there if you’ve been to this type of rodeo before and just need to see the solution.

First, we need to reference all the assets:

<script type="text/javascript" src="http://yourSPDomain/sites/site/library/jQuery.js" ></script>
<script type="text/javascript" src=" http://yourSPDomain/sites/site/library/SPServices.js" ></script>
<script type="text/javascript" src=" http://yourSPDomain/sites/site/library/jShowoff.js" ></script>
<link type="text/css" href=" http://yourSPDomain/sites/site/library/jshowoff.css">

This should point to either the uploaded files in the document library or to your scripting center instance. Also note that in my links, I’ve removed all the version attributes from the jQuery and SPServices file names, as that’s just how I roll. Be sure you’re properly referencing your files with however you like to program.

Second, we need to build some styles to make it look presentable. I freely admit I’m not the best designer in the world, feel free to go crazy with the styling. Make it fit your site theme and or corporate brand.

<style type="text/css">
 .sliderDiv	{margin-left:5px; overflow:hidden;margin-top:5px;}
 .announceTitle {font-weight:bold; border-bottom:3px red solid;}
 .announceBody	{padding-left:20px;}
 .announceFooter {font-size:8pt; color:gray;}
 .announceFooter span {font-style:italic;}
</style>

I’m including these after the jshowoff css so I can override any styling that I don’t particularly like.

Now the script. I’ll do my best to chunk this portion up to minimize overload. First is the declaration of the script, to fire when the page has finished loading and set some variables to use later. Change the emptyResults to be anything you’d like to display if there are no results.

<script type="text/javascript">
$(document).ready(function(){ 
var emptyResults = "<div class='sliderDiv'><p class='announceTitle'>There are no current announcements.</p></div>";
var maxVal = 0;
var toShow = false;
var heightTemp  = 0;

Now the heavy lifting of this solution.

$().SPServices({
    operation: "GetListItems",
    async: false,
    listName: "Announcements",
    CAMLViewFields: "<ViewFields><FieldRef Name='Title' /><FieldRef Name='Body' /><FieldRef Name='Modified' /></ViewFields>",
    CAMLQuery: "<Query><OrderBy><FieldRef Name='Created' /></OrderBy>" +
    		   "<Where><Or><Geq><FieldRef Name='Expires' /><Value Type='DateTime'>" +
               "<Today /></Value></Geq><IsNull><FieldRef Name='Expires' /></IsNull></Or></Where></Query>",
    completefunc: function (xData, Status) {
     var itemCount = $(xData.responseXML).find("[nodeName='rs:data']").attr("ItemCount");
	 if(itemCount > 0){
	  toShow = true;
	  $(xData.responseXML).find("[nodeName='z:row']").each(function() {
     	var modDate = $(this).attr("ows_Modified");
     	modDate = modDate.substr(5, 2) + "/" + modDate.substr(8, 2) + "/" + modDate.substr(0, 4);
     	var titleHtml = "<div class='sliderDiv'><p class='announceTitle'>" + $(this).attr("ows_Title") + "</p>";
     	var bodyHtml = "<p class='announceBody'>" + $(this).attr("ows_Body");+ "</p>";
		var expireHtml ="<p class='announceFooter'>Modified: <span>" + modDate + "</span></p></div>";
		$("#announcements").append(titleHtml + bodyHtml + expireHtml);
       });
	  }
	 else{$("#announcements").append(emptyResults);}
	 }
   });

As you can see, we’re using the GetListItems operation from SPServices to fetch the contents of the Announcments list. We’re telling it to return the Title, Body and Modified date and to retrieve everything with no expiration date or any greater than or equal to Today. Additional fields can be retrieved by simply adding them into the CAMLViewFields section. If you’d like to roll your own CAML, the U2U CAML builder can be used. If you have an existing view created you’d like to use, the Stramit CamlViewer can be used to connect to the list and see the List CAML, as shown in the picture below.

2011-07-09-ContentSlider-01.png

So what is the completefunc doing? Well it’s evaluating the response from the SPServices call. If the ItemCount is greater than zero, we set a variable to true and enter into a loop that builds our announcement divs and appends them to a blank div further down in the code. If no results are returned, the empty message will be added. Fairly straight forward, you can adjust the generated markup if you wish to achieve your desired results, especially if you add more fields into the CAMLViewFIelds.

Last bit of code and we’re there.

if (toShow == true) {
	$('.sliderDiv').each(function() {
		heightTemp = $(this).height();
		if (heightTemp > maxVal) {maxVal = heightTemp};  
	});
	$('#announcements').css('min-height',maxVal);
	$('#announcements').jshowoff({ 
		speed:12000, 
		changeSpeed: 1000,
		controls: false,
		animatePause: false,
		effect: 'none',
		cssClass: false,
		links: false
	});
}

});
</script>
<div id="announcements"></div>

So if results were returned, then the toShow logic will fire. This finds the height of all the divs that were created and sets the min-height of the output div to the maximum height of all the divs. This eliminates jerkiness of page content as the script rotates through the items. Then the jshowoff function executes the rotation. These are the options I chose, feel free to tinker to get the desired results. A full list of the options is listed below, taken from the jShowOff website.

2011-07-09-ContentSlider-02.png

Here are the two images from my slider. You can see the final slider here

2011-07-09-ContentSlider-03.png

2011-07-09-ContentSlider-04.png

To bring it all together, here’s the full script, happy rotating!

<script type="text/javascript" src="http://yourSPDomain/sites/site/library/jQuery.js" ></script>
<script type="text/javascript" src=" http://yourSPDomain/sites/site/library/SPServices.js" ></script>
<script type="text/javascript" src=" http://yourSPDomain/sites/site/library/jShowoff.js" ></script>
<link type="text/css" href=" http://yourSPDomain/sites/site/library/jshowoff.css">
<style type="text/css">
 .sliderDiv	{margin-left:5px; overflow:hidden;margin-top:5px;}
 .announceTitle {font-weight:bold; border-bottom:3px red solid;}
 .announceBody	{padding-left:20px;}
 .announceFooter {font-size:8pt; color:gray;}
 .announceFooter span {font-style:italic;}
</style>

<script type="text/javascript">
$(document).ready(function(){ 
var emptyResults = "<div class='sliderDiv'><p class='announceTitle'>There are no current announcements.</p></div>";
var maxVal = 0;
var toShow = false;
var heightTemp  = 0;
$().SPServices({
    operation: "GetListItems",
    async: false,
    listName: "Announcements",
    CAMLViewFields: "<ViewFields><FieldRef Name='Title' /><FieldRef Name='Body' /><FieldRef Name='Modified' /></ViewFields>",
    CAMLQuery: "<Query><OrderBy><FieldRef Name='Created' /></OrderBy>" +
    		   "<Where><Or><Geq><FieldRef Name='Expires' /><Value Type='DateTime'>" +
               "<Today /></Value></Geq><IsNull><FieldRef Name='Expires' /></IsNull></Or></Where></Query>",
    completefunc: function (xData, Status) {
     var itemCount = $(xData.responseXML).find("[nodeName='rs:data']").attr("ItemCount");
	 if(itemCount > 0){
	  toShow = true;
	   $(xData.responseXML).find("[nodeName='z:row']").each(function() {
        var modDate = $(this).attr("ows_Modified");
        modDate = modDate.substr(5, 2) + "/" + modDate.substr(8, 2) + "/" + modDate.substr(0, 4);
        var titleHtml = "<div class='sliderDiv'><p class='announceTitle'>" + $(this).attr("ows_Title") + "</p>";
        var bodyHtml = "<p class='announceBody'>" + $(this).attr("ows_Body");+ "</p>";
        var expireHtml ="<p class='announceFooter'>Modified: <span>" + modDate + "</span></p></div>";
        $("#announcements").append(titleHtml + bodyHtml + expireHtml);
       });
	  }
	 else      { $("#announcements").append(emptyResults); }
	 }
   });
if (toShow == true) {
	$('.sliderDiv').each(function() {
		heightTemp = $(this).height();
		if (heightTemp > maxVal) {maxVal = heightTemp};  
	});
	$('#announcements').css('min-height',maxVal);
	$('#announcements').jshowoff({ 
		speed:12000, 
		changeSpeed: 1000,
		controls: false,
		animatePause: false,
		effect: 'none',
		cssClass: false,
		links: false
	});
}

});
</script>
<div id="announcements"></div>