Create a jQuery accordion with a SharePoint CQWP

Today we’ll be creating 5 (don’t be scared!) small files that will result in you being able to add a Content Query Web Part to a page, and display the results in a jQuery accordion format. It should look something like this:

Click for a demo or download the source files

Steps to create your own:

Step 1: Add, then Export a standard CQWP

This method of editing a CQWP to do what you want involves no custom coding, no packaging, no .wsp files. All you need to do is go to any page and insert a CQWP Web Part (OOTB). Once it is on your page, click the little black arrow that displays the Web Parts context menu and select Export. This will download a .webpart file called Content. Open this file in your favorite code editor (at the moment mine are Notepad++ for Windows and TextMate for Mac), and go to step 2.

Step 2: Edit the .webpart file to read custom .xsl files

To see the full .webpart file, check out the source code, but basically we’re going to edit 4 lines and put links to our custom .xsl files:

  • Title
  • ItemXslLink
  • MainXslLink
  • XsL

Once you have edited these 4 lines, upload this webpart to the root Web Part gallery by clicking Site Actions > Site Settings > Web parts.

<property name="Title" type="string">Accordion</property>
<property name="ItemXslLink" type="string">/Style Library/XSL Style Sheets/AccordionStyle.xsl</property>
<property name="MainXslLink" type="string">/Style Library/XSL Style Sheets/AccordionCQWP.xsl</property>
<property name="Xsl" type="string">&lt;xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:cmswrt="http://schemas.microsoft.com/WebPart/v3/Publishing/runtime" exclude-result-prefixes="xsl cmswrt x" &gt; &lt;xsl:import href="/Style Library/XSL Style Sheets/Header.xsl" /&gt; &lt;xsl:import href="/Style Library/XSL Style Sheets/AccordionStyle.xsl" /&gt; &lt;xsl:import href="/Style Library/XSL Style Sheets/AccordionCQWP.xsl" /&gt; &lt;/xsl:stylesheet&gt;</property>

Step 3: Create AccordionStyle.xsl

Instead of using SharePoint’s ItemStyle.xsl (not best practice to edit that directly) we’re going to create our own stylesheet (the one we linked to in step 2). It has the same header as ItemStyle.xsl, so feel free to copy from there or from below. However, it only has one template. I’ve called the template Accordion, so when you’re editing the Web Part properties in the browser you’ll see this as the only selectable style in the Presentation pane.

Basically all this style does is wrap the header field (represented by @Title) in a div with a class of accordion-header, and the body field (represented by @Body) in a div with a class of accordion-content. We’ll use these classes later in the jQuery functions.

Once you’ve created this file, put it in /Style Library/XSL Style Sheets/ using SharePoint Designer.

<xsl:stylesheet
  version="1.0"
  exclude-result-prefixes="x d xsl msxsl cmswrt"
  xmlns:x="http://www.w3.org/2001/XMLSchema"
  xmlns:d="http://schemas.microsoft.com/sharepoint/dsp"
  xmlns:cmswrt="http://schemas.microsoft.com/WebParts/v3/Publishing/runtime"
  xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:msxsl="urn:schemas-microsoft-com:xslt">

<!-- Accordion Template -->
    <xsl:template name="Accordion" match="Row[@Style='Accordion']" mode="itemstyle">

       <div class="accordion-header"><xsl:value-of select="@Title"/></div>
	   <div class="accordion-content"><xsl:value-of select="@Body" disable-output-escaping="yes" /></div>

    </xsl:template>
</xsl:stylesheet>

Step 4: Create AccordionCQWP.xsl

The next page we’ll make starts off as a clone of ContentQueryMain.xsl, so go there real quick and copy all of that code into your new file.

There are three things we will do to this code.

  1. Replace dfwp-list with accordion (on lines 32 and 83)
  2. Replace all occurrences of dfwp-item with accordion-item (line 34)
  3. Add (using html character codes…annoying) “expand all” and “collapse all” divs before the list.

Come to think of it, you wouldn’t have to do #3 if you just used jQuery to prepend those buttons to the list. Yeah, that’s the easier way…I’ll update the post soon.

