Me & My SharePoint [FrontEnd]

© Christian Stahl – All about SharePoint branding & customizations

Customizing SharePoint 2013 global navigation with CSS and jQuery – Part 2 — December 31, 2013

Customizing SharePoint 2013 global navigation with CSS and jQuery – Part 2

In this second post, I will show how you can create your own markup for the global navigation. This could be a great option when you need to take advantage of HTML 5 tags and additional jQuery plugins that requires simpler markup than SharePoint gives you out of the box.
Alternative to create a complete new control via code, an easy way is to use a standard old good .NET repeater control, instead of the SharePoint:AspMenu control and let the repeater connect to a asp:SiteMapDataSource. To use a repeater control instead of the SharPoint:AspMenu is most likely something suitable for a public SharePoint site.

simple
The repeater gives you a possibility to simplify the markup and just render a minimum of UL and Lis where you can set you own names for IDs or classes.
In order to add a selected class for selected links in the navigation you’ll need to use code behind or java script to do this. The thing here is that JS this will be valid as long as the page is still open, as soon as the user goes to a new page the JS will be reset. To overcome this you can use a cookie or read the URL, parse it, and then add a selected class to the current navigation node or as in this solution just use jQuery with location.pathname to compare the selected link to what’s in the URL.

Ok, if you only need a plain navigation without any dropdown items, replace the old control with this stuff:

<SharePoint:AjaxDelta id="DeltaTopNavigation" BlockElement="true" CssClass="ms-displayInline ms-core-navigation" role="navigation" runat="server">
<SharePoint:DelegateControl runat="server" ControlId="TopNavigationDataSource" Id="topNavigationDelegate"></SharePoint:DelegateControl>
<asp:ContentPlaceHolder id="PlaceHolderTopNavBar" runat="server">
<nav class="SpNav">
<ul id="SpNavUL">
<asp:Repeater ID="GlobalNavMenuItems" runat="server" DataSourceID="topSiteMap">
<ItemTemplate>
<li>
<asp:HyperLink ID="SpNavLinks" runat="server" NavigateUrl='<%# Eval("Url")%>' Text='<%# Eval("Title") %>'></asp:HyperLink>
</li>
</ItemTemplate>
</asp:Repeater>
<asp:SiteMapDataSource ShowStartingNode="False" SiteMapProvider="CombinedNavSiteMapProvider" id="topSiteMap" runat="server" StartingNodeUrl="sid:1002" />
</ul>
</nav>	 
</asp:ContentPlaceHolder>
</SharePoint:AjaxDelta>

And the CSS:

#SpNavUL, #SpNavUL ul {
margin:0;padding:0;list-style:none;
}
#SpNavUL{
margin: 0px auto;
border: 1px solid #222;
background-color: #111;
background-image: linear-gradient(#444, #111);
border-radius: 6px;
box-shadow: 0 1px 1px #777;
}
#SpNavUL:before,
#SpNavUL:after {
content: "";
display: table;
}
#SpNavUL:after {
clear: both;
}
#SpNavUL li {
float: left;
border-right: 1px solid #222;
box-shadow: 1px 0 0 #444;
position: relative;
}
#SpNavUL a {
float: left;
padding: 12px 30px;
color: #999;
text-transform: uppercase;
font: bold 12px Arial, Helvetica;
text-decoration: none;
}
#SpNavUL li:hover > a {
color: #fafafa;
}
.SpNavActive{
color:#04acec!important;
}

And the jQuery:

$(document).ready(function(){
$(function() {
$('#SpNavUL a[href^="/' + location.pathname.split("/")[1] + '"]').addClass('SpNavActive');
});    
});

If you need to display dropdown items in the repeater control you have to use a bit server side script in the repeater to get the child nodes. You need to enable code blocks via web config file to get this working and if you need to do this for a production environment, don’t forget to handle the changes for the web.config in a WSP. Note that you will not be able to modify the web.config file for a SharePoint Online site.

