Skip to content

Getting started with REST in SharePoint 2013 – Part II

Welcome to the second post in this series about REST in SharePoint 2013. Please read the first post before you go on to this post Get started with REST in SharePoint 2013 – Part I

In this post I will show you how create a web part with help of REST web service that will display a list of all sub sites immediately below the current site, similar to what you can find under ‘Site Contents’. We’ll also need to have this permission trimmed.

subsites

Before you start scripting and build the HTML and CSS for this, you’ll first need to construct the RESTful HTTP / oData request in order to retrieve the entities, in this case all sub sites of some site. Assume you have a number of sub sites under a site named Projects. Change the domain name and try the following basic query in your browser.

https://contoso.sharepoint.com/projects/_api/web/webs/?$select=title

Once you get the results back in your browser in pure XML and you have construct the query properly with the filters you want, it’s time to create the script that will return the result in JSON format and will create the markup with the styling.

Let’s start

You can use notepad, SharePoint Designer or Visual Studio or the tool of your choice. For example you can just add the following script, the CSS and the jQuery references in one single text file to a folder in your SharePoint environment and use a content editor web part to link to the text file.

Here’s the script that will create a list of all sub sites. You can download the script with the CSS and jQuery references from here.

<div id="listResult"></div>
<script type="text/javascript">
// If the web part will live in the root web or a subsite
if (_spPageContextInfo.webServerRelativeUrl === '/') {
var webUrl = '';
}    
else{
var webUrl = _spPageContextInfo.webServerRelativeUrl;
}
// start ajax
$.ajax({
url: webUrl + "/_api/web/webs/?$select=title,ServerRelativeUrl,Created,effectivebasepermissions&$filter=(effectivebasepermissions/high%20gt%2032)&$orderby=Created desc",

type: "GET",
headers: {"Accept": "application/json;odata=verbose"},
cache:false,
// start success                  
success: function(data){
//console.log(data);
var items = [];
items.push("<ul id='listContainer'>");
items.push("<div id='listHeader'>" + 'Subsites ' + "</div>");     
// if content exist
var dataResult = data.d.results;
if (dataResult.length == 0) {
items.push("<div id='listNoRecords'>" + 'No subsites were found' + "</div>");
}    
else{
// start data.d.results
$(data.d.results).each(function(){
var CreatedDate = moment(this.Created).startOf('hour').fromNow()
items.push('<li id="' + 'listContent' + '">' + 
'<span id="' + 'listContentInner' + '">' + 
'<img src="/_layouts/15/images/SharePointFoundation16.png" />' + ' <a href="' + this.ServerRelativeUrl + '">' +  this.Title + '</a>' +  
'</span>' + 
'<span id="' + 'listContentInnerTime' + '">' + 
' - ' + CreatedDate + 
'</span>' + 
'</li>');			    		
});
// end data.d.results		
}    
// end if content exist
items.push("</ul>");
$("#listResult").html(items.join(''));
}
// end success  
});
// end ajax
</script>
<script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.6.0/moment.min.js"></script>

A couple of things

Filter and sorting

You can filter the oData query by conditions or sort the result, for example:

  • $filter=ID eq 1 (only the object with ID eq to 1)
  • $top=5 (limit to 5 items)
  • $orderby=Created desc (sort by descending order)

There’s a lot of oData operators that are supported in SharePoint’s REST service like numeric comparsions, string comparsions and Date/TIme functions. Read more about this at MSDN.

Add the results to the DOM

All the data in the array are stored in a variable called Items. The trick I used in the script for appending the data to the DOM is to use jQuery’s Push() method, in this way you’ll have good control of the HTML you create.

_spPageContextInfo

In this example I added a condition that will add a slash to the beginning of the URI if it’s not a top site, otherwise I don’t want this trailing slash there. The _spPageContextInfo will simply get the site paths after the domain name.

if (_spPageContextInfo.webServerRelativeUrl === '/') {
var webUrl = '';
}    
else{
var webUrl = _spPageContextInfo.webServerRelativeUrl;
}
url: webUrl + "/_api/web/webs/?$select=title,ServerRelativeUrl,Created,effectivebasepermissions&$filter=(effectivebasepermissions/high%20gt%2032)&$orderby=Created desc",

Date parsing

The REST API in SharePoint returns the date in ISO8601 which means that you’ll get the date and time back in a format like this: 2014-06-30T22:56:00Z. To format date and time in JS is tricky. To avoid this I’ve used a great JS plugin called Moment.js this one will help you and take care of the parsing. MomentJS will also give you the option to display the result in a clean way like 2014-06-30 or for example a format like ‘1 month ago’.

Security trimming

The result from a REST query are not security trimmed so if you want to display only the sites for which the users has access to, you need to secure trim the REST URI with a filter using the EffectiveBasePermissions with a following parameter like this

filter=(effectivebasepermissions/high%20gt%2032)

There’s a permission in SharePoint to allow web service called "Use Remote Interfaces". All users should have this permission to be able to read results from a REST call.