Once you’ve done those 3 edits, upload this file to /Style Library/XSL Style Sheets/ (the same place as the file in step 3)

      <!-- beginning of code from ContentQueryMain.xsl goes here -->
  <xsl:variable name="BeginList" select="string('&lt;ul class=&quot;accordion&quot;&gt;&lt;div class=&quot;expand-all&quot;&gt;Expand All&lt;/div&gt;&lt;div class=&quot;collapse-all&quot;&gt;Collapse All&lt;/div&gt;')" />
  <xsl:variable name="EndList" select="string('&lt;/ul&gt;')" />
  <xsl:variable name="BeginListItem" select="string('&lt;li class=&quot;accordion-item&quot;&gt;')" />
  <xsl:variable name="EndListItem" select="string('&lt;/li&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:variable name="BeginColumn1" select="string('&lt;div class=&quot;expand-all&quot;&gt;Expand All&lt;/div&gt;&lt;div class=&quot;collapse-all&quot;&gt;Collapse All&lt;/div&gt;&lt;ul class=&quot;accordion&quot; style=&quot;width:')" />
      <xsl:variable name="BeginColumn2" select="string('%&quot; &gt;')" />
      <xsl:variable name="BeginColumn" select="concat($BeginColumn1, $cbq_columnwidth, $BeginColumn2)" />
      <xsl:variable name="EndColumn" select="string('&lt;/ul&gt;')" />
      <!-- rest of code from ContentQueryMain.xsl goes here -->

Step 5: jQuery functions

Our jQuery code is going to do several things:

  • Start every content pane hidden and make sure all headers are deactivated
  • When a header is clicked, it toggles the “expanded” class on the header (giving it a different style) and uses slideToggle (a jQuery animation) to show or hide the content pane.
  • It adds functions to the “expand all” and “collapse all” buttons we made earlier

When you’re done copy and pasting (or modifying) this code, save it in /Style Library/scripts/accordion.js. If you’ve got other javascript files there you should consider combining and condensing your code for less calls, but for the sake of this tutorial, it will be a standalone .js file. Once you’ve dropped the file into your system, link to it from the Master Page. Here’s an article on how to call custom javascript from your Master Page.

function accordionLoad() {

	$(".accordion-header").removeClass("expanded");
	$(".accordion-content").hide();

	$(".accordion-header").bind("click", function(){
		$(this).toggleClass("expanded");
		$(this).siblings(".accordion-content").slideToggle();
	})

	$(".expand-all").bind("click",function(){
		$(this).siblings(".accordion").find(".accordion-content").slideDown();
		$(this).siblings(".accordion").find(".accordion-header").addClass("expanded");
	})

	$(".collapse-all").bind("click",function(){
		$(this).siblings(".accordion").find(".accordion-content").slideUp();
		$(this).siblings(".accordion").find(".accordion-header").removeClass("expanded");
	})
}

$(document).ready(function(){
	accordionLoad();
});

side note: I would love to rewrite this jQuery to be a controller, that way it can be re-used across the site anytime somebody adds .accordion() to an element using jQuery.

Step 6: CSS

This is the way I want my accordion to look, so feel free to modify. This is also the style used in the demo of this tutorial.

When you’re done, drop this file in /Style Library/css/accordion.css (again, you could also include this in you main css, but for the sake of the tutorial it’s standalone).

/* Accordion Style
********************************************************** */
ul.accordion {
	list-style:none;
	margin:0px;
	padding:0px;
}
.accordion-item {
	border-top:1px solid #ccc;
}
.accordion-header {
	font-size:1.2em;
	cursor:pointer;
	padding:10px;
}
.accordion-header:hover {
	background:#efefef;
}
.accordion-header.expanded {
	background:#dfdfdf;
}
.accordion-content {
	padding:20px;
}
.expand-all,
.collapse-all {
	display:inline-block;
	cursor:pointer;
	padding:5px 10px;
}
.expand-all:hover,
.collapse-all:hover {
	background:#efefef;
}

Step 7: Putting it all together

So, once you’ve made all of the above files, your structure should look like this:

  • /Style Library/XSL Style Sheets/AccordionStyle.xsl
  • /Style Library/XSL/Style Sheets/AccordionCQWP.xsl
  • /Style Library/scripts/accordion.js
  • /Style Library/css/accordion.css
  • Accordion.webpart (uploaded to the Web Part Gallery)

