Sunday, June 13, 2010

Customizing and branding the wiki pages for a SharePoint 2010 Team Site

Topic

Updated 2011 November 1st

I am examining the SharePoint 2010 architecture in order to find the best ways to customize the Wiki Pages of a Team Site. In this post we will focus on two kinds of elements:

  • The SharePoint 2010 CSS and especially the Rich Text Editor CSS and thus how are populated the RTE menus (Styles, Markup Styles, etc)
  • Some of the SharePoint 2010 templates, including the v4.master Master Page and the Team Site Wiki Page Template, wkpstd.aspx

Important: do not mistake a Wiki Page of a Team Site for a Wiki Page of an Enterprise Wiki. They are totally different since an Entreprise Wiki is a kind of publishing site, and a Wiki Page of an Enterprise Wiki can be based on different Wiki Page Templates. So, although it is not so difficult to customize the Enterprise wiki pages, it is tricky to do the same job for the team site wiki pages. This post focuses on the second...

In this post, I will examine the Wiki Pages for a Team Site so as this information can be used for SharePoint Foundation 2010.

For more information about Enterprise Wiki:

Enterprise Wikis overview (SharePoint Server 2010)
ContentTypeId.EnterpriseWikiPage Property
SPC: Customizing Enterprise Wikis in SharePoint 2010 with Gail Jacoby & Ted Pattison

Summary

1 - Managing the CSS, inculding Rich Text Editor CSS and  the RTE Menus Items of the Ribbon

     1.1 - Debugging the SharePoint 2010 Ribbon 
             Conclusion
     1.2 - Storing and registering the SharePoint 2010 CSS (OOTB and Custom)  
     1.3 - Conclusion

2 - Provisioning custom content within a wiki page

3 - Customizing the Wiki Page Template programmatically

4 - Creating a custom template for the team site wiki pages

5 - A real world example: Internet-Facing team site with SharePoint 2010 Foundation

1 - Managing the SharePoint 2010 CSS, including the Rich Text Editor CSS and  the RTE Menus Items of the Ribbon

In a previous post I have explained how to add items to these menus and in return, I have received and read questions on forum about removing the native items. I have already updated the post to give information about it.
One important thing to know is that these items are populated dynamically, client side, using the JavaScript loaded by the SharePoint 2010 Ribbon, and I am now going to show how to see it in action.

1.1 - Debugging the SharePoint 2010 Ribbon

We are going to debug the JavaScript of the Ribbon while using IE8 in order to see how the menu are populated, so let us start by adding a new Style menu item.
Add an HTML form Web Part in a SharePoint 2010 wiki page in order to be allowed to insert some HTML within the page and add an style tag with a ms-rteStyle so that the menu can be able to load this style as a new item.

Then open the Tools menu of IE8 and locate the Developer Tools

Open the Developer Tools and hit the Script Tab

There is not much scripts loaded for the moment but activate the Edit mode for the page.

You will notice that activating the Edit Mode leads to the load of several files, but locate the following:

sp.ui.rte.debug.js

