Thursday, November 29, 2012

Creating the base Web Part.

  1. Create a new SharePoint 2010 Empty SharePoint Project. Name it MyWebPartProject.
  2. Once it’s been created, click on the project, choose Add > New Item.
  3. Choose the Visual Web Part template and name it MyWebPart.
We’ve now have a very simple Web part that we can build, deploy, and add to our pages in SharePoint. Of course, it wont show anything, but this it shows how simple it is to get a Web part skeleton setup to a compiled, deployable and usable state. Let me explain some of important files we’ll focus on:
  • MyWebPartUserControl.ascx
    This UserControl files take care of all the visual front-end controls and functionality. It’s associated MyWebPartUserControl.ascx.cs file takes care of the code-behind work.
  • MyWebPart.cs
    This file is the class that is used to handle all the behind-the-scenes functionality of your Web part. This where the Web Part is initialized, where it loads up, and references the UserControl.
All the other files that are in your project are necessary for the Web part to function, however you don’t need to touch any of other files to get a custom WebPart (even at a very customized level) working. For now, just focus on the MyWebPart.cs, MyWebPartUserControl.ascx and MyWebPartUserControl.ascx.cs files.

Add some functionality

  1. Add an asp Label Control named lbl_MySelection to the MyWebPartUserControl.ascx file.
  2. Open the MyWebPartUserControl.ascx.cs file and override the OnPreRender method like such and add the following code to it:
    protected override void OnPreRender(EventArgs e)
    {
       base.OnPreRender(e);
       lbl_MySelection.Text = “Please make a selection.”;
    }
  3. Deploy the project to your SharePoint instance
  4. Edit a page and add your Web part to the page
We should now see some text that says, “Please make a selection.” This demonstrates how and where to add custom code to interact with our UserControls’ form controls (in this case our lbl_MySelection label).

Web Part Properties

When you edit a Web part, and the Web part editor pops up in your browser, each one of those options are called properties. We can add our own properties and in real development environments they’re not a novelty but a necessity.
Before we begin with the code, it’s important to understand that there are two major categories to Web part properties:
  • Standard Toolbox Properties
    These are standard text fields, checkboxes, or dropdown lists that are able to receive data from the user and push those values to the Webpart. These do not display dynamic data. For instance: You couldn’t use a standard dropdownlist property to display a list of items from a SharePoint list. This is because the there’s no way to bind data to the dropdownlist, it uses a hard-coded enum in your Web part .CS file (more on this in the example code below).
  • Custom EditorPart Toolbox Properties
    These allow you to build up any type of asp control (or third party control) bind custom data to do (like list data from within SharePoint or an external database) and push these values to the Web part.

Creating Standard Toolbox Properties

  1. Open up your MyWebPart.cs file.
  2. Right before the private const string _ascxPath … declaration, add the following code:
    [WebBrowsable(true),
    Category("Miscellaneous"),
    Personalizable(PersonalizationScope.Shared),
    WebDisplayName("Enter some text")]
    public string CustomTextProp { get; set; }
    The Category seen here can be any existing category within the Web part editor tool pane, or you can type your own custom category. The WebDisplayName option is what the label will say above the property. And of course, the final line is the actual property.
    If we deploy our project now, we will see our property show up in the Web part tool pane when editing the Web part, but it simply is a dummy property area. It doesn’t do anything because we haven’t tied the property to our MyWebPartUserControl. Let’s do that now…
  3. Open the MyWebPartUserControl.ascx.cs file and right before the empty Page_Load() method, add the following property:
    public MyWebPart WebPart { get; set; }
    This will allow us to reference our other MyWebPart.cs class in this ascx code-beind class and ultimately expose the tool pane properties to us.
  4. Back in the MyWebPart.cs file, locate the CreateChildControls() method and replace it with the following:
    protected override void CreateChildControls()
    {
       MyWebPartUserControl control = Page.LoadControl(_ascxPath) as MyWebPartUserControl;
       if (control != null)
          control.WebPart = this;
          Controls.Add(control);
       }
    }
    This looks for our user control on the page and it’s not null, we set the WebPart property (which we created in the previous step). Then we add the usercontrol to the controls collection.
  5. Switch back again to the MyWebPartUserControl.ascx.cs file. Locate the OnPreRender method and replace it with the following:
    protected override void OnPreRender(EventArgs e)
    {
       base.OnPreRender(e);
       if (this.WebPart != null && this.WebPart.CustomTextProp!=null)
       {
          lbl_MySelection.Text = this.WebPart.CustomTextProp.ToString();
       }
    }
    This is the final piece to the puzzle. We’re setting the text field within our Web parts’ user control to the tool pane’s property text field.