double

Download all the stuff here including how to do with a repeater that includes a drop down menu.

Stay in tune for the next post in this series about the global navigation in SharePoint 2013

Please drop a comment if you have any question or just ideas for the next posts!

/ Christian

User information in SharePoint 2010 with help of the SPCWC control — December 21, 2012

User information in SharePoint 2010 with help of the SPCWC control

In this post I’ll show you how you can retrieve something from the current user’s profile and then do something based of its value with a little help of jQuery and CSS. In this example I have used a typical AD field (office) that are imported into SharePoint’s profile information. You can use any field that exist as a property in the profile information like Country, manager, profile picture or even use a custom property in SharePoint.

workingInLondon

Let’s say we want display something at the Intranet for those users that works in London and display some other stuff for the one’s that works in Paris. This can be used in a many different scenarios, hide/show web parts, controls or fields in the page layout or maybe set a cookie based on the value or do something related to the branding, redirect users to different pages and much more. Hopes this example gives you some ideas for a cool implementation of your own!

Let’s try this out

Use SharePoint Designer 2010 and open the custom master page, your custom CSS file and your JS file.

Masterpage
First you need to declare SPCWC tag prefix in your custom master page. It’s just to include the following line for example just below the last existing tag prefix

<%@ Register Tagprefix="SPSWC" Namespace="Microsoft.SharePoint.Portal.WebControls" Assembly="Microsoft.SharePoint.Portal, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

Then you need to load and make the profile properties available through the pages that are connected to your custom master page. This attribute is needed for some of the properties, but in this example you don’t need it. You can for example paste the following tag just below the existing WebPartPages:SPWebPartManager tag.

<SPSWC:ProfilePropertyLoader id="m_objLoader" LoadFullProfileOfCurrentUser="true" runat="server"/>

Finally it’s time to include the HTML somewhere in your custom master page including the profile property value.

<div class="Office">
<SPSWC:ProfilePropertyValue PropertyName="Office" ApplyFormatting="false" runat="server"/>
</div>
<div class="OfficeOutput IfOffice s4-notdlg"></div>

jQuery
Add the following script in an external JS file referenced from your master page.

$(document).ready(function(){	
var office = $('.Office > span').text();
if(office == 'Stockholm') {
$(".OfficeOutput").show().html('Working in Stockholm!');
}
else if(office == 'London') {
$(".OfficeOutput").show().html('Working in London!');
}
else {
// do something else
} 
});

CSS
Add the following CSS in an external CSS file referenced from your custom master page.

.Office > span{display:none}
.OfficeOutput{display:none}
.IfOffice{
padding:4px; background-color:#304F6D;
color:#fff; font-family:"Segoe UI"; font-size:8pt
}

That’s all, hopes this gives some ideas or inspiration. Please comment if you have questions or if just want to discuss this.
/ Christian

Comment functionality for news pages – Part I — June 30, 2012

Comment functionality for news pages – Part I

If you want to implement comment functionality into the news pages in SharePoint Server 2010, a no code solution with Data Views and portion of jQuery could be a perfect option for you. Alternative you can use the OOTB Note board web part or even use a blog site to get comment functionality but these options limits you if you need to customize such solution in comparison to data views powered with XSLT, jQuery and CSS.

My concept for this is basically to use two connected lists. In the following example I’ll use the Page library in the root site and a custom list called NewsComments. The NewsComments lists have a lookup column (PageID) that connects the ID column in the Pages library. You can do this at a news sub site as well if you prefer.
I am using a data view form web part for the comment textbox in a page layout that sends the comment text, the current page ID, the page title and the page URL to the NewsComments list. Into this Page layout that serves as a template for the news pages, I have created a DVWP that displays all comments related to the current page. Do get this relation I use a parameter with a server variable and a XSL filter that matches current page name to the column in NewsComments list that stores the page names. I do also use some jQuery to grab and populate information on the page and the list.
When you connecting lists with a lookup it gives you the possibility to join content from both lists in a Data View Web Part (joined subview), this can also be useful if you want to create a news rollup that shows the latest news including the number of comments per news item. I’ll write more about such web parts in the next blog.