Now go to your page, add the Accordion Web Part, and use it to display a list of items (FAQs and announcements work great in this format). It should be quite easy to read in the is jQuery Accordion format.

Click for a demo or download the source files

PrettyCal: A better view of a SharePoint Calendar

SharePoint calendars are ugly to look at, and the list views that come OOTB aren’t that great for a quick read. So instead of using a list view, I’ve modified a web part and its XSL links to display all “Upcoming Events” in the following format:

Now let’s learn how! First off, I have to thank the internet as a whole. This is a collection of so many tips and tricks picked up from dozens of discussion boards, blogs, comments, that has helped to come up with the final product. I’ve pasted the final code at the bottom of the post, so feel free to click and skip ahead if you know what you’re doing.

Note: as opposed to splitting the code up among the steps, I’ve put all code at the bottom of the page

Step 1: Create “Nice Date” – a calculated column

First, go to your Calendar Settings and add a column called Nice Date. Set it to Calculated and give it the formula:

=TEXT([Start Time],"yyyy-mm-dd")

Make sure the data type is Date and Time and the Format is Date Only. We need to do this step because we want the header to sort correctly and format nicely in our final product.

Step 2: Create/Export a new Content Query Web Part

You can actually do quite a lot with a CQWP without using Visual Studio or any serious coding. The first thing you’ll need is a standard CQWP web part file. So insert a Content Query Web Part into your page. Once it’s inserted click the little black arrow at the top right and select Export. This will prompt you to download a file named something like Content(1). Remember where this file is, you’ll need it in step 5.

Step 3: Create PrettyCalHeader.xsl

PrettyCalHeader.xsl will be referenced when we modify the Web Part (step 5). The code for this is below, but basically we need to format the header using ddwrt:FormatDateTime. To do this, pay attention to the following line in PrettyCalHeader.xsl. Also, check out the full list of date and time formats on Microsoft’s site.

<xsl:with-param name="GroupName" select="ddwrt:FormatDateTime(string(@*[name()=$Group]), 1033, 'dddd, MMM d yyyy')" />

Step 4: Create PrettyCal.xsl

PrettyCal.xsl is where we get into the display of our data. First we declare the variables, then we wrap in some divs with classes we’ll use later (see the CSS at the end of this page). But there are two pieces that require some thinking. First, we need to display the date differently depending on what the span is. Consider the following options:

  • All Day Event
  • All Day from Jul 1 – Jul 30
  • 3:30PM – 4:30PM
  • Jul 1, 3:00PM – Jul 10, 4:00PM

We need to account for all of those scenarios (no, I’m not counting recurrence, it’s terrible in SharePoint, don’t even consider using it). So to account for those scenarios, check out the flow-chart below.

The bits in single quotes in the flow-chart above signify the ddwrt strings you should use to get the display.

Secondly, we want the “details” link to show a modal dialog box of the display form of the calendar event. So to do that, we’re going to use xsl to set the attributes href and onClick (ok, a little dated I know…but it gets the job done for now). Here’s the tricky part. We need to hard-code (unless you’ve found a better way) the link to the list display form, appended with the item’s ID. It is put inside a SP.UI.ModalDialog.showModalDialog function.

Almost done!

Step 5: Modify the .webpart file

There are 8 lines that you need to replace in the .webpart file you exported from your SharePoint page. See the final code to view details of the changes you’ll need to make.

  • Title
  • AdditionalGroupAndSortFields
  • GroupByFieldType
  • ItemXslLink
  • AdditionalFilterFields
  • GroupStyle
  • HeaderXslLink
  • Xsl

Step 6: Upload, add, and configure the web part in the page

Save, upload and insert your web part into the page and click Edit Web Part.

  • Filter settings: Show items when EndDate is greater than or equal to [Today]
  • Group by: Nice Date (ascending)
  • Sort by: Nice Date (ascending)
  • Limit items (or else you’ll get a lot!)
  • Group Style: DateHeader
  • Item Style: PrettyCal

Don’t forget to fill in your fields to display, and then you’re ready to go!

PrettyCal.webpart (just the edits)