Of course, you can do more than just text field type properties (the following code would be implemented in your MyWebPart.cs file:
  • Checkboxes
    [WebBrowsable(true),
    Category("Miscellaneous"),
    Personalizable(PersonalizationScope.Shared),
    WebDisplayName("Checkbox Option Text")]
    public bool CustomCheckboxProp { get; set; }
  • Dropdown Lists
    public enum ddlEnum { option1, option2, option3 }
    [WebBrowsable(true),
    Category("Miscellaneous"),
    Personalizable(PersonalizationScope.Shared),
    WebDisplayName("Dropdown List Display Text")]
    public ddlEnum ddlProp { get; set; }
As you can see so far, the standard tool pane properties are kind of limited; especially the dropdown list: we’re tied to the enumeration. What if we wanted some SharePoint list data feeding that dropdownlist Control? To create fully customized tool pane properties, we need to create our own “EditorPart” and here’s how to do it:

Creating custom EditorPart properties

We’re going to create our own custom DropDownList control EditorPart that feeds in some values from a custom SharePoint list.
  1. In your root SharePoint site, create a new custom list. You can keep the new custom list really simple, or you can add your own custom fields; doesn’t matter. If you’d like to use a already existing list, feel free to reference that list instead.
  2. Open your MyWebPart.cs file and after the private const string _ascxPath declaration add the following code:
    public string _OptionValue { get; set; }
  3. After the whole MyWebPart.cs class declaration, add the following class:
    public class MyEditorPart : EditorPart
    {
       private DropDownList ddl_Options;
       protected override void CreateChildControls()
       {
          base.CreateChildControls();
       }
       public override bool ApplyChanges()
       {
          EnsureChildControls();
          MyWebPart webPart = WebPartToEdit as MyWebPart;
          if (webPart != null)
             webPart._OptionValue=ddl_Panels.SelectedValue.ToString();
          return true;
       }
       public override void SyncChanges()
       {
          EnsureChildControls();
          MyWebPart webPart = WebPartToEdit as MyWebPart;
          if (webPart != null)
             ddl_Options.SelectedValue = webPart._OptionValue .ToString();
       }
    }
    This is the meat and potatoes, if you will, of what makes the custom EditorPart a reality. But there is some more tweaking to do in order for it all to work:
  4. Locate the CreateChildControls() method you created in the code in the previous step. Replace what’s inside with the following:
    base.CreateChildControls();
    ddl_Options = new DropDownList();
    lbl_Options = new Label();
    lbl_Options.Text = “<strong>Choose:</strong><br />:”;
    using (SPSite site = new SPSite(“http://” + Page.Request.Url.Host.ToString()))
    {
       using (SPWeb web = site.OpenWeb())
       {
          SPList Forms = web.Lists["Side Panel Content"];
          SPQuery qry = new SPQuery();
          qry.Query = @”<Query><Where><Gt><FieldRef Name=’ID’ /><Value Type=’Counter’>0</Value></Gt></Where></Query>”;
          SPListItemCollection SPLIC = Forms.GetItems(qry);
          if (SPLIC != null && SPLIC.Count > 0)
          {
             foreach (SPListItem SPLI in SPLIC)
             {
                string OptionTitle = “”;
                string OptionID = “”;
                if (SPLI["ID"] != null)
                   PanelID = SPLI["ID"].ToString();
                if (SPLI["Title"] != null)
                   PanelTitle = SPLI["Title"].ToString();
                if (PanelTitle != “” && PanelID != “”)
                   ddl_Options.Items.Add(new ListItem(OptionTitle, OptionID));
             }
          }
       }
    }
    Controls.Add(lbl_Panels);
    Controls.Add(ddl_Panels);
  5. Now, back in your MyWebPartUserControl.ascx.cs file, add the following line of code to your OnPreRender() method:
    lbl_MySelection.Text = WebPart._OptionValue;
    This will set the label in your Web part’s User Control to the value of the DropDown list in your custom EditorPart tool pane property.

Wednesday, November 7, 2012

Configure User Profile synchronization with Active Directory

Select the User Profile Service and click the Manage button on the ribbon. You should see the screen just like the one below.
SharePoint UPS User Profile Service
Default User
Profile Service configuration window after being created

Select Configure
Synchronization Connections
in the Synchronization section. Now
click the Create new Connection option, if you see the
pop-up window In that case go back to Manage Services on Server and wait until the service starts.
SharePoint UPS User Profile Service
Pop-Up window when
attempting to create the UPS synchronization connection

In the Add New
Synchronization connection window, we will need to fill-in several fields.
In the Connection Name
field enter a descriptive name of your connection, such as AD Synchronization.
In the Forest name field
enter the FQDN name of your domain (in my example: ad.local). Leave
the Auto discover domain controller option selected.
In the Account name, Password,
Confirm Password
,enter credentials for the synchronization account
(sps_ups_sync).
SharePoint UPS User Profile Service
User Profile
Synchronization Connection configuration

Now click the Populate
Containers
button and select your AD organizational units you would like to
import. I’ve selected NetPro and Users OU’s where I usually store
all my users.
SharePoint UPS User Profile Service
User Profile
Synchronization Connection – AD Container selection

Click OK and after a
while you should see your newly created connection listed. We can add
additional properties now, to tell the UPS Service that we do not want to import
AD accounts that are disabled. In my experience this is often requested by clients, so I propose
to make it a default for your setups.
Scroll over your connection name
and expand the menu using the black arrow on the right, then select Edit
Connection Filters
option.
SharePoint UPS User Profile Service
Edit Connection
Filters option under Synchronization connection name

Right now we need to add
exclusion filter for users that are disabled. You need to choose userAccountControl
attribute with Bit on equals operator with filter value 2.
See the screenshot below for the exact config you should perform.
SharePoint UPS User Profile Service
Exclusion
configuration that would prevent importing disabled user accounts

Click the Add button – you
should see your newly created filter listed now. Click the OK button and
go back to the User Profile Service settings window.

Hide Links in Discussion Board Flat Topic View

 hide the “View Properties” and “Reply” icon and text that appears in the far right of the flat topic view in SharePoint 2010.  Here is a CSS style statement to hide both links and the separator image that appears in-between.Snapshot of the flat topic view in a discussion list
/* Discussion Board - Flat topic view
-Hide View Properties and Reply options on far right
*/

table.ms-disc-bar td a[id^="DisplayLink"], /* View Properties link */
table.ms-disc-bar td a[id^="ReplyLink"], /* Reply icon and link */
table.ms-disc-bar td.ms-separator img /* Separator bar */{
display: none;
}
<style type="text/css">
TABLE.ms-disc-bar TD A[id^='DisplayLink'] {
 DISPLAY: none
}
TABLE.ms-disc-bar TD.ms-separator IMG {
 DISPLAY: none
}</style>

Branding

5 PowerShell snippets for SharePoint branders

Just as I wrote in my last blog post I like to collect pieces of code snippets. Sooner or later I’ll found them useful and they could save time and other efforts. My intention with this post is just to share a couple of my snippets and I hope that you’ll found something useful here.
PowerShell is a command-line scripting tool that provides an administrator full access to applicable application programming interfaces (APIs), along with the ability to unlock the capability to interact directly with SharePoint 2010 Products to manipulate Web applications, site collections, sites, lists and much more. So what’s a useful thing to do with PowerShell as a SharePoint brander or a front end developer? Well, there are a lot of different types of tasks you can use PowerShell to, for example populate a list with a large amount of objects when you need to performance test your Data View Web Part or if you need to apply a theme to let’s say some site in the structure including its sub sites or if you need to batch update properties of a collection page layouts.
Maybe you see something that can be written more efficient or if you have some cool snippets of your own you like to share, please drop this in a comment. Take these snippets as they are, try them first in your developer or test environment and feel free to use them and modify in the way you want.
Running PowerShell scripts is easy and you will find many resources out there if you never used PowerShell before, when you know the basics it’s just to go ahead and try these out. This stuff is written for SharePoint 2010 but most of this can be used in SharePoint 2013 as it is.

1. Change Master Page for all sites in the collection

In this example I’ll apply a customer master to all the sites in the site collection, this can be rewritten specific for SharePoint foundation, where PowerShell is much useful for such task. In this snippet I have set V4.master, so have to change the name of the master page file if apply a custom master page.
01# ----- For publishing sites and non publishing sites
02$site = Get-SPSite http://intranet
03foreach ($web in $site.AllWebs) {
04$web; $web.CustomMasterUrl = "/_catalogs/masterpage/V4.master";
05$web.Update(); $web.CustomMasterUrl;
06$web.Dispose()
07}
08foreach ($web in $site.AllWebs) {
09$web; $web.MasterUrl = "/_catalogs/masterpage/v4.master";
10$web.Update(); $web.MasterUrl;
11$web.Dispose()
12}
13$site.Dispose()
14write-host "Complete! V4.master is now applied";

2. Set alternate CSS

In this way you can set a custom CSS file as an alternate CSS at the top site of your site collection, publishing sub sites will inherit the alternate CSS by default.
1$web = Get-SPWeb http://intranet
2$web.AlternateCssUrl = "/Style Library/MyStyles/main.css"
3$web.AllProperties["__InheritsAlternateCssUrl"] = $True
4$web.Update()

3. Set a site logo

With this one you can associate a logo with all sites in the site collection by entering the URL to an image file.
1(get-spsite http://intranet).AllWebs | foreach {
2$_.SiteLogoUrl = "/Style%20Library/MyClient/Images/ClientLogo.png";

4. Set regional setting/locale

This one can be handy when you need to specify the way the site displays numbers, dates, and time. In this example I set locale to Swedish (1053).
1$site = Get-SPSite http://intranet
2foreach ($web in $site.AllWebs) {
3$web; $web.Locale = 1053;
4$web.Update(); $web.Locale;
5$web.Dispose()
6}
7$site.Dispose()

5. Set a theme

This one will set a theme to all sites in the site collection. This script is originally written by my friend MVP Yaroslav Pentsarskyy
01$SiteUrl = "http://intranet"
02$NewTheme = "Azure"
03# Loading Microsoft.SharePoint.PowerShell
04$snapin = Get-PSSnapin | Where-Object {$_.Name -eq 'Microsoft.SharePoint.Powershell'}
05if ($snapin -eq $null) {
06Write-Host "Loading SharePoint Powershell Snapin"
07Add-PSSnapin "Microsoft.SharePoint.Powershell"
08}
09# Setting site themes on sites and sub sites
10$SPSite = Get-SPSite | Where-Object {$_.Url -eq $SiteUrl}
11if($SPSite -ne $null)
12{
13$themes = [Microsoft.SharePoint.Utilities.ThmxTheme]::GetManagedThemes($SiteUrl);
14foreach ($theme in $themes)
15{
16if ($theme.Name -eq $NewTheme)
17{
18break;
19}
20}
21foreach ($SPWeb in $SPSite.AllWebs)
22{
23$theme.ApplyTo($SPWeb, $true);
24Write-Host "Set" $NewTheme "at :" $SPWeb.Title "(" $SPWeb.Url ")"
25}
26}
27Write-Host "Themes updated at:" $SPSite.Url -foregroundcolor Green

More

If you’re a truly SharePoint Designer guy, why not use PowerShell to check if you allowed to do your branding stuff before fire it up…
1Get-SPDesignerSettings -webapplication http://intranet
There’s lot of blogs about using PowerShell in SharePoint but here’s a pic of a few cool scripts that somehow are related to this topic.
N8Design Stefan Bauer – Hide fields from list forms using PowerShell
MSDN Samples Stefan Bauer – version cleanup in SharePoint
Gary Lapointe – Reset Theme
Finally I’d like to give thanks to MVP Cathy Dew for inspiring discussions about this topic; PowerShell from a brander’s perspective as well as I’d like to thanks Falak Mahmood for general discussions and suggestions for the use of PowerShell.
Stay in tune!
Christian
September 27, 2012

10 jQuery snippets for SharePoint 2010

I like to collect pieces of code snippets, sooner or later I’ll found them useful and they could save time and other efforts. My intention with this post is just to share a couple of my snippets and I hope that you’ll found something useful here.
Maybe you see something that can be written more efficient or if you have some cool snippets of your own you like to share, please drop this in a comment. These snippets are all plugin independent and should be easy to follow and modify and they can be used in SharePoint Designer 2010, Visual Studio or be included in a text file in SharePoint linked from a content editor. Don’t forget to create a reference to latest jQuery in the master page or into the text file.
1. Text manipulation
In this example I replace ‘All site content’ with help of the each function.

1/* --- Doc ready ---*/
2$(document).ready(function() {
3$('.ms-splinkbutton-text').each(function(i){ $(this).text($(this).text().replace('All Site Content','More stuff here..'))
4})
2. Check the URL
If the URL contains ‘news’, let’s do something conditionally with JS.
1if(document.URL.indexOf("news") != -1){
2alert("News site");
3} else{
4alert("Not the news site");
5}
Another way is to getting a URL parameter and maybe their values and to something based on a condition with help of jQuery. Let’s give the background different colors depending if the view are sorted by Desc or Asc
01var url = window.location.href;
02/* --- Doc ready ---*/
03$(document).ready(function() {
04if (url.search("&SortDir=Asc") > 0) {
05$(".ms-viewheadertr").css('background-color','lime');
06};
07else if (url.search("&SortDir=Desc") > 0) {
08$(".ms-viewheadertr").css('background-color','yellow');
09};
10/* --- End doc ready ---*/
11});
3. Timestamp
If each page you create needs to have a unique name, you can set a time stamp when it creates. In this example I’ve used year to milliseconds and a random number at the end. This may be useful for a news site with many pages.

01// create a timestamp with random
02var now = new Date();
03var year = now.getFullYear();
04var month = now.getMonth();
05var day = now.getDay();
06var hours = now.getHours();
07var minutes = now.getMinutes();
08var seconds = now.getSeconds();
09var milliseconds = now.getMilliseconds();
10var rand = Math.floor((Math.random()*1000000)+1);
11var pageID = ('ID-')
12var CustomInput = pageID + '' + year + '' + month + '' + day + '' + hours + '' + minutes + '' + seconds + '' + milliseconds + '' + rand;
13 
14/* --- Doc ready ---*/
15$(document).ready(function() {
16$("input[name='ctl00$PlaceHolderMain$nameInput']").val(CustomInput);
17/* --- End doc ready ---*/
18});
If you only want this function for let’s say a news site, you can use an If statement and identify the URL. But don’t forget that URL can be changed.
1/* --- Doc ready ---*/
2$(document).ready(function() {
3if(document.URL.indexOf("news") != -1) {
4// Unique page title
5$("input[name='ctl00$PlaceHolderMain$nameInput']").val(CustomInput);
6} else{}
7/* --- End doc ready ---*/
8});
4. Change the attribute
Let’s say you want to change for example the title tag for the ‘I Like It’ button, you can do like this to set a custom attribute.

1/* --- Doc ready ---*/
2$(document).ready(function() {
3$(".ms-socialNotif-Container > a").attr({
4title: "Click the button if you like this page",
5});
6/* --- End doc ready ---*/
7});
5. Change CSS
Let’s change the header text to red if the name is Link.
1/* --- Doc ready ---*/
2$(document).ready(function() {
3$(".ms-WPTitle span:contains('Links')").css("color", "red");
4});
Another way is to use a condition and a variable for this, if the web part header is equal to Shared Documents set the color to green, if the text is eq to Link set a border around the web part and set the text to red color. Normally I set the CSS into a CSS file, and you can use addClass to set the class as an option to set the CSS inline the script if you like.

01/* --- Doc ready ---*/
02$(document).ready(function() {
03var WPtitle = $('.ms-WPTitle span');
04for (var i = 0; i <= WPtitle.length; i++) {
05if ($(WPtitle[i]).text() == 'Links') {
06$(WPtitle[i]).css({'color': 'red'});
07$(WPtitle[i]).parents().eq(10).css({'border': '1px black solid!important'});
08}
09else if ($(WPtitle[i]).text() == 'Shared Documents') {
10$(WPtitle[i]).css({'color': 'green'});
11}}
12/* --- End doc ready ---*/
13});
6. Add expand / collapse web parts
The following code will get expand/collapse for all standard web parts.

01/* --- Doc ready ---*/
02$(document).ready(function() {
03$(function($) {
04$('.s4-wpTopTable').find('tr:first h3').append('<a class=\'min\' style=\'float:left; margin-right:5px\'><img src=\'/_layouts/images/collapse.gif\'/></a>');
05var Collapse = "/_layouts/images/collapse.gif";
06var Expand = "/_layouts/images/expand.gif";
07$('.min').click(function(){     
08var img = $(this).children();
09$(this).closest('.s4-wpTopTable').find('tr:first').next().toggle().is(":visible") ? img.attr('src',Collapse) : img.attr('src',Expand );
10});
11});
12});
7. Modify form field
jQuery can be used in many ways for standard list forms in SharePoint and this fist example shows how to set read only, a color and a specific width for the title field in edit mode.

1/* --- Doc ready ---*/
2$(document).ready(function() {
3$("input[title='Title']").attr("readonly","true").css('background-color','#ccc').width(70);
4/* --- End doc ready ---*/
5});
Next example shows how to set a field limit and add a counter that shows number of characters left

01// Show Nr of Characters left in a common list field
02(function($){ 
03$.fn.fieldLimit = function(options) { 
04return this.each(function() { 
05var characters = 30;
06$(this).keyup(function(){
07if($(this).val().length > characters){
08$(this).val($(this).val().substr(0, characters));
09}  
10var remaining = characters - $(this).val().length;
11$(options.result).html(remaining + " characters left");        
12});
13}); 
14}; 
15})(jQuery);
16 
17/* --- Doc ready ---*/
18$(document).ready(function() {
19$('.ms-formtable').prepend("<div class='CharactersLeft'></div>");
20$('input[title$=Title]').fieldLimit({
21result:".CharactersLeft",
22});
23/* --- End doc ready ---*/
24});
8. Check site template
If you need to do something based on which site template a site has been created from, you can identify this with help of the site template ID. I have only covered a few templates below.
01/* --- Doc ready ---*/
02$(document).ready(function(){
03CurrentTemplate = g_wsaSiteTemplateId;
04TeamSite = 'STS#0'
05EnterpriseWiki = 'ENTERWIKI#0';
06PublishingSite = 'CMSPUBLISHING#0';
07if (CurrentTemplate == TeamSite){
08alert('Im a Team site');}
09else if (CurrentTemplate == EnterpriseWiki){
10alert('Im a Enterprise Wiki');}
11else if (CurrentTemplate == PublishingSite){
12alert('Im a Publishing Site');}
13else {
14alert('Sitetemplate not defined yet..');}
15/* --- End doc ready ---*/
16});
9. Welcome message
This example shows how to work with variables. You’ll also find some plain old good JS date stuff that can be useful when you need to check times.

01/* --- Doc ready ---*/
02$(document).ready(function(){
03var WelcomeMenuContent = $('.ms-welcomeMenu > a.ms-menu-a > span');
04var UserName = WelcomeMenuContent.text();
05var FirstName = UserName.split(" ")[0];
06var Display;
07var Digital = new Date()
08var Hours = Digital.getHours()
09Morning = 'Good morning' + " " + FirstName;
10Lunch = 'Lunch time' + " " + FirstName;
11Evening = 'Good evening' + " " + FirstName;
12Night = 'Time to go home' + " " + FirstName;
13TimeElse = 'Welcome' + " " + FirstName;
14if (Hours >= 5 && Hours <= 11)
15WelcomeMenuContent.text(Morning);
16else if (Hours == 12)
17WelcomeMenuContent.text(Lunch);
18else if (Hours >= 13 && Hours <= 17)
19WelcomeMenuContent.text(Evening);
20else if (Hours >= 18 && Hours <= 23)
21WelcomeMenuContent.text(Night);
22else
23WelcomeMenuContent.text(TimeElse); 
24/* --- End doc ready ---*/
25});
10. Append today’s date
While we’re talking about get date with JS, let’s see how you can use this to display current date somewhere at the page like this.

1var d = new Date();
2var month = d.getMonth();
3var date = d.getDate();
4var year = d.getFullYear();
5/* --- Doc ready ---*/
6$(document).ready(function() {
7$('.s4-pagedescription').append("<div style='float:right'>" + month + "/" + date + "/" + year + "</div>");
8});
Stay in tune!
/ Christian Ståhl
August 31, 2012

Use jQuery & cookies in SharePoint 2010

In this article I’ll show you how to use Cookies in jQuery for your SharePoint Designer 2010 no code applications.
With help of a cookie you can write information to the user’s computer and this can be useful if you need to store stuff like visitors preferences, for example if the user has checked a check box or not at some page. Cookies can be very useful in many ways, but in some situations you need to write such information to the server like a database instead, cookies should not be used for critical information or any kind of sensitive information especially at a public faced site. However a cookie can be a great choice for many tasks in your front end development.
Some examples of the usefulness of a cookie
  • Change color schemes
  • Hide / Show elements at the page
  • Resizing fonts, scale up or down
  • Form, auto save inputs in fields, selected check box or radio button
  • Accordion / tabs, remember last state of collapsed/opened
  • Navigation, remember the last location
  • Welcome message, for example if you want to show a popup only once at specific date at the start page.
jQuery doesn’t support cookies natively but you can use a super small plugin called ‘jquery.cookie.js’  that contains all kind of basic functions and options you’ll need for your scripting. This plugin is also included in jQuery UI development-bundle.
Jquery.cookies gives a couple of options like:
  • Expires
    The lifetime for the cookie. You can use a number of days or a specific date. If omitted, the cookie is a session cookie
  • Path
    Where the cookie is valid. If you want it to be valid at every site in the site collection, just use a slash /, if you want it to be valid at let’s say only the news site set e.g /news/

Get going

Let’s start with a simple example just to get going, the following example will set the top row to a red or green background color depending of which link you click. Let’s say you clicked at green one and then reload the page, the green background color will remain. If you restart the browser, the top row will be white again. This script do not have any expired date, therefore, the cookie will expire automatically when you close the browser.
Let’s try this out:
Download jquery.cookies.js and create a reference to this file in your custom master, don’t forget to include an reference to latest jQuery API as well.
HTML
Put this somewhere in your custom master page
1<!-- Session -->
2<div class="Wrapper">
3    <div class="Red">Red</div>
4    <div class="Pipe">|</div>
5    <div class="Green">Green</div>
6</div>
jQuery
Put this in an external JS file referenced from your master page
01$(document).ready(function() {
02 
03// Click red
04$('.Red').click(function() {
05$('.Wrapper').css("background-color","red");
06$.cookie('Wrapper', 'red');
07});
08 
09// Click green
10$('.Green').click(function() {
11$('.Wrapper').css("background-color","green");
12$.cookie('Wrapper', 'green');
13});
14 
15// Cookies
16var Wrapper = $.cookie('Wrapper');
17if (Wrapper == 'red') {
18$('.Wrapper').css("background-color","red");
19};
20if (Wrapper == 'green') {
21$('.Wrapper').css("background-color","green");
22};
23 
24});
CSS
Put this in an external CSS file referenced from your master page
01.Wrapper{
02width:100%;height:16px;
03background-color:#fff;color:#000;
04}
05.Red{
06cursor:pointer;padding-left:5px;
07float:left;
08}
09.Green{
10cursor:pointer;float:left;
11}
12.Pipe{
13float:left;padding:0px 5px 0px 5px
14}
Maybe you want to set the cookie to a life span of 2 days, take a look at the jQuery script and the part where you set the name and the property:
1$.cookie('Wrapper-', 'Green-');
Just add a path and a value; a number or a specific date, this will create the cookie

1$.cookie('Wrapper-', 'Green-', {path: '/', expires: 2});
Take a look at the cookie in your disk, if you are using IE, you will find it through this path

1C:\Users\...\AppData\Local\Microsoft\Windows\Temporary Internet Files
The file will contain the name of the cookie, the property and the path like this

1Wrapper-Green-ecmtest67/108815182001923024639810215318430245996*

How to use cookies in a Data View web part

If we take this a step further and try to use cookies in a typical news roller DVWP. In this example, If you click at the icon next to the header for a news item that section will disappear, a kind of ‘I Have Read This’ function. At the bottom of the web part there’s a reset link that will delete the cookie.

The HTML part of the DVWP, it’s important to use @ID for the id, classes and href as the script shows
01<div class="NewsRow {@ID}">
02<div class="NewsContentContainer">           
03<div class="NewsTitle">
04<div class="NewsHider"><a href="{@ID}" id="{@ID}"><img alt="" src="/Style%20Library/Custom/Images/IhaveReadThis.png" width="22" height="22" /></a></div>
05<div class="NewsTitleInner"><a href="/news/Pages/{@LinkFilename}"><xsl:value-of select="@Title" /></a></div>
06<div class="GeneralClearBoth"></div>
07</div>       
08</div>
09<div class="NewsAuthorCreatedWrap">
10<span class="NewsAuthor">By <xsl:value-of select="@PublishingContact.title" />,</span> <span class="NewsCreated"><xsl:value-of select="@ArticleStartDate" /></span>
11</div>
12<div class="NewsContent">
13<xsl:call-template name="FirstNWords">
14<xsl:with-param name="TextData" select="$DescText"/>
15<xsl:with-param name="WordCount" select="15"/>
16<xsl:with-param name="MoreText" select="'...'"/>
17</xsl:call-template>
18</div>
19</div>
The jQuery goes here
01jQuery(function ($) {
02var removedLinks = 'removedLinks'
03,Options = {
04expires: 7,
05path: '/news'
06},
07c=$.cookie(removedLinks)||'#DebuggingCode'
08$(c).remove();
09$(".NewsHider a").click(function (e) {
10e.preventDefault();
11var LinkClass = '.'+ $(this).attr('id'),
12removeLinksClasses=c.split(',')
13$(LinkClass).remove()
14removeLinksClasses.push(LinkClass)
15c=removeLinksClasses.join(',')
16$.cookie(removedLinks, c, Options)
17});
18$('#NewsResetCookie').click(function(){
19$.cookie(removedLinks,'',{expires:-1,path:'/news'})
20})
21});
If you prefer to use this in the ItemStyle.xsl and use it as a format for the Content Query web part, it works fine as well. If you want to take a look at a video of this, take a look here: http://youtu.be/kKEE_yktk8c
Hopes this give some ideas or inspiration for your cookie scripting adventures!
/ Christian
July 18, 2012

Comment functionality for news pages – Part II

This article is the last one of two describing how to implement comment functionality into the news pages in SharePoint Server 2010. You’ll find Part I here. If you followed the examples in the Part II and have implemented the comment functionality it’s time to create one or more news rollup web part:
  • A web part that display the latest news pages and the number of related comments
  • A web part that display recently commented news pages
  • A web part that display the Display most commented news pages

First step – create a news rollup DVWP

When Lists and libraries are connected with a lookup you have the possibility to join content from both sources into a single Data View Web Part (joined sub view). This is useful if you want to create a news rollup that shows the latest news including the number of comments for each news item. In my examples I use the Page library in the root like the custom list NewsComments. You can use this in a sub site for news if you prefer.
I wanted to strip out HTML from the body text and limited body text by a number of words, so I used the strip HTML and the Count Word templates; a Codeplex project called SPXSLT created by my friend Marc D Anderson.
  • Open SPD and create a new folder direct in the root level and give it the name ’SPD-WebParts’.
  • Create a new ASPX page and give it the name RollupNews.aspx, check it out and open this with SPD.
  • Paste all the content from my file with the same name, you’ll find the download link at the end of this blog post.
  • Save the file and hit F12 for preview.
  • Check in and publish the file.
  • You can save this DVWP to the site gallery or to your disc if you want to implement the web part with the browser.

Next step – create a recently comments DVWP

This web part displays the most recent commented news pages. If the comment is created today, ‘New!’ will be displayed otherwise not.

  • Create a new ASPX page, save into the folder SPD-WebParts and give it the name LatestCommentedNews.aspx, check it out and open it up.
  • Paste all the content from my file with the same name, you’ll find the download link at the end of this blog post.
  • Save the file and hit F12 for preview. Check in and publish the file.
  • You can save this DVWP to the site gallery or to your disc if you want to implement the web part with the browser.

Next step – create a most comments DVWP

This web part display the most commented news pages. In order to group this, I have used the PageID column for the grouping. Furthermore I want to sort the web part by number of Items but of some reason I haven’t yet found the perfect way to accomplish this in XSLT, so I leave this as an open question to you readers! If you found a pure XSLT way for this I’ll update this blog post. In the meantime I’ll go for the jQuery TableSorter plugin. This plug is useful in different scenarios when you need client side sorting with all kind of data and it a works great if you need secondary ‘hidden’ sorting or for example just sorting a table without page refresh. You’ll find the file included in the download, see the link at the end of this blog post.

  • Create a new ASPX page, save it save into the folder SPD-WebParts and give it the name MostCommentedNews.aspx, check it out and open it up.
  • Paste all the content from my file with the same name, you’ll find the download link at the end of this blog post.
  • Save the file and hit F12 for preview. Check in and publish the file.
  • You can save this DVWP to the site gallery or to your disc if you want to implement the web part with the browser.
To activate the sort order, add a reference in your custom master page to the tablesorter file and add the following line of script into an external JS file or into the head section of your master page:
1<script type="text/javascript">
2$(document).ready(function() {
3// Custom sort DVWP news sort by most comments
4$('.tablesorter').tablesorter({sortList:[[0,0]] });
5});
6</script>

Download the files

If you got questions about this or maybe ideas for more functions or web parts related to this, pleas drop a comment.
Download my example files here
Thanks!
/ C
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:
    1<xsl:variable name="Rows" select="/dsQueryResponse/Rows/Row"/>
    change to:

    1<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.
01<script type="text/javascript">
02// Limit characters
03function limitChars(textid, limit, infodiv){
04var text = $('#'+textid).val();   
05var textlength = text.length;
06if(textlength > limit) {
07$('#' + infodiv).html(''+limit+' limit reached');
08$('#'+textid).val(text.substr(0,limit));
09return false;
10}
11else {
12$('#' + infodiv).html(''+ (limit - textlength) +' characters left');
13return true;
14}}
15$(function(){
16$(".FormFieldNewsComments > span > textarea[title='Comments']").keyup(function(){
17limitChars(".FormFieldNewsComments > span > textarea[title='Comments']", 140, "LimitInfo");
18})
19});
20     
21$(document).ready(function() {
22var loc = window.location.href.substr(window.location.href.lastIndexOf("/")+1); // Get the page filename
23var PageTitle = $('.PageTitleDiv').html(); // Get the page title
24$(".FormFieldNewsTitle > span > input[title='Title']").val(loc); // insert page filename in a CSS hidden formfield
25$(".FormFieldPageTitle > span > input[title='PageTitle']").val(PageTitle);    // insert pages title in a CSS hidden formfield
26var HiddenInput = $("input[title='PageID']").attr("optHid"); // Lagrar ID till attributet optHid
27$("select[title='PageID']").val(_spPageContextInfo.pageItemId); // If less than 20 items i Pages bibl, lägger in ID nr som en selected i DD
28$("input[title='PageID']").val(_spPageContextInfo.pageItemId);  // If 20 or more items in Pages lib
29$("input[id='" + HiddenInput +"']").attr("value",(_spPageContextInfo.pageItemId)) // Set ID as selected if 20 or more items in Pages lib
30});
31</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

1<xsl:if test="count($Rows) = 0">No comments yet..</xsl:if>
2<xsl:if test="count($Rows) = 1"><xsl:value-of select="$dvt_RowCount" /> Comment</xsl:if>
3<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

1<xsl:param name="UserID" />
Create these parameter for the rowview template

1<xsl:param name="KeyField">ID</xsl:param>
2<xsl:param name="KeyValue" select="ddwrt:EscapeDelims(string(@ID))"/>
3<xsl:param name="Mode">view</xsl:param>
Match the author to the logged in user

1<xsl:if test="@Author.title = $UserID">
2<a href="javascript: {ddwrt:GenFireServerEvent(concat('__cancel;__delete={',$KeyField,'=',$KeyValue,'};__commit'))}">DELETE</a>
3</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

1<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.
See Part II

Stay in tune!
News comments
News comments
May 23, 2012

Branding the Quick launch in SharePoint 2010 – Part II

This post is the last one of two articles about some branding tips and tricks for the Quick launch in SharePoint 2010. In this article I’ll show you a simple way to add rounded corners with help of two background images at the top and bottom. Take a look at the first article here.

Let’s go – Example 1

Open your custom master page with SharePoint Designer and find the Sharepoint:SPNavigationManager control. Add the following DIV just above this control.
1<div id="QLtopwrapper"></div>
When you complete this find the end tag of the </Sharepoint:SPNavigationManager> and add the following DIV just above this control.
1<div id="QLbottomwrapper"></div>
Now you have everything in place in your custom master page as needed, so now it’s time to add some CSS. Copy the following CSS code and paste it into your external CSS file. As you can see I have used two background images. Make your own or download the Images I have used here. I have included my example master page in the download if you find it difficult to locate where you should place the top and bottom div.
01/* |--------- Quicklaunch -----------| */
02.ms-quickLaunch {padding-top:0px}
03#s4-leftpanel-content{
04background-color:transparent!important;
05}
06#s4-leftpanel-content {
07border:0px!important;
08background-color:transparent!important;
09}
10.s4-ql {
11background-color:#fff;
12margin-bottom:0px!important;
13}
14/* Inner nav element */
15.menu-vertical {
16padding:0px!important;
17}
18/* top rounded */
19#QLtopwrapper {
20background:url('/Style%20Library/Branding/Images/QLtop.png') repeat-x;
21height:19px;
22width:220px;
23}
24/* bottom rounded */
25#QLbottomwrapper {
26background:url('/Style%20Library/Branding/Images/QLbottom.png') repeat-x;
27height:19px;
28width:220px;
29}
30.menu-vertical > ul.root > li.static > .menu-item{
31border-bottom:1px #929292 solid!important;
32padding-left:0px;
33color:#fff;
34font-family:Arial;
35font-size:11px;
36font-weight:bold;
37background-color:#8c8c8c!important;
38background-color:#8C8C8C!important;
39}
40/* Selected */
41.s4-ql a.selected {
42background-color:transparent;
43background-image:none;
44border:1px transparent solid!important;
45color:#fff!important;
46}
47/* no border in teamsites */
48.s4-ql,.s4-specialNavLinkList{
49border:0px!important;
50}
51.menu-vertical > ul.root > li.static {
52padding:0px!important; margin:0px!important;
53}
54/* headers */
55.menu-vertical > ul.root > li.static > a.menu-item {
56padding:10px 4px 10px 5px;
57border-bottom:1px #ccc solid;
58}
59/* headers selected for publishing sites */
60.menu-vertical > ul.root > li.static > a.selected {
61padding:10px 4px 10px 3px;!important;
62padding-left:4px!important;
63background-color:#777!important;
64}
65/* Subitem container */
66.menu-vertical > ul.root > li.static > ul {
67margin-bottom:0px;
68padding-top:0px;
69padding-bottom:0px;
70}
71/* SubItems wrap */
72.menu-vertical > ul.root > li.static > ul.static > li.static > a  {
73font-family:Arial, Helvetica, sans-serif;
74font-size:11px;
75padding:10px 4px 10px 8px;
76color:#ccc!important;
77}
78/* SubItems  */
79.menu-vertical > ul.root > li.static > ul.static > li.static > a > span > span {
80color:#333;
81text-decoration:none!important;
82}
83/* SubItems hover */
84.menu-vertical > ul.root > li.static > ul.static > li.static a:hover {
85text-decoration:none!important;
86}
87/* Selected SubItems  */
88.menu-vertical > ul.root > li.static > ul.static > li.selected > a.selected {
89background-color:#fff;
90border:1px transparent solid!important;
91padding-left:10px!important;
92}
93/* Selected SubItems  */
94.menu-vertical > ul.root > li.static > ul.static > li.selected > a.selected > span > span {
95color:#000;
96}
97.menu-vertical > ul.root > li.static > ul.static > li {
98border-bottom:1px #8C8C8C solid!important;
99}

Let’s go – Example 2

In this example I’ll use a jQuery script to get a simple and basic expand and collapse function in a specific scenario. Let’s say you have the setting “Display only the navigation items below the current site” for some site and have added headings and link manually. You can then use jQuery to toggle the headings. This behavior the jQuery script gives with the current navigation settings may not be suitable for all sites in the collection for you; this example is just build for this specific case and you can use it locally just on a single page if you prefer to.

Here’s the jQuery
01$(".menu-vertical > ul.root > li.static > ul.static").css("display","none");
02$(".menu-vertical > ul.root > li.static").css("background","url('/_layouts/images/plus.gif') no-repeat 3px 12px");
03  
04toggle();
05function toggle() {
06$(".menu-vertical > ul.root > li.static > a").toggle(
07function () {
08$("> ul", $(this).parent()).show("fast");
09$($(this).parent()).css("background","url('/_layouts/images/minus.gif') no-repeat 3px 12px");
10},
11function () {
12$("> ul", $(this).parent()).hide("fast");
13$($(this).parent()).css("background","url('/_layouts/images/plus.gif') no-repeat 3px 12px");
14});
15}
16$sel = $('.menu-vertical > ul.root > li.static > ul.static > li.selected');
17if($sel.length) {
18$sel.parent().css("display", "block");
19$sel.parents().eq(1).css("background","url('/_layouts/images/minus.gif') no-repeat 3px 12px"); 
20}
Here’s the CSS
01/* |--------- Quicklaunch -----------| */
02.s4-ql A.selected {
03background-color:transparent;
04border:0px!important;
05}
06/* Inner nav element */
07.menu-vertical {padding:10px; padding-left:0px}
08 
09/* Headers */
10.menu-vertical > ul.root > li.static > a > span > span.menu-item-text {
11border-bottom:1px #ccc solid;
12padding-left:5px; color:#333;
13padding-bottom:5px; padding-top:5px;
14}
15/* Sublinks */
16.menu-vertical > ul.root ul > li > a {
17padding-left:15px; color:#333;
18}
19/* Sublinks hover */
20.menu-vertical > ul.root ul > li > a:hover{
21color:#009BA4; text-decoration: underline
22}
23/* Sublinks top and bottom */
24.menu-vertical > ul.root ul {
25margin-top:5px; margin-bottom:5px;
26}
27/* Sublinks selected */
28.menu-vertical > ul.root > li.static > UL.static > li.selected > a.menu-item > span.additional-background{
29margin-left:6px!important
30}
Thanks & stay in tune!
/ Christian
April 2, 2012

SharePoint Server MVP 2012

I’m happy to announce that I have been selected again by Microsoft to receive the SharePoint Server MVP award for 2012 for the second time and I have now been awarded two years.
For me it’s really cool to receive this award, it’s motivates me to write more blogs & articles and other contributions to the SharePoint community. My goals for 2012 is to focus even more the area of branding and front end development in SharePoint. Besides my daily consulting work, I’ll also do more public speaking, to start with I’ll talk at TechDays in Sweden about branding & customize SharePoint online in Office 365. Later this year I’ll will speak at Konferenca SharePoint in Slovenia, SEF in Sweden and some more places, more about that later on.
MVP Award 2012
From the MVP site: “MVPs are recognized and awarded for their exceptional commitment to helping us improve our products and helping people around the world make the most of their Microsoft technology.”
Corey Artherholt Marketing, Events and Program Manager,
Community & Online Support, Microsoft
Read more about Microsoft MVP program at the Microsoft Most Valuable Professional site
Thanks a lot Microsoft, colleagues, friends and all great people out there in the world wide SharePoint communitys.
See you around and stay in tune for comming posts & articles .
March 27, 2012

Branding the Quick Launch in SharePoint 2010 – Part I

This post describes how to customize the standard Quick Launch in SharePoint by using SharePoint Designer 2010.
Branding the Quick Launch with only CSS could be a bit tricky and it takes a little while to become a friend with the markup of this navigation and have it to look the way you want. This first article in a series of two will show you how to create a simple custom look and feel with only CSS code. If you need to create a more advanced design for the Quick launch than you can do with just CSS, the alternatives is to manipulate the DOM with jQuery or using plain HTML with CSS and background images. Besides of this, CSS 3 comes with some exiting features like box shadow and border radius that lets you create stuff like boxes with curved corners but it’s not an option here because we need to render the master page in IE8 mode to get all functionalities intact in SharePoint 2010. I hope this post gives you some ideas and inspirations for branding the quick launch in the way you want.

Let’s go

Open SPD, create a custom master page and include a reference to an external CSS file. Paste the following CSS code in your custom CSS file. Save and publish the files and apply the master page to a site or your site collection. Use the browser and go to a site where you can see a Quick Launch to verify the changes. This first example uses a list style background image for the sub items. You can download the arrow icon here.

CSS

Add this CSS in your custom CSS file, don’t forget to change the path to the arrow icon to the folder where you put the image:
01/* |--------- Quicklaunch -----------| */
02.s4-ql ul.root ul {
03margin-bottom:5px;
04}
05/* Outher nav element */
06#s4-leftpanel-content{
07background-color:#fff!important;
08border:1px #d8d6d7 solid!important;
09border:0px!important
10}
11/* Inner nav element */
12.menu-vertical {
13padding-right:10px!important;
14padding-left:10px!important;
15}
16/* Inner Inner nav element */
17.menu-vertical > ul.root {
18padding-top:3px;
19}
20/* mainlinks */
21.menu-vertical > ul.root > li.static > .menu-item{
22border-bottom:1px #555 solid!important;
23padding:1px 1px 1px 0px!important;
24color:#333!important;
25}
26/* Sublinks */
27.menu-vertical > ul.root > li.static > ul.static  {
28margin-top:5px; margin-bottom:5px;
29}
30.menu-vertical > ul.root > li.static > ul.static > li.static > a > span > span {
31margin-top:2px
32}
33/* Selected */
34.menu-vertical > ul.root > li.selected > a {
35background-color:transparent!important;
36border:0px; margin:0px; padding:0px;
37}
38.menu-vertical > ul.root > li.static > ul.static > li > a.selected {
39background-image:none!important;
40background-color:transparent;
41color:green!important;
42border:0px; margin-top:1px;
43}
44/* no border for the QL when no links */
45.s4-specialNavLinkList {
46border:0px
47}
48/* Liststyle square */
49.s4-ql ul.root ul > li  {
50padding-top:0px;
51background-image:url('/Style Library/WordPress/Images/Arrow-Right.png');
52background-repeat:no-repeat;
53background-position:0.0em;
54}
55/* Liststyle square links */
56.s4-ql ul.root ul > li > a {
57display: inline-block!important;
58padding-top:0px;
59padding-bottom:0px!important;
60padding-left:0px!important;
61margin-left:16px;
62vertical-align:top!important;
63}

Another example

If you want to display more levels in the Quick Launch you can set the display level to three, MaximumDynamicDisplayLevels=”3″ for the SharePoint Asp menu in the master page. Look for the menu control with the ID V4QuickLaunchMenu. In this example I have used list-style squares instead of the arrows.

Add this CSS in your custom CSS file:
01/* |--------- Quicklaunch -----------| */
02.s4-ql ul.root ul {
03margin-bottom:5px;
04}
05/* Outher nav element */
06#s4-leftpanel-content{
07background-color:#fff!important;
08border:1px #d8d6d7 solid!important;
09border:0px!important
10}
11/* Inner nav element */
12.menu-vertical {
13padding-right:10px!important;
14padding-left:10px!important;
15}
16/* Inner Inner nav element */
17.menu-vertical > ul.root {
18padding-top:3px;
19}
20/* mainlinks */
21.menu-vertical > ul.root > li.static > .menu-item{
22border-bottom:1px #555 solid!important;
23padding-left:0px!important;
24padding:1px!important;
25color:#333!important;
26}
27/* Sublinks margins */
28.menu-vertical > ul.root > li.static > ul.static  {
29margin-top:5px;
30margin-bottom:5px;
31}
32/* Selected */
33.menu-vertical > ul.root > li.selected > a {
34background-color:transparent!important;
35border:0px; margin:0px; padding:0px
36}
37.menu-vertical > ul.root > li.static > ul.static > li > a.selected {
38background-image:none!important;
39background-color:transparent;
40color:green!important;
41border:0px; margin-top:1px;
42}
43/* no border for the QL when no links */
44.s4-specialNavLinkList {
45border:0px
46}
47/* Liststyle square */
48.s4-ql ul.root ul > li  {
49list-style:square inside !important;
50list-style-position:outside !important;
51margin-left: 23px !important;
52padding-top:0px;
53}
54/* Liststyle square links */
55.s4-ql ul.root ul > li > a {
56display: inline-block!important;
57padding-top:0px;
58padding-bottom:5px!important;
59padding-left:0px!important;
60vertical-align:top!important;
61}
62/* If 3 lvl in QL */
63/* Wrapper for all Items in lvl 3 */
64.menu-vertical > ul.root > li.static > ul.static > li.static > ul.dynamic {
65position:relative;
66left:-8px!important;
67top:1px!important;
68padding-left:0px
69}
70/* Wrapp each Item in lvl 3 */
71.menu-vertical > ul.root > li.static > ul.static > li.static > ul.dynamic > li.dynamic {}
72.menu-vertical > ul.root > li.static > ul.static > li.static > ul.dynamic a:hover {}
73.menu-vertical > ul.root > li.static > ul.static > li.dynamic-children > a.dynamic-children > span.additional-background {
74background-image:none
75}
76/* Items in level 3*/
77.menu-vertical > ul.root > li > ul > li > ul > li > a.selected > span > span  {
78padding-left:5px!important
79}
80/* Item lvl 3 - get all subItems from the last available DOM defined selected Item */
81.menu-vertical > ul.root > li > ul > li.selected > ul > li > a > span > span {}
Read more about customizing the Quick Launch at MSDN library How to: Customize the Display of Quick Launch
In the next blog post I’ll show you some more examples how to customize the quick launch with stuff like rounded corner & borders and how to expand / collapse the Quick Launch with help of jQuery. Stay in tune!
/ Christian
February 11, 2012