If you have users in the out of the box group ‘visitors’ which have the permission level = Read, you’ll need to add ‘Use Remote Interfaces’ to this permission level. You can find the page with this URL: http://YourSite/_layouts/15/editrole.aspx?role=Read
URI

Do also note that the ‘Use Remote Interfaces’ can be disabled and enabled on the Web Application level in central admin.

Do always test your REST calls for users with different permission levels.

Stay tuned for the next post in this series!

</christian>

Getting started with REST in SharePoint 2013 – Part I

Welcome to my new series about using REST in SharePoint 2013! My intention in writing this is to show some quick and easy to follow examples of how to use REST web services (Representational State Transfer) and oData to access and querying in SharePoint 2013 and all this will be in focused on the user interface, the branding and web development aspects of using REST in SharePoint, like how to retrieve and manipulate list data or site data, how to create ‘data views’, rollups using latest standards of HTML, CSS and jQuery spiced with Ajax.

If you have previously worked with XSLT and data view web parts I hope this series will bring some inspiration to get going with JS for your apps, web parts or pages in SharePoint.

REST-1

This image shows an example of how you can roll up items from a list, toggling for more information and filter by some metadata. More about this in one of the upcoming posts

With REST you can make an http request to get information from different kinds of data sources like a SharePoint list. If you try it in your browser it would be just like going to a website but instead of returning a web page, you will get back the data in XML.

In other words you can easily consume the services in SharePoint that the API offers like list data, social feeds or search if you for example needs to expose its content in an app or similar. REST do also permits the data formats XML or JSON and supports CRUD operations. REST is one of the main APIs that are provided in SharePoint 2013, foundation or server and SharePoint Online but it’s not enabled for a public SharePoint online site over http.