<property name="Title" type="string">PrettyCal</property>
<property name="AdditionalGroupAndSortFields" type="string">Nice_x0020_Date;</property>
<property name="GroupByFieldType" type="string">DateTime</property>
<property name="ItemXslLink" type="string">/Style Library/XSL Style Sheets/PrettyCal.xsl</property>
<property name="AdditionalFilterFields" type="string">EndDate;</property>
<property name="GroupStyle" type="string">DateHeader</property>
<property name="HeaderXslLink" type="string">/Style Library/XSL Style Sheets/PrettyCalHeader.xsl</property>
<property name="Xsl" type="string">&lt;xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:cmswrt="http://schemas.microsoft.com/WebPart/v3/Publishing/runtime" exclude-result-prefixes="xsl cmswrt x" &gt; &lt;xsl:import href="/Style Library/XSL Style Sheets/PrettyCalHeader.xsl" /&gt; &lt;xsl:import href="/Style Library/XSL Style Sheets/PrettyCal.xsl" /&gt; &lt;xsl:import href="/Style Library/XSL Style Sheets/ContentQueryMain.xsl" /&gt; &lt;/xsl:stylesheet&gt;</property>

PrettyCalHeader.xsl

<xsl:stylesheet  
  version="1.0" 
  exclude-result-prefixes="x d ddwrt xsl msxsl" 
  xmlns:x="http://www.w3.org/2001/XMLSchema" 
  xmlns:d="http://schemas.microsoft.com/sharepoint/dsp"
  xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:msxsl="urn:schemas-microsoft-com:xslt">
  
	<xsl:template name="DateHeader" match="*[@GroupStyle='DateHeader']" mode="header">
		<div class="upcoming-groupheader item medium">
			<xsl:call-template name="OuterTemplate.GetGroupName">
				<xsl:with-param name="GroupName" select="ddwrt:FormatDateTime(string(@*[name()=$Group]), 1033, 'dddd, MMM d yyyy')" />
				<xsl:with-param name="GroupType" select="$GroupType"/>
			</xsl:call-template>
		</div>
	</xsl:template>
 
</xsl:stylesheet>

PrettyCal.xsl

<xsl:stylesheet 
  version="1.0" 
  exclude-result-prefixes="x d xsl msxsl cmswrt"
  xmlns:x="http://www.w3.org/2001/XMLSchema" 
  xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" 
  xmlns:cmswrt="http://schemas.microsoft.com/WebParts/v3/Publishing/runtime"
  xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:msxsl="urn:schemas-microsoft-com:xslt">
    