Create a Microblog for SharePoint 2010

This post is about how to create a Microblog with SharePoint Designer 2010 and the use of DVWPs, CSS and jQuery. A Microblog can be used for quick communication with team members in short sentences at the Intranet. This example works just like a SharePoint blog site, posts and comments are stored in separate lists that are linked by a lookup and team members can add posts and anyone can reply to posts. This Microblog is a basic no code solution and if you are looking for more advanced social features like hash tagging, direct messages, document uploading or integration of my site you should check out tools like NewsGator or Yammer among more. If you are looking for a basic comment function, maybe the OTB web part Note board could be an option. But let’s look into how you can use the DWVP for a Microblog.

Let’s try it out

  • Open the browser and create two custom lists in the root site of your Site Collection
    • Name it ListPosts
    • Name it ListComments
  • ListPosts
    • Create a column:
    • Name: Content – Multi lines of text with three lines for editing and plain text type.
    • Go to list settings, click the Created By column and change the presentation for this field to Name (with picture).
    • Add a new Item in the list with a title and a comment.
  • ListComments
    • Create two columns:
    • Name: PostsID – type Lookup. Get information from ListPosts in the ID column. Do not allow multiple values.
    • Name:  Comments – Multi lines of text with three lines for editing and plain text type.
    • Go to list settings, click the Created By column and change the presentation for this field to Name (with picture).
    • If you don’t use English language, rename the the (Title) column to Title, another way is just to set this column as optional if you prefer.
    • Add a new Item in the list with a title and a comment. Type a title, select PostID according to the ID from the ListPosts item you added and add a comment.