I’ll not going into all the technical details here, read more about REST at Office Dev Center – MSDN library. [http://msdn.microsoft.com/en-us/library/office/jj164022(v=office.15).aspx]

Now let’s look into on how to start use REST/oData to fetch information from a SharePoint list.

Part 1 – A basic example

In this example we’ll examine how to access the REST/oData web services direct in the browser. Just replace the https://contoso/ with your URL. Furthermore make sure you have a document library in the site with the name Documents including some documents. Just make sure you have permission to access this site and the library.

  1. Paste this URL in your browser and hit enter:
    https://contoso/_api/web/lists/getbytitle('Documents')/items?$select=Title

    – the browser will now give you the desired result in XML.

  2. Now it’s time to parse the XML into a human readable format. To do this, I push the objects in the array into HTML and set the style with CSS.

    Use Visual Studio or SharePoint Designer and create an empty .aspx page for example in the root web in SharePoint to try this out. If you prefer you can also add the script, HTML and CSS into a .txt file and link this file by using the content editor web part. This will work in SharePoint Online or in SharePoint on prem, but not for and public site in SharePoint Online with HTTP.

    Download the page here to take a look.

    The key point is the script which looks like this:

$.ajax({
url: "/_api/web/lists/getbytitle('Documents')/items?$select=Title&$top=5",
type: "GET",
headers: {"Accept": "application/json;odata=verbose"},
cache:false,                
success: function(data){
console.log(data);
var items = [];
$(data.d.results).each(function(){
items.push('<ul id="' + 'listUL' + '">' + 
'<li id="' + 'listLI' + '">' + 
this.Title +
'</li>' + 
'</ul>');
});
items.push("</div>");
$("#listResult").html(items.join(''))}
}); 

Note that you need to add an reference to jQuery One thing to note is that the URL have a limitation of 256 characters, for normally usages like according to my examples in this series this shouldn’t be any issues, and if you need to more that the limit allows you can use CSOM with for example an old good CAML query or maybe use an data view web part instead.

In the next post I’ll will write more about how to build the queries with help of the following options:

  • Select
  • Filter
  • Expand
  • Order by
  • Filter
  • Top

I will also show a bit more advanced example of how to create a rollup of ‘the latest 5 blog posts’ on the start page of the home site including HTML and CSS for the UI.

More posts will come and here’s a list of some of the topics I will write about:

  • More examples of how to work with SharePoint lists and site information
  • Tools for site exploring, query building, debugging and JSON viewing
  • How to create and Image slideshow
  • Using REST to get external content
  • CRUD operations (Create Read Update Delete)
  • Using Knockout or Angular for data binding
  • Using DataTables, MixItUp and Moment.js for stuff like sorting, pagination and date parsing
  • Interact to the user profiles with help of SPservices
  • Packing you REST script as an APP

I will be back soon so stay tuned for the next post!

SharePoint Server MVP 2014

I’m very happy to announce that I’ve been renewed with the award SharePoint MVP 2014 by Microsoft for the fourth time in a row!

MVP2014

To receive this award again makes me really proud and of course motivates me to keep on writing articles, speaking at conferences and participate in different projects for the community around SharePoint. Many thanks to Microsoft, my MVP lead, colleagues, friends, readers of this blog and all great people out there in the world wide SharePoint community. If you want to know more about the program, read it from the Microsoft MVP site.

Just as Before, you can count on more posts about SharePoint branding and front end development in general. Recently, I have written a blog series about how to customizing SharePoint 2013 global navigation and next up I planning to write a couple of blogs about REST in SharePoint 2013. I think I’ll write this in the APP perspective using NAPA or VS2013. If you got some ideas here regarding the content, just drop a comment.

Furthermore, maybe we will meet on any SharePoint Conference this year>, the next opportunity will be at SharePoint Saturday in Dubai May 17 where I’ll be speaking about SharePoint Branding.

See you around!

/ Christian

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

Time for the last post in the series about how to customize the global navigation in SharePoint 2013. In this post, you get two new examples of how you can customize the navigation with the help of CSS. This will work for SharePoint 2013, Online or Onprem when using structural navigation.

Nav-Red

Add a nav tag in the master page

I added a nav tag as a container for the SharePoint top menu control. The nav tag is a new tag in HTML 5 and the element should be used for major navigation blocks in the html file. It’s a semantic tag that tells the browser or other reading software such as a search engine that it’s a navigation, compared to a div that just don’t say anything about its content. The CSS is dependent on this nav tag, so if you want to cut & paste, you need to add the nav tag in the master.

<nav>
<SharePoint:AjaxDelta id="DeltaTopNavigation" BlockElement="true" CssClass="ms-displayInline ms-core-navigation" role="navigation" runat="server">
<SharePoint:DelegateControl runat="server" ControlId="TopNavigationDataSource" Id="topNavigationDelegate">
<Template_Controls>
<asp:SiteMapDataSource ShowStartingNode="False" SiteMapProvider="SPNavigationProvider"
id="topSiteMap"	runat="server" StartingNodeUrl="sid:1002"/>
</Template_Controls>
</SharePoint:DelegateControl>
<asp:ContentPlaceHolder id="PlaceHolderTopNavBar" runat="server">
<SharePoint:AspMenu ID="TopNavigationMenu"
Runat="server" EnableViewState="false" DataSourceID="topSiteMap"
AccessKey="<%$Resources:wss,navigation_accesskey%>"
UseSimpleRendering="true" UseSeparateCss="false"
Orientation="Horizontal"
StaticDisplayLevels="2" AdjustForShowStartingNode="true"
MaximumDynamicDisplayLevels="2"	SkipLinkText="" />
</asp:ContentPlaceHolder>
</SharePoint:AjaxDelta>			
</nav>

CSS for the red navigation

In this first example, I use the CSS:after selector to get an arrow and set it's position relative to it's parent element, in this I can set the arrow to a selected element with out the use of a image.

#pageTitle{
display:none
}
nav ul li {
background:#dd4433;
border-left: 1px solid #c73d2e;
text-align: center;
height:55px;
}
nav ul li a {
font:16px/36px Arial, Helvetica, sans-serif;
color: #fff;
width:140px;
height:46px;
}
nav{margin:5px auto}
nav ul.root > li.static > ul.static{
border-left:1px #ee4e3d solid;
}
nav .ms-core-navigation .ms-core-listMenu-horizontalBox li.static >  .ms-core-listMenu-item{
margin-right:10px;
padding-top:7px;
margin:0px 0px 0px 0px
}
nav .ms-core-navigation .ms-core-listMenu-item, nav .ms-core-navigation .ms-core-listMenu-item:link, nav .ms-core-navigation .ms-core-listMenu-item:visited{
color:#fff;
}
nav .ms-core-navigation .ms-core-listMenu-horizontalBox ul.static > li.selected > a > span > span{color:#fff}
nav ul li a:hover{color:#000}
nav li{border-right:1px solid #ee4e3d}
nav li:last-child{border-right:0px solid #ee4e3d}
nav li.selected:after{
content:'';
position:relative;
width:0px;
display:block;
left:60px;
border:10px solid transparent;
border-top:8px solid #d43;
}

CSS for the blue navigation

For this blue navigation I use a smooth CSS gradient and a portion of border radius to get the rounded corners. If you want to adjust the width to be stretched relative to it's content, you can use the out commented paddings instead of the fixed width if you prefer.

Nav-Blue

nav {
overflow:hidden
}
#pageTitle{
display:none
}
nav ul li {
background: #618ba4; /* Old browsers */
background: -moz-linear-gradient(top, #618ba4 0%, #406a82 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#618ba4), color-stop(100%,#406a82)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #618ba4 0%,#406a82 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #618ba4 0%,#406a82 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, #618ba4 0%,#406a82 100%); /* IE10+ */
background: linear-gradient(to bottom, #618ba4 0%,#406a82 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#618ba4', endColorstr='#406a82',GradientType=0 ); /* IE6-9 */
border-left: 1px solid #7395a8;
border-right: 1px solid #406275;
text-align: center;
height:55px;
}
nav ul li a {
font:16px/36px Arial, Helvetica, sans-serif;
color: #fff;
width:140px;
height:46px;
/*padding-right:20px;padding-left:20px*/
}
nav ul li:last-child {
border-right: none;
border-radius: 0px 5px 5px 0px;
-moz-border-radius: 0px 5px 5px 0px;
-webkit-border-radius: 0px 5px 5px 0px;
}
nav {
margin:1px auto;
border-radius:5px;
}
nav ul.root > li.static > ul.static{
border-left:1px #406a82 solid;
}
nav div > div > ul.static > li.static a:hover{
background: #406a82;
height:46px;
}
nav div > div > ul.static > li.static > ul.static > li:hover {
background: #406a82;
}
nav div > ul.root > li.selected a:hover {
background: #406a82!important;
height:55px;
}
nav .ms-core-navigation .ms-core-listMenu-horizontalBox li.static >  .ms-core-listMenu-item{
margin-right:10px;
padding-top:7px;
margin:0px 0px 0px 0px
}
nav .ms-core-navigation .ms-core-listMenu-item, nav .ms-core-navigation .ms-core-listMenu-item:link, nav .ms-core-navigation .ms-core-listMenu-item:visited{
color:#fff;
}
nav .ms-core-navigation .ms-core-listMenu-horizontalBox ul.static > li.selected > a > span > span{
color: #fff;
}

Take a look at the previous posts here:

I hope you had joy of this posts in the series! Please drop a comment if you have any question.

/ Christian

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

Just as in the previous post, here you got some more examples about how you can spice up the global navigation by add some CSS3. In this post I have included five different kind of link effects animations for you to try out. I’ve used tympanus great piece of work ‘Subtle and modern effects for links or menu items’ tympanus.net/Development/CreativeLinkEffects/ and slightly modified this to work with the markup and CSS of SharePoint 2013.

This is an example of how you can work with CSS3 2D transform methods like translate and scale on pseudo elements (before and after). Take a look at my video on you tube to see this five examples in action!

GlobalNav2013tympanus

Let’s start

You need to add a nav tag in your custom master and some CSS in your exteral CSS file, linked from the master page file. You can change the class name for the nav element to one of this five examples, the available numbers are 1,4,7,12 or 19. For example change cl-effect-1 to cl-effect-4 etc. You can download all the CSS and the navigation control here as well.

Add a nav tag in the master page

I added a nav tag as a container for the SharePoint top menu control. The nav tag is a new tag in HTML 5 and the element should be used for major navigation blocks in the html file. It’s a semantic tag that tells the browser or other reading software such as a search engine that it’s a navigation, compared to a div that just don’t say anything about its content.

<nav class="cl-effect-1">

<SharePoint:AjaxDelta id="DeltaTopNavigation" BlockElement="true" CssClass="ms-displayInline ms-core-navigation" role="navigation" runat="server">
<SharePoint:DelegateControl runat="server" ControlId="TopNavigationDataSource" Id="topNavigationDelegate">
<Template_Controls>
<asp:SiteMapDataSource ShowStartingNode="False" SiteMapProvider="SPNavigationProvider"
id="topSiteMap" runat="server" StartingNodeUrl="sid:1002"/>
</Template_Controls>
</SharePoint:DelegateControl>
<asp:ContentPlaceHolder id="PlaceHolderTopNavBar" runat="server">
<SharePoint:AspMenu ID="TopNavigationMenu"
Runat="server" EnableViewState="false" DataSourceID="topSiteMap"
AccessKey="<%$Resources:wss,navigation_accesskey%>"
UseSimpleRendering="true" UseSeparateCss="false"
Orientation="Horizontal"
StaticDisplayLevels="2" AdjustForShowStartingNode="true"
MaximumDynamicDisplayLevels="2" SkipLinkText="" />
</asp:ContentPlaceHolder>
</SharePoint:AjaxDelta>
			
</nav>

And the CSS

/* ---------- NAVIGATION ---------- */
#pageTitle{display:none!important}
/* general */
nav a {
position: relative;
display: inline-block;
margin: 15px 25px;
outline: none;
color: #fff;
text-decoration: none;
text-transform: uppercase;
letter-spacing: 1px;
font-weight: 400;
text-shadow: 0 0 1px rgba(255,255,255,0.3);
font-size: 1.35em;
}
nav a:hover,
nav a:focus {
outline: none;
}
/* effect type */
/* Effect 1: Brackets */
.cl-effect-1 a::before,
.cl-effect-1 a::after {
display: inline-block;
opacity: 0;
-webkit-transition: -webkit-transform 0.3s, opacity 0.2s;
-moz-transition: -moz-transform 0.3s, opacity 0.2s;
transition: transform 0.3s, opacity 0.2s;
font-weight: 900;
font-size:25px
}
.cl-effect-1 a::before {
margin-right: 10px;
content: '[';
-webkit-transform: translateX(20px);
-moz-transform: translateX(20px);
transform: translateX(20px);
}
.cl-effect-1 a::after {
margin-left: 10px;
content: ']';
-webkit-transform: translateX(-20px);
-moz-transform: translateX(-20px);
transform: translateX(-20px);
}
.cl-effect-1 a:hover::before,
.cl-effect-1 a:hover::after,
.cl-effect-1 a:focus::before,
.cl-effect-1 a:focus::after {
opacity: 1;
-webkit-transform: translateX(0px);
-moz-transform: translateX(0px);
transform: translateX(0px);
}
/* Effect 4: bottom border enlarge */
.cl-effect-4 a {
padding: 0 0 10px;
}
.cl-effect-4 a::after {
position: absolute;
top: 100%;
left: 0;
width: 100%;
height: 1px;
background: #0072C6;
content: '';
opacity: 0;
-webkit-transition: height 0.3s, opacity 0.3s, -webkit-transform 0.3s;
-moz-transition: height 0.3s, opacity 0.3s, -moz-transform 0.3s;
transition: height 0.3s, opacity 0.3s, transform 0.3s;
-webkit-transform: translateY(-10px);
-moz-transform: translateY(-10px);
transform: translateY(-10px);
}
.cl-effect-4 a:hover::after,
.cl-effect-4 a:focus::after {
height: 5px;
opacity: 1;
-webkit-transform: translateY(0px);
-moz-transform: translateY(0px);
transform: translateY(0px);
}
/* Effect 7: second border slides up */
.cl-effect-7 a {
padding: 12px 10px 10px;
color: #566473;
text-shadow: none;
font-weight: 700;
}
.cl-effect-7 a::before,
.cl-effect-7 a::after {
position: absolute;
top: 100%;
left: 0;
width: 100%;
height: 3px;
background: #566473;
content: '';
-webkit-transition: -webkit-transform 0.3s;
-moz-transition: -moz-transform 0.3s;
transition: transform 0.3s;
-webkit-transform: scale(0.85);
-moz-transform: scale(0.85);
transform: scale(0.85);
}
.cl-effect-7 a::after {
opacity: 0;
-webkit-transition: top 0.3s, opacity 0.3s, -webkit-transform 0.3s;
-moz-transition: top 0.3s, opacity 0.3s, -moz-transform 0.3s;
transition: top 0.3s, opacity 0.3s, transform 0.3s;
}
.cl-effect-7 a:hover::before,
.cl-effect-7 a:hover::after,
.cl-effect-7 a:focus::before,
.cl-effect-7 a:focus::after {
-webkit-transform: scale(1);
-moz-transform: scale(1);
transform: scale(1);
}
.cl-effect-7 a:hover::after,
.cl-effect-7 a:focus::after {
top: 0%;
opacity: 1;
}
/* Effect 12: circle */
.cl-effect-12 a::before,
.cl-effect-12 a::after {
position: absolute;
top: 50%;
left: 50%;
width: 70px;
height: 70px;
border: 2px solid rgba(0,0,0,0.1);
border-radius: 50%;
content: '';
opacity: 0;
-webkit-transition: -webkit-transform 0.3s, opacity 0.3s;
-moz-transition: -moz-transform 0.3s, opacity 0.3s;
transition: transform 0.3s, opacity 0.3s;
-webkit-transform: translateX(-50%) translateY(-50%) scale(0.2);
-moz-transform: translateX(-50%) translateY(-50%) scale(0.2);
transform: translateX(-50%) translateY(-50%) scale(0.2);
}
.cl-effect-12 a:hover::before,
.cl-effect-12 a:hover::after,
.cl-effect-12 a:focus::before,
.cl-effect-12 a:focus::after {
opacity: 1;
-webkit-transform: translateX(-50%) translateY(-50%) scale(1);
-moz-transform: translateX(-50%) translateY(-50%) scale(1);
transform: translateX(-50%) translateY(-50%) scale(1);
}
/* Effect 18: cross */
.cl-effect-18 {
position: relative;
z-index: 1;
}
.cl-effect-18 a {
padding: 0 5px;
color: #b4770d;
font-weight: 700;
-webkit-transition: color 0.3s;
-moz-transition: color 0.3s;
transition: color 0.3s;
}
.cl-effect-18 a::before,
.cl-effect-18 a::after {
position: absolute;
width: 100%;
left: 0;
top: 50%;
height: 2px;
margin-top: -1px;
background: #0072C6;
content: '';
z-index: -1;
-webkit-transition: -webkit-transform 0.3s, opacity 0.3s;
-moz-transition: -moz-transform 0.3s, opacity 0.3s;
transition: transform 0.3s, opacity 0.3s;
pointer-events: none;
}
.cl-effect-18 a::before {
-webkit-transform: translateY(-20px);
-moz-transform: translateY(-20px);
transform: translateY(-20px);
}
.cl-effect-18 a::after {
-webkit-transform: translateY(20px);
-moz-transform: translateY(20px);
transform: translateY(20px);
}
.cl-effect-18 a:hover,
.cl-effect-18 a:focus {
color: #fff;
}
.cl-effect-18 a:hover::before,
.cl-effect-18 a:hover::after,
.cl-effect-18 a:focus::before,
.cl-effect-18 a:focus::after {
opacity: 0.7;
}
.cl-effect-18 a:hover::before,
.cl-effect-18 a:focus::before {
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
transform: rotate(45deg);
}
.cl-effect-18 a:hover::after,
.cl-effect-18 a:focus::after {
-webkit-transform: rotate(-45deg);
-moz-transform: rotate(-45deg);
transform: rotate(-45deg);
}
/* Effect 19: cross */
.cl-effect-19 {
position: relative;
z-index: 1;
}
.cl-effect-19 a {
padding: 0 5px;
color: #b4770d;
font-weight: 700;
-webkit-transition: color 0.3s;
-moz-transition: color 0.3s;
transition: color 0.3s;
}
.cl-effect-19 a::before,
.cl-effect-19 a::after {
position: absolute;
width: 100%;
left: 0;
top: 50%;
height: 2px;
margin-top: -1px;
background: #0072C6;
content: '';
z-index: -1;
-webkit-transition: -webkit-transform 0.3s, opacity 0.3s;
-moz-transition: -moz-transform 0.3s, opacity 0.3s;
transition: transform 0.3s, opacity 0.3s;
pointer-events: none;
}
.cl-effect-19 a::before {
-webkit-transform: translateY(-20px);
-moz-transform: translateY(-20px);
transform: translateY(-15px);
}
.cl-effect-19 a::after {
-webkit-transform: translateY(20px);
-moz-transform: translateY(20px);
transform: translateY(15px);
}
.cl-effect-19 a:hover,
.cl-effect-19 a:focus {
color: #fff;
}
.cl-effect-19 a:hover::before,
.cl-effect-19 a:hover::after,
.cl-effect-19 a:focus::before,
.cl-effect-19 a:focus::after {
opacity: 0.7;
}
.cl-effect-19 a:hover::before,
.cl-effect-19 a:focus::before {
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
transform: rotate(90deg);	
}
.cl-effect-19 a:hover::after,
.cl-effect-19 a:focus::after {
-webkit-transform: rotate(-45deg);
-moz-transform: rotate(-45deg);
transform: rotate(-90deg);	
}

I hope you had joy of this and please drop a comment if you have any question!

/ Christian

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

In this third post, I will show how you can spice up the global navigation by add some CSS3. If you ever wanted to add some of the new CSS3 attributes like box-shadow or transitions to make some cool effects like animations this is a post for you. Now let’s change the look & feel for the global navigation in SharePoint Server to your heart’s desire!

GlobalNavIII

This example is suitable for SharePoint Server onprem as well as for SharePoint Online. The navigation is built after a structured navigation, there’s no CSS to handle dropdowns. The following CSS code includes transitions, an animation effect that let an element gradually change from one style to another. With this technique you can give the navigation an extra layer of interactivity.

There’s a bunch of sites out there like CSS Deck, CSS-trick, SpeckyBoy, Smashing Magazine etc. where you can find snippets and tutorial to get going with the latest stuff on HTML 5 and CSS 3. Why not find an example and try to implement this in SharePoint. In this post I’ll show you how to take one of this example and modify this a bit to fit it into SharePoint’s markup. Take a look at this example: http://cssdeck.com/labs/large-pressable-css3-navigation now let’s implement this one!

First of all, let’s wrap the SharePoint:AspMenu with a nav tag. Open your custom master and just add this two lines, start and end using the new HTML5 tag (nav) or an old good div if you prefer.

<SharePoint:AjaxDelta id="DeltaTopNavigation" BlockElement="true" CssClass="ms-displayInline ms-core-navigation" role="navigation" runat="server">
<SharePoint:DelegateControl runat="server" ControlId="TopNavigationDataSource" Id="topNavigationDelegate">
<Template_Controls>
<asp:SiteMapDataSource ShowStartingNode="False" SiteMapProvider="SPNavigationProvider" id="topSiteMap" runat="server" StartingNodeUrl="sid:1002"/>
</Template_Controls>
</SharePoint:DelegateControl>
<asp:ContentPlaceHolder id="PlaceHolderTopNavBar" runat="server">
<nav id="nav">
<SharePoint:AspMenu ID="TopNavigationMenu" Runat="server" EnableViewState="false" DataSourceID="topSiteMap" AccessKey="<%$Resources:wss,navigation_accesskey%>" UseSimpleRendering="true" UseSeparateCss="false" Orientation="Horizontal" StaticDisplayLevels="2" AdjustForShowStartingNode="true" MaximumDynamicDisplayLevels="2" SkipLinkText="" />
</nav>
</asp:ContentPlaceHolder>
</SharePoint:AjaxDelta>

And at last it's time for the CSS:

.ms-core-navigation .ms-core-listMenu-horizontalBox li.static >  .ms-core-listMenu-item{
margin-right:1px
}
.ms-core-navigation .ms-core-listMenu-horizontalBox ul.static > li.selected > a > span > span{
color:#CFE1F1
}
#pageTitle{
display:none
}
#nav {
margin:4px auto;
overflow:hidden;
opacity:0.90;
border-radius:5px;
list-style-type:none;
}
#nav ul {
background-color:#2C4A70;
padding:0px 0px 1px 0px;
border-radius:5px;
}
#nav ul li {
height:55px;
}
#nav ul li a {
font:21px/52px Arial, Helvetica, sans-serif;
background-color: #0f6fb2;
background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(15, 111, 178)), to(rgb(34, 65, 112)));
background-image: -webkit-linear-gradient(top, rgb(15, 111, 178), rgb(34, 65, 112));
background-image: -moz-linear-gradient(top, rgb(15, 111, 178), rgb(34, 65, 112));
background-image: -o-linear-gradient(top, rgb(15, 111, 178), rgb(34, 65, 112));
background-image: -ms-linear-gradient(top, rgb(15, 111, 178), rgb(34, 65, 112));
background-image: linear-gradient(top, rgb(15, 111, 178), rgb(34, 65, 112));
filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#0f6fb2', EndColorStr='#224170');
color: #fff;
text-decoration: none;
box-shadow:inset 0 1px 0 #0081bd,inset 0 2px 0 #0078b0,inset 0 3px 0 #0070a3, 0 0 10px rgba(0,0,0,0.2);
box-sizing:border-box;
transition:all .2s ease-in;
-o-transition:all .2s ease-in;
-moz-transition:all .2s ease-in;
-webkit-transition:all .2s ease-in;
}
#nav ul li a {width: 140px}
#nav ul li:first-child a {
-webkit-border-top-left-radius: 5px;
-webkit-border-bottom-left-radius: 5px;
-moz-border-radius-topleft: 5px;
-moz-border-radius-bottomleft: 5px;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
}
#nav ul li:last-child a {
-webkit-border-top-right-radius: 5px;
-webkit-border-bottom-right-radius: 5px;
-moz-border-radius-topright: 5px;
-moz-border-radius-bottomright: 5px;
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
}#nav ul li a:hover {
box-shadow:inset 0 1px 0 #0070a3,inset 0 0 30px 0 #142a4a;
text-shadow:0 1px 3px #143157;
border-bottom:5px solid #0e223d;
}
#nav ul li a span {
border-left:1px solid #143157;
border-right:1px solid #1563a3;
height:100%;
display:block;
text-align:center;
box-sizing:border-box;
}
#nav ul li:first-child a span { border-left: none}
#nav ul li:last-child a span { border-right: none}