<!-- PrettyCal Template -->
<xsl:template name="PrettyCal" match="Row[@Style='PrettyCal']" mode="itemstyle">
	<xsl:variable name="Start"><xsl:value-of select="@EventDate" /></xsl:variable>
	<xsl:variable name="End"><xsl:value-of select="@EndDate" /></xsl:variable>
	<xsl:variable name="AllDay"><xsl:value-of select="@AllDayEvent" /></xsl:variable>
	<xsl:variable name="Departments"><xsl:value-of select="@ISBDepartment" /></xsl:variable>
	
	<div class="upcoming-events">
    	<h2><xsl:value-of select="@Title" /></h2>
    	<span class="date-time">
    		<!-- check if item is an "All Day Event" -->
    		<xsl:if test="$AllDay = 1">
    			<!-- check if "All Day Event" spans multiple days (by seeing if end date isn't greater than the start date -->
    			<xsl:if test="not(ddwrt:FormatDateTime(string($End), 1033, 'yyyyMMdd') &gt; ddwrt:FormatDateTime(string($Start), 1033, 'yyyyMMdd'))">
    				All Day
    			</xsl:if>
    			<!-- if it spans multiple days, say which days it spans -->
        		<xsl:if test="ddwrt:FormatDateTime(string($End), 1033, 'yyyyMMdd') &gt; ddwrt:FormatDateTime(string($Start), 1033, 'yyyyMMdd')">
					All Day from <xsl:value-of select="ddwrt:FormatDateTime(string($Start), 1033, 'MMM d')" /> - <xsl:value-of select="ddwrt:FormatDateTime(string($End), 1033, 'MMM d')" />
				</xsl:if>
    		</xsl:if>
    		<!-- if item is not "All Day" event -->
	        <xsl:if test="$AllDay = 0">
	        	<xsl:if test="ddwrt:FormatDateTime(string($End), 1033, 'yyyyMMdd') &gt; ddwrt:FormatDateTime(string($Start), 1033, 'yyyyMMdd')">
	        		<xsl:value-of select="ddwrt:FormatDateTime(string($Start), 1033, 'MMM d, h:mm tt')" /> - <xsl:value-of select="ddwrt:FormatDateTime(string($End), 1033, 'MMM d, h:mm tt')" />
	        	</xsl:if>
    			<xsl:if test="not(ddwrt:FormatDateTime(string($End), 1033, 'yyyyMMdd') &gt; ddwrt:FormatDateTime(string($Start), 1033, 'yyyyMMdd'))">
	        		<xsl:value-of select="ddwrt:FormatDateTime(string($Start), 1033, 'h:mm tt')" /> - <xsl:value-of select="ddwrt:FormatDateTime(string($End), 1033, 'h:mm tt')" />
    			</xsl:if>
	        </xsl:if>
    	</span>
    	<br/>
        <a>
        <xsl:attribute name="href">
        	javascript;
        </xsl:attribute>
        <xsl:attribute name="onClick">
        	javascript:SP.UI.ModalDialog.showModalDialog({ url: '/c/Lists/evann/displayevent.aspx?ID=<xsl:value-of select="@ID" />', title: 'Event Details' }); return false;
        </xsl:attribute>
        see details</a>
	</div>
</xsl:template> 
</xsl:stylesheet>

CSS


/*************UPCOMING EVENTS**************/
.upcoming-groupheader {
	font-size:2em;
	border-bottom:1px solid #ccc;
	color:#666;
	margin-top:20px;
	padding-left:40px;
	background:url('/Style Library/Images/calendar.jpg') no-repeat;
}
.upcoming-events h2 {
	font-weight:normal;
}
.date-time {
	font-style:italic;
	color:#666;
}

Intro to branding SharePoint 2010 for designers

I’ve been in the SharePoint world for a couple of years now, and feel like I’m finally able to start seeing clearly what branding in SharePoint really entails. For those of you just getting started, prepare for a long journey. But no need to worry, branding in SharePoint isn’t too scary once you get into it.

I started out (and still do) hand-coding websites. I then progressed to CMS’s like Drupal and WordPress. I have since taken the plunge into SharePoint 2010 as well. If designing a website is like putting together a Lego castle, then designing a website in SharePoint is kind of like putting together a Lego castle where all the pieces are individually wrapped in little plastic bags, and are strangely shaped. It takes a long time to strip away all the “SharePoint-y” stuff to get down to your real design. But once you get there, it’s not so bad.

Not being a developer, SharePoint was a bit daunting at first. A lot of .aspx pages, as well as strange new programs like SharePoint Designer, InfoPath, and Visual Studio (although I don’t use this one). As you begin designing in SharePoint, you’ll want to consider your approach, and it will be slightly different than your typical approach to web design.

Bite-sized pieces

Don’t jump in and start opening every file in SharePoint Designer that you find…you’ll go crazy. Here is my three-step basic process to get started with branding in SharePoint. Move through each step slowly and see how it goes. Once you’re done, you’ll want to repeat the process (probably backwards) to create your own solution.

  1. Apply your own custom CSS
  2. Create new content types & page layouts
  3. Customize/create a new Master Page

Apply your own custom CSS

You’re a designer, so this is something you can be comfortable with as a first step. First, register your CSS file in the master page (all we will touch in the master page for now), and then create a new CSS file in “/Style Library/”. Using the web developer toolbar in Firefox, or Chrome’s built in developer tools, you should have what you need to get started customizing right away. You could do just this step, and be totally fine. However, if you keep digging the grave gets deeper.

Create new content types & page layouts

To keep things clean, I would suggest creating your own content type(s), and from there create unique page layouts for your content. With a page layout you can add your own html wrappers to your content (titles, body text, custom fields, etc.), which gives you that much more control of layout within a page. Also, you can add header styles in these documents to call CSS files and .js scripts without editing a Master Page (not best practice…but it’s possible).

[note] Don’t forget to enable any new page layouts in “Site Settings > Page Layouts and Site Templates” so your pages can use them.

Customize/create a new Master Page

This is the trickiest feat. I would suggest starting with something like Kyle Schaeffer’s HTML5 Master Page, or the Starter Master Pages on CodePlex (I believe by Randy Drisgill and others). My method? I printed out v4.master on giant A3 sheets, along with a couple of other master pages, and sat down at a table, analyzing line by line what I needed to pay attention to, what I was confused about, and what I could edit. So grab a couple of highlighters, print out a sample master page, and get familiar with your blueprint. You’ll learn soon enough what you can and can’t get rid of. A great tip I learned from Heather Waterman at a branding session in Las Vegas one year is to give yourself a bunch of blank space at the beginning of the document, put in your (working) html, and then slowly add in little pieces of the master page as needed. This way you don’t delete stuff you need, and you keep your html intact.

Explore

There is so much more you can do with SharePoint than just CSS and master pages. It gets really fun when you start working with jQuery and interacting with SharePoint services, for example. But that’s for another time. If you want to explore some more about branding in SharePoint, here are a few resources (some articles of mine, as well as other things you might find useful):

SharePoint in Education: an online scheduling solution for conferences

I wanted to give a little preview of a SharePoint 2010 scheduling solution we’re building for a school. The goals of the project are:

  • Online reservation process for parent-teacher conferences
  • Email alerts upon booking, cancellation, and 24hrs before appointment
  • Ability for teachers to block off times where parents can’t come in
  • Hooked into Active Directory so it knows who is logged in
  • Repeatable and scalable

Some of the methods to the madness

  1. Use stripped down .aspx pages
  2. Hook up jQuery Mobile, and jQuery for SPServices
  3. Create individual lists per teacher (from a list template we’ve made)
  4. Create workflows for list actions

Once we’re done I’ll post a video of the full, working solution for you to check out. If you’re needing something like this for your school or workplace, let me know!

Create Custom SharePoint 2010 Table Styles

Let’s take a look at the default (OOTB) table styles that come with SharePoint 2010, and then we’ll create a brand new table style of our own using CSS. If you want a broader look, check out how to integrate custom header and styles.

By default, SharePoint 2010 comes with 3 different table styles that you can select in the ribbon:

Clear (no borders)

Light Banded (Headers and footers have a white background, and alternating blue/white rows)

Medium Two Tones (Headers and Footers in strong blue, and alternating grey/white rows)

These styles are…ok. But we want much better looking tables than the ones Microsoft gives us. So we are going to declare a new style (so it shows up in the drop-down), and style it like we want.

Creating a new Table Style

When the RichHTMLField loads, it looks for the default SharePoint table styles. In order to create a new style, we have to declare a new table class and style name in our CSS so SharePoint knows what to look for.

In order to declare a new table style, you must declare a class that starts with “table.ms-rteTable-” and ends with the name of your table. Within the class you must set a CSS property that SharePoint will see called “-ms-name”. This will set the human-readable name of the table style. See the following example:

table.ms-rteTable-mytable {
-ms-name: "My Custom SharePoint Table Style";
}

Once you have put this in your CSS, refresh your page and click ‘Edit’ and go to the ‘Design’ tab for your table. Now you should see your custom table style (it’ll have no styling attached yet).

Style your new table!

Now that you have this created, it would be good to check all 4 checkboxes for the style (header row, footer row, first column, and last column). Then you should populate your table with at least 5 columns and around 7 or 8 rows. This will allow you to test all of the possible styles on your table.

Here’s what we’ll wind up with. A table that has no border, has a grey header and a lighter grey footer; a light grey border on the bottom of each row; and when you hover over a row it turns light blue.

Full Code

Here’s the CSS. Feel free to copy and make your own. You’ll notice at the bottom a giant commented block at the bottom that has all of the table styles. Keep in mind you might need to add “td”, “th”, and “tr” where you see fit in order to get target the rows and cells correctly.

table.ms-rteTable-mytable {-ms-name:"My Custom SharePoint Table Style";} /* sets the name of the table style */

.ms-rteTable-mytable td,
th.ms-rteTableFirstCol-mytable,
th.ms-rteTableFooterFirstCol-mytable {
	padding:10px;
	text-align:center;
	border-bottom:1px solid #ccc;
}
.ms-rteTableHeaderRow-mytable th {
	background:#ccc;
	color:#333;
	padding:10px;
	text-align:center;
}

.ms-rteTableOddRow-mytable:hover,
.ms-rteTableEvenRow-mytable:hover {
	background:#b5e2ff;
}

.ms-rteTableFooterRow-mytable td,
th.ms-rteTableFooterFirstCol-mytable{
	padding:10px;
	border-top:1px solid #ccc;
	background:#efefef;
}

/*
.ms-rteTable-XXXXX
.ms-rteTableHeaderRow-XXXXX
.ms-rteTableHeaderFirstCol-XXXXX
.ms-rteTableHeaderLastCol-XXXXX
.ms-rteTableHeaderOddCol-XXXXX
.ms-rteTableHeaderEvenCol-XXXXX
.ms-rteTableOddRow-XXXXX
.ms-rteTableEvenRow-XXXXX
.ms-rteTableFirstCol-XXXXX
.ms-rteTableLastCol-XXXXX
.ms-rteTableOddCol-XXXXX
.ms-rteTableEvenCol-XXXXX
.ms-rteTableFooterRow-XXXXX
.ms-rteTableFooterFirstCol-XXXXX
.ms-rteTableFooterLastCol-XXXXX
.ms-rteTableFooterOddCol-XXXXX
.ms-rteTableFooterEvenCol-XXXXX
*/

Is it worth branding SharePoint?

I’m a designer…can you guess the outcome of this? But really, let’s think logically about this before jumping to conclusions :).