Create a Linked Data Source for the posts and comments lists

  • Open the root site with SPD and click at site objects in the left navigation at click Data Sources. Click at Linked Data Source in the ribbon. Give it the name MicroBlog in the General tab and click at configure Linked Source in the Source tab.
  • Select ListPosts and ListComments and add them to the right pane. If you can’t see the list you have to update SPD. Click at the next button and select Join and click at Finish and OK.
  • Open the root site with SPD and create a new folder named SPD-WebParts
  • Create a new ASPX page called MicroBlog and save it in the folder you created, open the page with SPD. IF you download my pages and will copy and paste you don’t need to do more now, but if you want to set this up by your self you can attach the page to your custom master page. Check it out, click at the Style tab in the ribbon, the button Attach and attach it as a custom master page. In the design view, click at the right arrow for the PlaceHolderMain place holder and click at create custom content.
  • Create a new ASPX page called MicroBlogForm and save it in the same folder as Microblog.aspx. Repeat the steps as you just did for the MicroBlog.aspx.

Create two ASPX pages

In the next step it’s time to create two DVWPs for MicroBlog.aspx, the first is for inserting posts and the second is for displaying current posts and their comments. If you want to build this by yourself you can just add a Display Item Form DVWP and use the Linked Sources and then insert field from the Comments as a Joined sub view. You will also have to create a New Item Form DVWP for the second page meant for inserting comments.
If I would describe all the steps from now including styling and jQuery this blog would be too long and for this reason I have prepared this so it’s just to download the pages and do some copy and paste. If you export or upload the DVWPs as web parts the CSS and the jQuery will not follow the web part. so cut the CSS from the MicroBlogForm page and paste this into an external CSS file. The same goes for the jQuery stuff in both pages, cut the scripts and paste them into the head section of your custom master or into an external JS file.
Read more about Linked data sources at the Microsoft Office SPD pages.
SPD-MicroBlog
SPD-MicroBlog