Open it
locate this line (12890) RTE.StyleRuleUtility.$u = function($p0, $p1, $p2)
and set the following breakpoint:

  • sp.ui.rte.debug.js -->

    Place a breakpoint in front of
    the first line
    if (!$p0.startsWith('.')) {



The goal now is to force SharePoint 2010 to load the styles, so Save & Close the page, empty the temporary internet files, add a custom style to one of the CSS files.

Now, hit the "Start Debugging" button in the Developer Tools
then, go back to the wiki page and activate the Edit Mode.

The tool starts debugging and stops on the breakpoint.
Continue to press F11, and you will be taken to a resource file that seems to validate some parameters, then when you come back to the script, you notice that a variable has been initialized to look for the ms-rte class elements.

Then the url for the first css file is retrieved

Then, this is AMAZING! the JavaScript of the Ribbon is loading the content of the CSS file by using an AJAX request with the XMLHttpRequest object.
You will notice the responseText variable with all the CSS classes loaded! 

Then it is the turn of the wiki.css

and the corev4.css

finally I had a custom styles CSS, and you will see that I have placed the ms-rteStyle-Normal inside of it

Then the JavaScript starts loading the classes available within the page, first these two that are located in the <head> tag:

    <style type

        .ctl00_PlaceHolderMain_Bottom_0

        {

            border-color: Black;

            border-width: 1px;

            border-style: Solid;

        }

        .ctl00_wpz_0

        {

            border-color: Black;

            border-width: 1px;

            border-style: Solid;

        }

    </style>


 

Then the JavaScript finds the custom style I have placed within the HTML Form web Part

and stores the inner and outer html of it

and the class name

 

Conclusion: 

as the styles are loaded dynamically from all the places where you can store CSS, we should not have to worry about coding to manage the Styles and Markup Menus items, but just to focus on the good way of storing and referencing our CSS.

However, it is not true!

The CSS are managed in SharePoint 2010 by 2 important controls : CssLink and CssRegistration and their behaviour are sometimes very weird (while there is fortunately a logical explanation after all) and we will have to perform programming operations either client side or server side to manage the CSS. It is the topic of the next section 

1.2 - Storing and registering the SharePoint 2010 CSS

Storing the CSS

I am planning to update this post (CSS Registration and Rendering for SharePoint 2010 (including themes)) that is rather adviced regarding this topic, but roughly, you can store your CSS:

  • in a custom file usualy located in the 14\layouts\language\styles\yourCompanyOrClientName folder. That means it will be deployed by a SharePoint solution (.wsp) thus, independant of the content database and that the web designer will have to use TFS.
  • in the style library. That means that the CSS files will be stored in the content databases and thus, unghosted. So don't try to deploy them that way using a SharePoint feature, it is inapropriate since you will have to delete them before any update. If you store them in the database it is a way for Web Designers to deploy them by uploading them directly in the style libraries so as they don't need to use TFS and generate conflicts with the team developers.
  • Within the code, in the templates, the pages, etc... Although it is, of course,  not a professionnal way of storing the CSS...

 

Registering the CSS

- At the wiki page level (for one, several pages or a specific page library).

As it is not prefessional although it is possible to put a reference to a CSS file by inserting a web part within a wiki page, that means we need to modify the wiki template for one or generally several wiki pages in order to put a CssRegistration control refering to a CSS file. (try to avoid using <link> tags in SharePoint, use rather the CssRegistration control. The CssLink control within the master page will gather all the registrations done that way for rendering them in a unique location so as you will be able to drive properly all the registrations...)

That leads to the concern of team site wiki page template:

With MOSS 2007, when creating a portal, we were sometimes hesitating between using the collaborative part of SharePoint (the lists, the pages, the Web Part pages), and the integrated CMS (Web Content Management). Both had benefits and drawbacks, and it seems that, in SharePoint 2010 the Wiki Pages of a Team Site are now closer to a WCM Page Layout than ever because the layout of the page has been dramatically improved.

However, the wiki pages of a Team Site don't seem to have been designed to be customized, and it is perfectly normal because there is a customizable version of the Wiki Pages in Sharepoint Server 2010: the Wiki Pages of the Enterprise Wiki.

Now this precision has been made, let us examine the limitations of the Wiki Pages for a Team Site:

First of all if you unghost a Wiki Page, it seems that the page UI will be spoiled by a  permanent warning message (although I am sure you can remove it if not you could not use the SharePoint designer to customize a team site).



Second, you cannot create other Wiki Page Templates and make them available for the end users when they want to create pages although it is possible with the Page Layouts and for the Wiki Pages of the SharePoint 2010 Enterprise Wiki.
Why?
When you create a Wiki Page within a team Site by using the SharePoint 2010 UI, the product use the method
SPFileCollection.Add( String,SPTemplateFileType)

It is the only method that can produce ghosted files within SharePoint 2010. The available tempates are:

  1. StandardPage
  2. WikiPage
  3. FormPage



and as you can see in the following screen shot of relector, the reference to the Wiki Page template is hardcoded, so there always will be only one template for the wiki pages of a Team Site, the one that is located at DocumentTemplates\wkpstd.aspx

Of course you can customize the Wiki Pages of a Team Site and let them in a ghosted state by deploying them with a feature, but you will have to upgrade and activate your feature each time you need another custom wiki page, and you will lose the benefit of letting end users create the pages by themselves. (recently I have found a way of using another template than the OOTB one). This is, at first, a bit puzzling, especially because, as the JavaScript of the SharePoint 2010 Ribbon is loading dynamically the CSS classes to populate the Styles and Markup menus within a Wiki Page, we were expecting to a native way of referencing the CSS at the level of the Wiki Page without that it could be modified by a contributor. Here again, we cannot do it although it is possible with a Page Layout and for the Wiki Pages of the Entreprise Wiki.

However, if you want to reference a custom CSS for one or several wiki pages of a Team Site at the level of the page without modifying any template (even the master page!), I have found a means to do it using a delegate control. I have explained it in this section of the my fisrt post about the RTE CSS

 

Unfortunately, this trick will be useless if you have to manage the Rich Text Editor CSS especially if you plan to perform changes for the items of the Rich Text Editor menus (Fonts, Styles, Markup, etc.) since you have first to REMOVE those that are delivered with the Out Of The Box version of SharePoint 2010 as the ms-rteStyle and ms-rteElement classes (ms-rteStyle-Normal, ms-rteStyle-Highlight, ms-rteStyle-Byline,...., H1.ms-rteElement-H1, .ms-rteElement-H1, etc.) that are located within the corev4.css file. And as we are going to see now, if this can be performed at the page level using JQuery, if you want to do it with server code, you cannot avoid using a custom master page.

- At the site level  (often requires a custom Master Page)

Because we will need most of the time when branding a SharePoint 2010 site using the team site wiki pages, to at least, remove the OOTB RTE styles (ms-rteSyle, ms-rteElement,etc.) located in the Themable/corev4.css file and to replace them by our custom classes, we will use most of the time an alternate CSS, either by specifying it within the SharePoint Server 2010 UI, or programmatically for SharePoint 2010 foundation. Unfortunately it won't be enough for the wiki pages of a team site, because, although you use an alternate css, the wiki page keeps referencing the corev4.css file. I have released a beta version of a custom CssLink Control for solving this problem. For further information you can see 2.8 - Second limitation of the wiki page in SharePoint 2010: it is very difficult to remove the OOTB RTE style

By the way, don't even think to remove the CssLink control of the master page to do this! It is a very bad idea when wanting to replace the SharePoint 2010 corev4.css by a custom one to remove the CSSLink control within a Master Page and to place instead a custom <link> tag because the CssLink web control renders some other useful CSS links for the search, and the new SharePoint 2010 dialogs, and also manages the new SharePoint 2010 themes. If you want to know more about it, you can visit my previous post on the topic, CSS Registration and Rendering for SharePoint 2010 (including themable)     So, in SharePoint 2010, when referencing any CSS it becomes quite mandatory to use the CssLink and the CssRegistration controls, especially because of the new SharePoint 2010 themes.

1.3 - Conclusion

If you want to manage the RTE CSS  of a team site wiki page for SharePoint 2010, you have to

  1. Register your own CSS with an alternate Css or by using the defaultUrl property of the CssLink control so as they are dynamically loaded by the SharePoint 2010 Ribbon, for example to populate the Ribbon menus of the Rich text editor like the Styles and Markup Styles Menu. This is worth only for adding items not for removing any!
  2. Use server code (customCssLink) at the site level or client code (branded style sheet using JQuery) at the page or site level for removing the OOTB RTE styles located in the corev4.css file.  



Another scenario if you want to specify the styles at the site page library level or at the wiki page level is to use a delegate control and the CssRegistration web control to be compliant with the SharePoint 2010 new themes management (this is worth only if you don't want to use a custom master page). But as you might need anyway to use a custom master page if you have to remove some RTE menus items, you will do all this within the custom master page and won't need anymore to use a delegate control, excepted, of course if you have decided to remove the items and manage the styles using JQuery...

2 - Provisioning custom content within a wiki page

I have detailled a way of provisioning a pre populated wiki page for a team Site in a new post. I will complete the current post with generic explanations on the concept, but if you want to look at the detailled technical approach, here it is: Provisioning a custom Wiki Page within a SharePoint 2010 Team Site

 

3 - Customizing the Wiki Page Template programmatically

I have detailled a way of adding a new control or replacing one of the standard controls present within the wiki page for a team Site. For this section also, I will complete the current post with generic explanations on the concept, but if you want to look at the detailled technical approach, here it is: Adding a custom control to the SharePoint 2010 Team Site Wiki Page Template ( wkpstd.aspx ) programmatically

 

4 - Creating a custom template for the team site wiki pages

I am now going to show you a very amazing workaround to use another template than the wkpstd.aspx one and will process in two steps. First I will demonstrate it so as you can easily understand its principle then I will provide a programmatic way of doing it. Creating a Wiki Page template For SharePoint 2010 Foundation

5 - A real world example: Internet-Facing team site with SharePoint 2010 Foundation

I am starting a set of posts regarding the ability of SharePoint 2010 foundation to be used to build Internet-facing web sites. In this one we are just going to perform configuration and creation operations so as we can obtain a SharePoint Foundation site collection that can be used to publish content on the Internet and therefore, available for anonymous users. Configuring SharePoint 2010 Foundation for Internet-facing publishing

2012 July 28th

I have posted elements and quick instructions to mount an Internet facing website using SharePoint foundation... check it out!
The site content is in french but it doesn't matter, you can mount it and examine the server code...

I will publish a post with further informations soon.

 

 

 

5 comments:

Marcus@WebVine said...

Hi Marc

I really appreciate discovering your article, you provided a lot of information and obviously took a lot of time. Thank you very much. I am working on a 2007 TeamSite for a client, and we are branding it. We are now requested to use a wiki and am not sure how we will be able to brand it. Also, if we have styles for tables, will we be able to apply those styles without going in the html? Or even then? Thanks a lot, Marcus

Marc Charmois said...

Hi Marcus,

sorry for the late answer.
If I understand well you are branding a SharePoint 2007 TeamSite and are requested to use the 2007 wiki template ?

Regarding the tables concern, as you will quickly notice if you check the html code of a SharePoint page, quite everything in SharePoint is done with tables that is awful for example regarding web accessibility.
So maybe you will be able to use the OOTB SharePoint css classes to change the styles for a specific table but I think it will be very difficult not to generate conflict with other tables you don't want to change...
It is just an assumption, I am not sure of this at all...
Just try...

Usually in my Internet project for SharePoint, I always generate custom htlm code with custom css classes.
If you want advices to do that just ask...

By the way congratulations for your blog EN PARENTHESES, it is very nice.
Seeing it was particulary amazing for me since I am French and was living 15 years in Savoie so not far away from beaufortain... ;-)

Thierry said...

Hi Marcus, very interesting even a bit complicated for me, simple sharepoint user/community manager. But it is exactly my case : I want to change defauly font and sizes proposed by wiki pages (Style & HTML mark up) on my team site. The IT department says that it is not possible to do this for my site only and then it will impact all other team sites of the company (big one). It is hard to admit this, but may be they are right. What do you think ? Is it really impossible (or very difficult) to change the appearance of wiki default fonts with sharepoint 2010 on my site only ?

Marc Charmois said...

Hi Thierry,

your IT departement are partially right, because the easiest way to change the style & html mark-up is to change the CSS on a file called CoreV4.ccs.
And if you do that all the sites of the SharePoint Farm will be impacted...

However there is 2 known workaround to change this for only a site or several sites (that is exactly why I published this post, by the way...)
You can do it using server code (VB.net C#) or client code (JavaScript).

let's forget the server code, it is too complicated, if you go to your IT department with the server code solution, they will certainly decline to examine it.

The JavaScript solution is easier to implement an safer.

Here is the link :
http://stackoverflow.com/questions/7615767/how-to-leverage-custom-styles-markup-styles-in-the-sharepoint-2010-cewp-100

If your IT department make a new master page for your site and place this kind of JavaScript code within the master page, they will be able to change your styles only for your site.
It can cost a day of work for a developper to do so, and I don't know if your company will allow you to have a custom master page, but you should try to ask ;-)

Good luck...

Marc

Anonymous said...

Hello Marc,

I'm trying to upload versioned wiki pages to sharepoint 2010/2013 using CSOM. I store the files to be uploaded in FileCollection and the following is the code
public void AddTemplateFile()
{
FileCollection.AddTemplateFile("Filename", TemplateFileType.WikiPage);
}

The issue I have here is when I try to add multiple files with the same name to the FileCollection, I get an exception stating the file already exists. To avoid this issue, I created the file from FileCreationInformation and added it to the File Collection.
public void AddTemplateFile()
{
FileCreationInformation fci = new FileCreationInformation();
fci.Url = name;
fci.Overwrite = true;
fci.ContentStream = stream;
FileCollection.Add(fci);
}

After uploading the wikis to sharepoint and I try to open the wiki pages, I get a warning "The current page has been customized from its template. Revert to template." . I see all the versions getting uploaded under the version history. I suspect the proper template is not being used. Can you tell me how to resolve this issue ?