Easily add jQuery tabs using the “Reusable Content” feature

This post is quite a fun one. Whilst I was working with a customer today someone came up to me and asked if it was possible to add tabs to their content pages to which I gave it a few seconds thought and I responded “sure that’s absolutely possible – leave it with me!”.

I then spent my commute home thinking about how tabs could be delivered for end-users to make use of without them having to meddle around with any code. Sure getting tabs to work in SharePoint is pretty straight forward and is something we’ve all done at least on a couple of occasions but I give more thought about making it easier for the end-users to consume rather than just meeting the customers requirement by putting in a solution that isn’t pretty nor easy to use.

Solution

I eventually decided to use, what I thought was a very simple approach to giving users the option to use tabs. My solution makes use of the tabs from the jQuery UI (http://jqueryui.com/tabs/) library. It starts with a small modification to the master page that is currently being used. The following code should be added before the closing </head> tag.

[code lang=”html”]
<link href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" rel="stylesheet" />
<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script type="text/javascript" src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script type="text/javascript">
// <![CDATA[
$(function() {
$("#tabs").tabs();
});
// ]]>
</script>
[/code]

I then added the following to the “Reusable Content” list in the root site of the Site Collection where I was adding tabs. Make sure that the “Automatic Update” is unchecked for this piece of reusable content.

Reusable Content item
Reusable Content item
Reusable Content Lists
Reusable Content Lists

Below is the code that should be added to the Reusable HTML field.
[code lang=”html”]
<div id="tabs">
<ul>
<li><a href="#tabs-1">Overtype tab 1 title here</a></li>
<li><a href="#tabs-2">Overtype tab 2 title here</a></li>
<li><a href="#tabs-3">Overtype tab 3 title here</a></li>
</ul>
<div id="tabs-1">Overtype tab 1 content here.</div>
<div id="tabs-2">Overtype tab 2 content here.</div>
<div id="tabs-3">Overtype tab 3 content here.</div>
</div>
[/code]

To add the tabs onto a content page you can simply select the item that has just been added to “Reusable Content” list by clicking on the “Insert” tab whilst editing the page and expanding the “Resumable Content” menu.

Reusable Content menu
Reusable Content menu

Rich text that represents the HTML markup for the tabs is then added onto the page. Each tab is represented by a bullet list item “<li>” and a content area “<div>”. The names of tabs you require can then be added by carefully overtyping the existing tab names. You must be careful not to introduce or remove any markup as this might prevent the tabs from working correctly.

Once you have entered the names of the tabs you can then add the appropriate content by overtyping the content that you wish to include in that tab. This content can consist of rich text such as tables, images and also web parts. Again you must be careful not to introduce or remove any markup. Any tabs that are no longer required can be carefully removed by deleting the bullet list item and content area.

Tabs demonstration
Tabs demonstration

There are other ways to achieve the same result but I thought this was a simple approach using out-of-the-box functionality. Happy tabbing!

Install standalone OneDrive for Business (formally SkyDrive Pro)

Ok, so this has bothered me for sometime – until now, there has been standalone OneDrive for Business SkyDrive Pro client. Users have had to install Office 2013 to experience the new way of synchronising files with SharePoint.

The reason it has bothered me is that it is such a limitation to require the client to be installed in this way. For most organisations it is just not feasible to install the latest and greatest software from day one due to budgets and wider IT constraints, resources and policies where software has to be tested, licensed and patched for example.

Let’s put that aside now as I’m really happy to see that Microsoft released a standalone installer for the OneDrive for Business SkyDrive Pro client earlier this week.

Download

The standalone OneDrive for Business client is available on the Microsoft Downloads site. Both 32-bit and 64-bit versions of the client are available.

The client can also be installed alongside previous versions of Office and can be used to synchronise libraries from SharePoint 2010, SharePoint 2013 and SharePoint Online in Office 365.

Determining the version of your SharePoint Online servers

If you need to check what version of SharePoint server your Office 365 tenant is running especially  during the Office 365 and SharePoint Online service upgrade (aside from checking through the Admin Portal via https://portal.microsoftonline.com) then you can add the following /_vti_pvt/service.cnf to the end of your SharePoint site – as shown below.

https://jcallaghan.sharepoint.com/_vti_pvt/service.cnf

The page will output two lines of text from which we can determine the version of the SharePoint servers. If the second row starts with 14 then you are running SharePoint 2010, if it starts with 15 then you are running SharePoint 2013.

/_vti_pvt/service.cnf output displayed
/_vti_pvt/service.cnf output displayed

SharePoint Online on SharePoint 2010 servers:

vti_encoding:SR|utf8-nl
vti_extenderversion:SR|14.0.0.6120

SharePoint Online on SharePoint 2013 servers:

vti_encoding:SR|utf8-nl
vti_extenderversion:SR|15.0.0.4454

After the service upgrade you may be running SharePoint 2010 on SharePoint 2013 servers (technically known as 14 mode) until you upgrade your site collections to SharePoint 2013 (15 mode).

Security trimmed top navigation links

I was asked to review a client environment yesterday to find out why the links in their top navigation bar were displaying for users that did not have permission to the particular sites.

Creating sites

It turns out that when sites were being created by the client on SharePoint Foundation 2010 they were being created without the ‘include on the top navigation bar’ check box ticked. As a result the link was then not automatically added to the top navigation bar but instead later manually added and so was not a security trimmed link.

Display this site on the top link bar of the parent site
Display this site on the top link bar of the parent site

It was then after removing permissions to the various sites that it became clear that users were able to see the top navigation bar link to the sites even though they did not have access.

Obviously there are situations when users don’t have permissions to a site and you don’t want them to see that the site even exists. An example of this might be in an extranet scenario, when you have third parties accessing project sites and you don’t want those third parties seeing the names of other project sites that may exist let alone the content…so how do we prevent this?

Identifying security trimmed links

By reviewing the URLs of the links in top navigation bar I was able to identify whether the links were security trimmed or not. If the field for the URL is disabled then the link is security trimmed and most probably created when as site was created.

Custom top navigation link that is not security trimmed
Custom top navigation link that is not security trimmed
Security trimmed top navigation link
Security trimmed top navigation link

Adding new security trimmed links

After identifying the problem, I then had to make the existing links security trimmed. I did this in two stages. The first was to make a note of the position of the link that needed to be replaced. I then deleted it from the top navigation bar using the ‘Top Link Bar’ site settings page (_layouts/topnav.aspx). The second stage was then to create the new security trimmed link by using the PowerShell code below.

[code lang=”powershell”]
$SPWeb = Get-SPWeb http://demo.jcallaghan.com/
$Nav = $SPWeb.Navigation.TopNavigationBar
$NewLink = New-Object Microsoft.SharePoint.Navigation.SPNavigationNode -argumentlist @("Site Name", "/sitename/default.aspx")
$Nav.AddAsLast($NewLink)
[/code]

Modify the $SPWeb and @(“Site Name”, “/sitename/default.aspx”) arguments as required and run the code for each of the top navigation bar links that need to be security trimmed. Remember the old link will need to be removed and the new one ordered as required.

Conclusion

It appears SharePoint, specifically SharePoint Foundation 2010 only honours security trimmed links in the top navigation when the links are created automatically as opposed to being created manually.

Note: this post specifically targets SharePoint 2010 Foundation which does not include the extended navigation that is included as part of the Publishing feature.

Hiding an empty rich text column in XSLT

This morning I was trying to create a new style in the itemstyle.xsl stylesheet to use within the content query web part (CQWP). I needed a custom style to display a list of announcements, some of which had content and others didn’t and this style was to improve this output.

The problem is that the ‘Body’ column of an announcement or more importantly the ‘rich text’ field type is never really empty. Even when the column genuinely empty and has no rich text content, a hidden html element (a div) exists and acts as a wrapper for any content. As a result, if you try and use a typical ‘if equals null’ statement to hide the rich text column it won’t work because of this hidden element.

Examples

An empty rich text column on SharePoint 2010 always has 37 characters as shown below.

Empty rich text column in SharePoint 2010
Empty rich text column in SharePoint 2010

With SharePoint 2007 the rich text column has 65 characters when empty, again as shown below.

Empty rich text column in SharePoint 2007
Empty rich text column in SharePoint 2007

Solution

The solution in the end was to use the string-length function to determine if the rich text column was longer than the standard 37 characters on SharePoint 2010 as identified above.

[code lang=”powershell”]
// SharePoint 2007 = 59
// SharePoint 2010 = 37
<!– any conditional formatting would go here –>
<xsl:if test="string-length(@Body) &gt; 37">
<!– conditional formatting and presentation would go here –>
<div class="item body">
<xsl:value-of disable-output-escaping="yes" select="@Body"/>
</div>
</xsl:if>
[/code]