Please drop a comment if you have any questions

/ Christian

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

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

It’s time for another blog series and this posts will be centered around how to customize and brand the global navigation in SharePoint 2013 online or on prem. In November 2010, I published three post in this subject for SharePoint 2010, and so far this posts together have generated 165.000 views and 166 comments. These blog entries has become a great success, and I am of course happy to be in any help when you are about to modify the navigation.

Creating a nice looking global navigation is a great way to improve the look and feel of the SharePoint site. A design that is well built and attractive will increase the usability and simply make the users happy! This post is based on a structural navigation in SharePoint 2013 server, and the focus is on the CSS parts. Let’s start with an easy example of how you can add some styling for the global navigation in order to get tabs in the navigation like the image below.

2013-globalnav

Three years have elapsed since the last time, so what has happened since SharePoint 2010 in terms of the global navigation?

  • The rendering markup from the navigation controls with class names has changed slightly
  • SharePoint 2013 is by default CSS3 and HTML 5 friendly
  • New jQuery framework and jQuery plugins to be used
  • Managed navigation that allows us to define the navigation based by Manage metadata

The OOTB markup for the global navigation looks like this:

HTMLnav

It’s still a complex markup and a lot of classes to deal with but let’s start with an easy example just to get going. I have added comments to the classes so you should be able to change for example colors and paddings by your needs. I’ll publish more examples in the next post.