First step – create the list and a page layout

  • Create a list in the root site of the site collection by the type of Custom List named NewsComments. Create following columns:

    • A column named PageID by the type Lookup. Select Pages in ’Get information from’ and select ID for ’In this column’. Set it to required and click OK.
    • A column named PageTitle by the type Single Line of Text and click OK.
    • A column named Comments by the type multiple lines of text with 5 rows, specify this as Plain text and click OK.
  • Open SPD and create a new page layout and give it the name ’NewsPages’. Don’t forget to give the file a Title. You can copy an existing page layout. Open the page and add or remove the content fields you like the page to have, you can use just Page Content and Title. Add some additional markup; give the elements class names that the jQuery functions needs. Download my example files down below and copy the markup. In my example I have created a Page layout based on the Article Page layout, if you are using a content type like the Enterprise Wiki you have to add tag prefix in the top of the page layout that match the fields you put on the page.
  • Save and publish the file in _catalogs > masterpage folder at the root site. Make sure that it’s available at the root site as a selectable page layout so you can specify this page layout when you create a new page in the root site.
  • Now use the browser and create some pages at the root site, for example name the first on to test1 and the URL will be /Pages/test1.aspx. Use your new page layout as template.

Next step – create a comment in the list

Open the NewsComments list and create a new item, type the URL name of one of the pages you have created in the tile field, for example test1.aspx. Type the filename of the page in the Title field, select the ID of this page, type the title of the page in the PageTitle column and create a comment. You’ll need to do this just to make sure the comments can be connected.

You have now created the basics and were now move the two DVWPs that will display the comments for the pages and make the comment box available. Download my example files if you get stuck, you can just copy the DVWPs and the jQuery and paste them in your page layout.

Next step – create a Data View Web Part that only display comments related to the current news page.

  • Open SPD and the page layout that you just created with SharePoint Designer. Create a DVWP (display Item Form) that get the information from the NewsComments list. Add this DVWP at the bottom of the page just below the last content field. Use no paging, show all objects and show only the column Comments.
  • Create a new parameter as in the image below. The parameter is required to match the current page’s URL name to what caught up in NewsComments list’s Title field.
  • Change the dsQueryRespoinse/Rows variable. If you have a language other than English don’t forget to change name of Pages. Locate the following line:

    <xsl:variable name="Rows" select="/dsQueryResponse/Rows/Row"/>
    

    change to:

    <xsl:variable name="Rows" select="/dsQueryResponse/Rows/Row[@Title=substring-after($ReferPageURL, 'Pages/')]"/>
    
  • Save the page and verify that only the comments appear per page according to what you entered in the NewsComments list.
  • Clean up the DVWP, och add the some markup for presentation.
  • Verify that everything works so far.

Next step – create a form web part

  • Add a DFWP (New Item Form) below the other data view, that get the information from the NewsComments list.
  • Use only following columns: PageID, PageTitle, Title and Comments

Clean the DFWP and give it some markup. As for the other DVWP, it’s important that you use the appropriate markup when jQuery and CSS makes use of class names.

Next step – create the jQuery you need for the comment box in the page layout

The purpose of the following jQuery is to get the page’s ID populated in the dropdown and to populate the Page’s title and URL into the select fields. I have also included a function that show characters left and set a limit to 140 characters.

<script type="text/javascript">
// Limit characters
function limitChars(textid, limit, infodiv){
var text = $('#'+textid).val();    
var textlength = text.length;
if(textlength > limit) {
$('#' + infodiv).html(''+limit+' limit reached');
$('#'+textid).val(text.substr(0,limit));
return false;
}
else {
$('#' + infodiv).html(''+ (limit - textlength) +' characters left');
return true;
}}
$(function(){
$(".FormFieldNewsComments > span > textarea[title='Comments']").keyup(function(){
limitChars(".FormFieldNewsComments > span > textarea[title='Comments']", 140, "LimitInfo");
})
});
	