Why SharePoint?
Before we decide whether or not branding SharePoint is necessary, we need to all be on the same page as to the purpose of SharePoint. According to Microsoft:

​Microsoft SharePoint 2010 makes it easier for people to work together. Using SharePoint 2010, your people can set up Web sites to share information with others, manage documents from start to finish, and publish reports to help everyone make better decisions. (link)

It’s clear from the beginning that SharePoint is not about form, but about function. It is meant to be a collaborative space where huge numbers of people can effectively communicate and work. And after working with it for a few years, I’ll give it that. It does what it says it will do.


But is it pretty? No.


Why Brand?
Deeper than “why brand SharePoint?”, you have to ask the question, “why brand anything?” Is branding purely for marketing purposes? Is it something you do because “everyone else is doing it?” It has to be more than that. In fact, working in SharePoint provides more incentive than ever to brand.

A typical SharePoint installation could host hundreds or thousands of users. With social networking and collaboration as some of the main components of SharePoint 2010, it means that thousands of your users are replacing water cooler trips and meetings with emails and version control.

In the words of Depeche Mode (which I’m actually listening right now), “people are people;” and for your company to be successful, your people need to be kept happy. If you have thousands of users interacting with an online portal every day, it’s really important that it makes their jobs more efficient and more enjoyable. I believe Microsoft has done a pretty decent job at making things fairly efficient with SP2010…as long as you like clicking ;). Where they lack is in making the process enjoyable. The advertising for SharePoint is far nicer to look at than any SharePoint installation I’ve ever seen. People like to look at nice things, it’s pretty simple. So business owners and decision-makers should be allocating time and effort into branding their portals so their users enjoy using it.

Branding your internal SharePoint portal might seem like a waste of time (after all…why do internal marketing?), but it might bring some unexpected results. And keep in mind, when I say “branding,” I don’t mean sticking your logo in “Site Settings > Title & Description”! Spend time creating an internal branding strategy that serves your users and delights them when they login every morning. If anything, the pressure is much lower…you’re not trying to market to your employees!

A few things to think about:

  • a fresh design can act as a buffer while you create new functionality
  • internal marketing can increase team spirit and camaraderie
  • including fun (not just work!) elements in your design can lighten spirits in a dreary office (don’t be afraid to be cheesy, a lot of people secretly like that stuff!)

So I say “Brand!” It’s really important to your employees that they are able to use a nicely designed system. It lets them know you’re thinking about them. It lets them know someone is actually behind the curtain pulling the wires, and you didn’t just purchase some “system off a shelf.”

Learning Sharepoint 2010 Branding

If you’re looking for a great resource to begin learning how to brand and design in Sharepoint 2010, check out Professional Sharepoint 2010 Branding and User Interface Design. It’s a great read, and if you purchase through my link, it helps pay for my hosting!

Or you can purchase the Kindle Version