/* --- Global navigation --- */
#DeltaPlaceHolderMain{
margin-top:30px;
}
.ms-breadcrumb-top{
background-color:#f2f2f2;
}
.ms-core-navigation > div > ul.root > li.static a:link, ul.root > li.static a:visited{
font-family:Arial; font-size:16px
}
/* links */
.ms-core-navigation > div > ul.root{
padding-top:8px;
padding-left:8px
}
.ms-core-navigation > div > ul.root > li a{
border:1px #fff solid;
padding:15px 20px 22px 20px;
font-size:15px;
}
.ms-core-navigation .ms-core-listMenu-horizontalBox li.static >  .ms-core-listMenu-item{
margin-right:8px
}
/* links not selected */
.ms-core-navigation > div > ul.root > li.static a:link, ul.root > li.static a:visited{
color:#222
}
/* links selected */
.ms-core-navigation > div > ul.root > li.static > ul.static > li.selected a:link, ul.root > li.static > ul.static > li.selected a:visited{
color:#222;
background-color:#fff
}
/* home link selected */
.ms-core-navigation div.ms-core-listMenu-horizontalBox > ul.static > li.selected a.selected{
border:1px transparent solid;
background-color:#fff
}
/* home */
.ms-core-navigation > div > ul.root > li.static > ul.static{
margin-left:0px
}
/* Hover */
.ms-breadcrumb-top .ms-core-navigation ul.static > li a:hover{
border:1px transparent solid;color:#222;
background-color:#fff
}