$(document).ready(function() {
var loc = window.location.href.substr(window.location.href.lastIndexOf("/")+1); // Get the page filename
var PageTitle = $('.PageTitleDiv').html(); // Get the page title
$(".FormFieldNewsTitle > span > input[title='Title']").val(loc); // insert page filename in a CSS hidden formfield
$(".FormFieldPageTitle > span > input[title='PageTitle']").val(PageTitle);	// insert pages title in a CSS hidden formfield
var HiddenInput = $("input[title='PageID']").attr("optHid"); // Lagrar ID till attributet optHid
$("select[title='PageID']").val(_spPageContextInfo.pageItemId); // If less than 20 items i Pages bibl, lägger in ID nr som en selected i DD
$("input[title='PageID']").val(_spPageContextInfo.pageItemId);  // If 20 or more items in Pages lib
$("input[id='" + HiddenInput +"']").attr("value",(_spPageContextInfo.pageItemId)) // Set ID as selected if 20 or more items in Pages lib
});
</script>

Next step – add a few more functions

I added a few additional functions in this example which I think may be helpful and that is the ability to remove own comments and to show number of comments for the page. If you download my example files, this is already included in the DVWPs.

Show the number of comments

<xsl:if test="count($Rows) = 0">No comments yet..</xsl:if>
<xsl:if test="count($Rows) = 1"><xsl:value-of select="$dvt_RowCount" /> Comment</xsl:if>
<xsl:if test="count($Rows) &gt;= 2"><xsl:value-of select="$dvt_RowCount" /> Comments</xsl:if>

Add the following parameter to your XSL style sheet

<xsl:param name="UserID" />

Create these parameter for the rowview template

<xsl:param name="KeyField">ID</xsl:param>
<xsl:param name="KeyValue" select="ddwrt:EscapeDelims(string(@ID))"/>
<xsl:param name="Mode">view</xsl:param>

Match the author to the logged in user

<xsl:if test="@Author.title = $UserID">
<a href="javascript: {ddwrt:GenFireServerEvent(concat('__cancel;__delete={',$KeyField,'=',$KeyValue,'};__commit'))}">DELETE</a>
</xsl:if>

If you want to create a link to the comment list that only administrators should see you can use the DDWRT:IfHasRights() function with an appropriate value

<xsl:if test="ddwrt:IfHasRights(33554432)"><a href="/Lists/NewsComments/AllItems.aspx"><img src="/Style Library/Branding/Images/EditIcon.gif" alt="" /></a></xsl:if>

Next step – branding

The functions for this are now completed and it’s time to give this some visual awesomeness! Download my example files where you find CSS and an image that should get you going.

More to do

There are a lot of things to keep in mind to get this up and I hope you can take this as a base for your own solution and find inspiration. There are many ways to extend this and maybe I’ll publish this to Codeplex for the support and possibilities to further extensions. Maybe it could be an idea to integrate this function with my friend Marc D Anderson’s SPservices SocialDataServices

Download the files

Download my example files here

Part II

In the next blog I’ll show you how to create a news rollup out of this, a joined DVWP that displays the latest news and the number of related comments.

SharePoint 2010 branding examples — November 30, 2011

SharePoint 2010 branding examples

A couple of weeks ago I had two sessions at SharePoint & Exchange forum 2011 about branding in SharePoint and Data Views in SharePoint Designer. SEF was as usual a great event with a lot of good speakers like Marc D Anderson, Penny Coventry, Todd Klindt, Dan Holme, CA Callahan, Göran Husman, Wictor Wilén and many more.