Insert the Dataviews into the ASPX pages

MicroBlog.txt

  • Open this page and copy the content into MicroBlog.aspx and save the page

MicroBlogForm.txt

  • Open this page and copy the content into MicroBlogForm.aspx and save the page

CSS

Copy this CSS into your custom CSS file
01/* --- MicroBlog --- */
02.PostBodyWrapper {width:100%;}
03.PostWrapper {margin-left:5px}
04.PostSeparator {border-bottom:1px #f1f1f1 solid; border-top:1px #fff solid; margin:5px 5px 5px 5px}
05.PostImg {float:left; width:50px; height:50px; padding-right:10px}
06.PostContentWrapper {background-color: #fff; height:50px;}
07.PostEditor {font-weight:bold; color: #0072bc}
08.PostContent {}
09.PostLink {}
10.PostComment {}
11.PostCreatePost {padding:10px}
12.FormFieldMicroBlogWrapper {margin-left:5px; width:100%; }
13.FormFieldMicroBlog > span > textarea {
14background-color: transparent; width:95%;
15border:1px solid #ccc;       
16overflow:hidden; overflow-y: hidden; overflow-x: hidden;  
17font-size:14px; color:#999;
18font-family:Arial, Helvetica, sans-serif;
19padding:10px 20px 0px 10px;
20margin-right:20px
21}
22.PostBtn {padding-right:3px; float:left}
23.PostBtn Input {
24width: auto;
25padding: 5px 10px 5px 10px;
26background: #617798;
27border: 0;
28font-size:13px;
29color: #fff;
30cursor: pointer!important;
31float:right
32}
33.CommentWrapper {margin-left:60px; margin-right:5px; background-color: #f7f7f7; padding:10px; border-bottom:1px #fff solid}
34.CommentImg {width:50px; float:left;}
35.CommentContentWrapper {}
36.CommentEditor {font-weight:bold; float:left}
37.CommentEnd {margin-left:60px; margin-right:5px; border-top:1px #ccc solid; border-bottom:1px #fff solid; margin-bottom:20px}
38.CommentContent {}
39.CommentLink {}
40.CommentNoComment {border-bottom:1px #fff solid; border-top:1px #fff solid; margin:0px 0px 15px 0px}
41/* --- End MicroBlog --- */

Jquery

Copy this jQuery into your custom master or into a referenced JS file
01$(document).ready(function() {
02$(function() {
03// Remove autofocus
04$("textarea[title='Content']").blur();
05// Set defaulttext
06var defaultText = 'What are you working on?';
07$("textarea[title='Content']"
08// Handle blur effect 
09.val(defaultText)
10.focus(function() {
11if ( this.value == defaultText ) this.value = ''
12})
13.blur(function() {
14if ( !$.trim( this.value ) ) this.value = defaultText
15});});
16});

Image Paths

If you not have activated the user profiles and my site, you have to change the image path in the MicroBlog file. You can create an image library in the root site and store the user images there if you want. Just name the images same as the Users ID. The path can looks like:
<img src=”/RootImages/{@Author.id}.jpg” alt=”" width=”50″ height=”50″ />

Ready to test

Finally it’s time to try this out, open your browser and to to the MicroBlog page

Behind the scenes

Some notes if you needs to change something
  • You have to reference the latest jQuery file in your custom master page
  • Save the two web parts into the web part gallery, or export them as files and you can use them at any page in the site collection, not only at the root site.
  • I have set a RowLimit variable to 5 In MicroBlog.aspx, change this as you prefer.
  • I changed the variable that Joins the list to get rid of the unwanted characters
    <xsl:variable name=”Rows” select=”../../../ListComments/Rows/Row[substring-before(@PostsID., ';#') = normalize-space($dvt_ParentRow/@ID)]“/>
  • The link ‘Reply’ sends the current posts ID as a query string over to the next page (the dialogue). I have used a bit jQuery go get this ID from the URL in order to prepopulate a hidden drop down (the lookup column), and as you may know if there are 20 or more items in a list and you use lookup to this list, the select drop down will be converted to an input drop down and this needs to be solved as well.
  • In the dialog I used a SharePoint:SaveButton as I think is an easy way to close a dialog when click the save button.
The jQuery used in the MicroBlogForm that sets the Post ID into the hidden dropdown.
1$(document).ready(function() {
2var loc = window.location.href.substr(window.location.href.lastIndexOf("/")).replace('/MicroBlogForm.aspx?CID=', '').replace('&IsDlg=1', '');
3var HiddenInput = $("input[title='PostsID']").attr("optHid");$("select[title='PostsID']").val(loc);
4$("input[title='PostsID']").val(loc);  
5$("input[id='" + HiddenInput +"']").attr("value",(loc))
6$('input[title="Title"]').val(loc);
7$(".FormFieldShow > span > textarea").focus();
8});

More to do

If someone’s profile picture should be broken or missing, you can use jQuery to replace a broken image with an shadow image:
1$(window).bind('load', function() {
2$('img.resizeme').each(function() {
3    if((typeof this.naturalWidth != "undefined" &&
4        this.naturalWidth == 0
5        || this.readyState == 'uninitialized' ) {
6        $(this).attr('src', '/_layouts/images/O14_person_placeHolder_32.png');
7    }
8});
9})
Enjoy, and drop a comment if you have something to ask
/ Christian
January 27, 2012

Customize the UI of web parts in SharePoint 2010

This post describes how to customize a standard Web Part in SharePoint by using SharePoint Designer 2010. Depending of the look and feel or factors such as accessibility, performance or cross browser stability it could be a challenge to bend the web part UI exactly in the way you want. The markup of the web parts in SharePoint contains a quite deep nested table structure and the elements do not always have an id or class.
When you need to create an advanced design for the web parts, the alternatives is to manipulate the DOM with jQuery or create custom web part control wrappers with code. Besides of this, CSS 3 comes with some interesting possibilities like box shadow and border radius that lets you create stuff like boxes with curved corners but it’s not an option here because we need to render the master page in IE8 mode to get all functionalities intact in SharePoint 2010.

So what can you do quick and easily then? The web part headers and all the cells in header row can easily be customized with CSS just like the borders around. I have made four examples with different colors you can download and use at the bottom of this page.
Using only CSS and images for rounded corners is the easiest approach where you don’t need plugins like CSS3 Pie or other htc solutions, fallback methods for different browsers or care about slow rendering when rewriting the already complex and nestled DOM. But when you reach the border of what is possible to do with just CSS and images it’s time to bend the DOM with our friend jQuery or fire up Visual Studio for write a control adapter. Take a look at this blog post from ‘All things SharePoint’ that describes how to use jQuery to adding classes and wrappers into the DOM so you can get a wrapper with rounded corners for the web parts, and take a look at Waldek Mastykars post about how to removing the web part tables with code.
Back to the basics, let’s see how you can customize the web part headers the easy way.
The following example, see the image above, applies background images for the corners and for the middle section. The left and right corners have dimensions of 7 x 33 pixels, and the middle image has dimensions of 14 x 33 pixels.

Let’s go

Download the images and put them into Style Library/BlogBranding/Images or change the path in the CSS below if you want to put the images in some other folder.
01/* WebPart headers */
02/* All tdS in the row */
03.ms-WPHeader > TD{
04background-image: url('/Style Library/BlogBranding/Images/WP-MidGreen.png');
05background-repeat:repeat-x;
06padding-left:1px; padding-right:1px; height:33px;
07border-bottom-style:none!important;border-bottom-color:inherit!important; border-bottom-width:0px!important;
08}
09/* Left cell */
10.ms-WPHeader td:first-child {
11width:5px;
12background-image:url('/Style Library/BlogBranding/Images/WP-LeftGreen.png')!important;
13background-repeat:no-repeat;
14}
15/* Right cell */
16.ms-wpTdSpace {
17width:7px;
18background-image:url('/Style Library/BlogBranding/Images/WP-RightGreen.png')!important;
19background-repeat:no-repeat;
20background-color:transparent;
21}
22/* Arrow */
23.ms-WPHeaderTdMenu{
24background-color:transparent;
25border:0px!important;
26}
27/* Web part title */
28.ms-WPTitle {
29padding-left:10px;
30font-family:Arial, Helvetica, sans-serif;
31color:#fff;
32font-weight:bold;
33margin-bottom:1px;
34font-size:14px;
35}
36/* linked title and visited */
37.ms-WPTitle a, .ms-WPTitle a:visited {
38color:#fff;
39text-decoration:none;
40}
41/* hover title */
42.ms-WPTitle a:hover {
43color:#333;
44text-decoration:none;
45}
46/* hover web part menu */
47.ms-WPHeaderTdMenu:hover{
48border-left:1px solid transparent;
49background-image: url('/Style Library/BlogBranding/Images/WP-MidGreen.png');
50}

More stuff you can do

If you want to do something special just for one single web part based on some condition or similar? Let’s say you want to have a different look and feel for some web part only if its header text is ‘Links’. I made up an example that makes the header title red and adds a border with a dropshadow filter older IEs and BoxShadow for modern browsers. Other web parts will not apply this look and feel.

Here’s the jQuery

01$(document).ready(function() {
02var WPtitle = $('.ms-WPTitle span');
03for (var i = 0; i <= WPtitle.length; i++) {
04    if ($(WPtitle[i]).text() == 'Links') {
05            $(WPtitle[i]).css({'color': 'red'});
06            $(WPtitle[i]).parents().eq(10).addClass("WebPartBorder");
07    }
08    else if ($(WPtitle[i]).text() == 'Shared Documents') {
09            $(WPtitle[i]).css({'color': 'blue'});
10    }
11}
12});

Here’s the CSS

01/* All TDs in the table row */
02.ms-WPHeader TD{
03background-color: #f7f7f7;
04filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ebebeb', endColorstr='#e2e2e2');
05background: -webkit-gradient(linear, left top, left bottom, from(#e2e2e2), to(#ebebeb));
06background: -moz-linear-gradient(top, #e2e2e2, #ebebeb);
07border-top:1px #cfcfcf solid; border-bottom:1px #e2e2e2 solid!important;
08padding:3px;
09}
10/* for css / jquery drop shadow */
11.WebPartBorder{
12border:1px #777 solid!important;
13-moz-box-shadow: 5px 5px 5px #ccc;
14-webkit-box-shadow: 5px 5px 5px #ccc;
15box-shadow: 5px 5px 5px #ccc;/* CSS3 */
16background-color:#fff;
17filter: progid:DXImageTransform.Microsoft.DropShadow(OffX=5, OffY=5, Color=#e9e9e9);   
18}
19.WebPartBorder > tbody {
20background-color:#f7f7f7!important
21}
22/* Border to the sides */
23.ms-WPHeader td:first-child {
24border-left:1px #e2e2e2 solid;
25border-right:0px;
26}
27.ms-wpTdSpace {
28border-right:1px #e2e2e2 solid;
29}
30/* Web part title */
31.ms-WPTitle {
32color: #333;
33font-weight:bold;
34}
35/* linked title and visited */
36.ms-WPTitle a, .ms-WPTitle a:visited {
37color: #333!important;
38text-decoration:none!important;
39}
40/* hover title */
41.ms-WPTitle a:hover {
42color:#0072bc!important;
43}
44/* hover web part menu */
45.ms-WPHeaderTdMenu:hover{
46 background-image:none;
47border-top:1px solid #ccc;
48border-right:1px solid transparent;
49border-left:1px solid transparent;
50background-color:#f7f7f7;
51}
52/* for the jQuery */
53.LinkTextColor {
54color:red;
55}
Hopes this gives you some ideas, and please feel free to drop a comment!
/ Christian