The next post in this series will cover

  • More branding examples you can download and use in your SharePoint environment
  • Using a ASP repeater control with jQuery to render custom markup
  • How to use jQuery for various UI effects
  • Branding example for a managed navigation

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

/ Christian

Design Manager in SharePoint – Part IV

Welcome to the fourth post in my series about the Design Manager in SharePoint 2013. Please read the previous posts before you read on.

Design Manager in SharePoint 2013 – Part I
Design Manager in SharePoint 2013 – Part II
Design Manager in SharePoint 2013 – Part III

If you followed the previous post you probably have a branding up and running in your developer machine or maybe in SharePoint online.

Snippets

So what is snippets? It’s a special markup that lets you add .net and SharePoint controls directly in your HTML page. You can add web parts, user controls or just any kind of .net control in your layout. It gives a way to separate code from the design. Ok, let’s take a closer look at the snippets. Go to the preview page and click at the Snippets link in top of the page. Let’s take a look at one of the snippets around, the snippet for the global navigation:

1

This snippet generates 3902 characters and if you just take this as it is you will have to work with a heavy cluttered HTML page not least in the fact that you’ll need a number of snippets onto the page. Well, let’s do something about it and clean it up to readable code. Take not that you don’t have to clean this up because SharePoint strips out the comment tags and all unnecessary stuff in this snippet, but if you working in the HTML document with your favorite text editor, the code over all with be easier and more semantic if you clean the snippets.