I talked about theoretical aspects of branding like importance, decision points, tools and how to plan for a branding in SharePoint in general in the branding session and I showed how to brand the SharePoint user interface piece by piece, not by how to make dramatic changes to the interface; more about where to start and which classes you can modify per element like:

  • Header area, faded background and height
  • Logo
  • Breadcrumbs
  • Social icons, smaller icons and the added title text with jQuery
  • Global navigation with dropdown
  • Searchbox, custom button, background color and jQuery for replace the default text

As promised during my session about branding, you’ll find all CSS and jQuery you’ll need to create a look and feel like the image above. Please feel free to use this in the way you want.

CSS

Download all the CSS here

Changes in the master page

If you want to display one more level in the fly out for the global navigation

<!-- Global Navigation activate dropdown -->	
<SharePoint:AspMenu
ID="TopNavigationMenuV4"
Runat="server"
EnableViewState="false"
DataSourceID="topSiteMap"
AccessKey="<%$Resources:wss,navigation_accesskey%>"
UseSimpleRendering="true"
UseSeparateCss="false"
Orientation="Horizontal"
StaticDisplayLevels="2"
MaximumDynamicDisplayLevels="2"
SkipLinkText=""
CssClass="s4-tn"/>

In this example I used small icons for the social icons, to do this just add –mini to the Control Id

<!-- Mini Social Icons  -->
<SharePoint:DelegateControl ControlId="GlobalSiteLink3-mini" Scope="Farm" runat="server"/>

The mini extensions means that no text will be displayed, just the icon will show up. I used jQuery to set a custom attribute per icon with first and last child. Paste this jQuery in your custom Master page and don’t forget to add a reference to latest jQuery in the head section of the MasterPage.

<script type="text/javascript">
$(document).ready(function() {
   $(".ms-mini-socialNotif-Container > a:first-child > span > span > IMG").attr({
   	title: "I like",
   	}); 
   $(".ms-mini-socialNotif-Container > a:last-child > span > span > IMG").attr({
   	title: "Tags & note",
   });
  });
</script>

The searchbox button is an image in the dimensions of 37 x 25 px, create you own button or use a background color. I have tested this stuff in latest Firefox, GC and IE 9 and hopes this can give you some ideas and thanks so much to everyone that attended at my sessions, if you have any questions about my presentations, please feel free to contact me.

/ Christian

The Breadcrumb in SharePoint 2010 — October 31, 2011

The Breadcrumb in SharePoint 2010

The breadcrumb in SharePoint is useful just like the other navigation elements like the global navigation. In SharePoint 2010 we have the PopoutMenu control which can be visible if you click at the folder icon in the ribbon. That’s cool, but if you want to display the breadcrumb as a part of every pages without the need to activate it, it just to add a ASP:SiteMapPath control onto your custom masterpage.

SiteMap

There’s no limit when it comes to style the breadcrumb, you can have a custom background and an image that separates the nodes if you like to. In my example I have placed the following code just above the ContentPlaceHolder ‘PlaceHolderMain’ tag in my custom masterpage.

<div class="BreadCrumbWrap s4-notdlg">
<asp:SiteMapPath runat="server" SiteMapProvider="SPContentMapProvider" id="ContentMap"	CssClass="BreadCrumbStyle" PathSeparator="&gt;">
<CurrentNodeStyle CssClass="BreadCurrentNode" />
<PathSeparatorStyle CssClass="BreadPathSeparator" />	
</asp:SiteMapPath>
</div>

Add the following CSS classes to your custom CSS file, referenced from the custom masterpage.

CSS

.BreadCrumbWrap {
margin-top:10px;
}
.BreadCrumbStyle {
padding-left:15px;
font-size:10px;border-bottom:1px #ebebeb dotted;	
padding-bottom:5px;
}
.BreadCrumbStyle a:link, .BreadCrumbStyle a:visited {
color:#3b4f65;
}
.BreadCrumbStyle a:hover{
color:#0072bc; text-decoration:underline
}
.BreadCurrentNode {color:#0072bc}
.BreadPathSeparator{
color:#ccc; padding:0px 8px 0px 8px;
}

/ Christian