2

The corresponding master page that’s in sync with the HTML page will contain this:

3

So what can be cleaned up and what’s about all this SPM, MS and ME comments?
SPM = SharePoint namespace registration, you don’t have to use this close to the snippets and not more than one on the page. It’s enough to have the registration in the top of the page
MS = Markup Start, where a control or a place holder starts
ME = Markup End, where a control or a place holder ends

If you need to add web parts or user controls onto the HTML page, just wrap them the same way as described above, and don’t forget to add the register name space.
I have created a text file containing a pure SharePoint generated snippet for the global navigation and a cleaned version, so it’s just to compare. Download this file here
There’s are more comments you can use, read more about it this at MSDN

That’s all in this series!
/ Christian

Design Manager in SharePoint – Part III

Welcome to this third post in my series about the Design Manager in SharePoint 2013. Please read the previous two posts before you read on testing this post.

Design Manager in SharePoint 2013 – Part I
Design Manager in SharePoint 2013 – Part II

Assuming you have read my previous post about how to map the master page gallery and how to convert your branding assets with help of the Design Manger, you’re now ready to convert your branding assets. If everything works fine including adding snippets, the next step should be to style the snippets so they should have the same look and feel as your original HTML design.

You can download a complete example of a pure HTML branding as well as the result by the Design Manager conversion within a few cleaned snippets. You’ll find the links at the end of this post.

SOL

The next step after you have uploaded and converted your HTML mockup and added the snippets you need, is to create some override CSS classes to make the snippets looks like your mockup. That’s because the snippets inherit their style from SharePoint’s CSS files

For example, let’s say that your HTML looks like this for the top navigation:

<ul class="globalnavigation">
	<li>Services</li>
	<li>About Us</li>
</ul>

When you add the navigation snippet, SharePoint generates this markup:

DOM-explorer

In order to get the snippet to looks like your mockup you’ll need to add some CSS to override what SharePoint renders. Use IE developer toolbar for this task.

Version 0.1

This design is created specific for this blog post and are not fully tested in every scenario or in all browsers and versions, please see this as a first version, and of course, feel free to use it and modify it in the way you want.

I have uploaded this branding at my public SharePoint Online site with help of the WSP file, take a look here: http://swe-public.sharepoint.com

Download the HTML Mockup
Download the Design Manager Converted files
Download the WSP

You can upload the branding files with a WSP file in SharePoint, but if this is about SharePoint Online and a public web site, you will not find any link to the user solution page through the browser, you need to specify this in the URL field: https://-public.sharepoint.com/_catalogs/solutions a public SharePoint online is a bit limited compared to an Intranet site collection in the cloud, but we can count of an evolution in the future.

Next step, detaching the HTML file

I’ll write more about how you can detach the HTML file from its corresponding master page in the next article. Detaching is necessary if you want to include the branding in a Visual Studio branding feature or if you want do edit for example the master page with SharePoint Designer 2013.

Next post [Part IV]

There’s a lot of stuff to cover about the Design Manager, preliminary next up will cover more on snippets and how you can wrap ASP.Net and you own controls into an converted HTML page, how to include web part zones and how to detach the HTML file from its Master Page.

Christian

Follow

Get every new post delivered to your Inbox.

Join 1,207 other followers