Saturday, December 12, 2009

Managing the Rich Text Editor CSS and the RTE Menus for the Wiki Pages of a SharePoint 2010 Team Site

Updated 2011 November 1st

Introduction

The wiki pages are a new feature in SharePoint 2010 that seems to replace the base pages of SharePoint 2007. With the wiki pages, SharePoint 2010 provides a way of not only quickly publishing content within a SharePoint site page but even more, to manage the layout of this content more easily.
The improvement of the publishing is due to two new features provided by the new SharePoint 2010 ribbon when displayed in edit mode:

  • The Styles and the Markup Styles menus
    These two menus allow end users to easily add styles to the content written using the Rich Text Editor.




  • The Text Layout Menu
    This menu allows end users to share the wiki page in several zones where to write content.

In this post we will focus on the Styles and Markup Styles menus and explain how they work and even more, how to remove, add, or modify some of their items.
Regarding the items adding, we will examine all the possible solutions and it will be a chance for the developer that wants to familiarize with SharePoint customization to see the different approaches when wanting to customize the product and the drawbacks pending for each.
So if you are an advanced developper or architect, or wants a quick synthesis on the topic, I rather advice you to move to this section of this second post.

Anyway, here are all the steps described in this post with anchors for a quick consultation:

 1 - How do the Styles and Markup Styles Menus of the wiki pages work in SharePoint 2010?

   1.1 information for advanced end-users (knowing basic html and CSS) and web designers
   1.2 Information for web designers and developers - Location of the CSS and loading mode
   1.3 - Information for web designers and developers - CSS syntax for these styles

2 - How to manage items in the Styles Menus of the wiki pages in SharePoint 2010? (audience: SharePoint developers and Architects)

   2.1 - The 2 possible locations for the Out Of The Box CSS of  the RTE styles and thus for the definition of the styles menus items
   2.2 - Creating and storing a custom CSS file.
   2.3 - First location for a custom Style CSS: within an HTML Form Web Part inserted in  the wiki page
   2.4 - Referencing a custom CSS file within the code of the wiki page
   2.5 - Modifying an existing SharePoint 2010 wiki page by using the WebDav and the FrontPage RPC protocols with Visual Studio
   2.6 - Adding a new wiki page in the Site Pages library by using a provisioning SharePoint 2010 Feature
   2.7 - First limitation of the wiki pages in SharePoint 2010 Foundation: there is only one available template
   2.8 - Second limitation of the wiki page in SharePoint 2010: it is very difficult  to remove the OOTB RTE style

3 - Workaround to give  its own CSS to each wiki page library of a team site

4 - To go further

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.

In this post, I will examine the Wiki Pages for a Team Site so that 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

1 - How do the Styles and Markup Styles Menus of the wiki pages work in SharePoint 2010?

1.1 information for advanced end-users (knowing basic html and CSS) and web designers

 

  • the "Markup Styles"
    • nest the text and its HTML tag within the html tag specified in the style if the tag to nest is a <span> element
    • replace the current tag if is is not a <span> element
    • remove all the styles for the children elements
    • remove the html tag if the same style is applied a second time (this is a way of removing a Markup style for an end-user)
  • the "Styles"
    • nest the text in a <span> tag with the style class if the text is not already inside an HTML tag
    • just add the class to the current HTML tag if this tag is not a <span> tag
    • replace the class of the HTML tag if this tag is a <span> tag
    • remove the html <span> tag if the same style is applied a second time (this is a way of removing a Style for an end-user)

Let us illustrate this by a little example. Assume we want to populate our page with five lines of text (I used Firefox 3.5 for the demo in order to show the cross browser compatibility):.



Then we apply

  • to the first line the "Colored Heading 1" from the "Markup Styles" menu
  • to the second line "Highlight" style from the "Styles" menu
  • to the third line the "Paragraph" style from the "Markup Styles" menu
  • to the fourth line the "Call out 2" style from the "Markup Styles" menu
  • to the fifth line the "Call out 1" style from the "Markup Styles" menu

 and we obtain the following result





 

1.2 Information for web designers and developers - Location of the CSS and loading mode

What is fantastic in the inplementation of the Styles and Markup Styles menus in the ribbon of the SharePoint 2010 wiki pages is that they are populated dynamically by the client side code using Ajax when you activate the Edit Mode of the wiki page. Furthermore, they are populated, based on ALL the CSS styles that are available for a specific wiki page and thus, can be stored:

  • in the Out Of The Box Cascading Style Sheet of the 2010 version (14\TEMPLATE\LAYOUTS\1033\STYLES\Themable\corev4.css)
  • in custom Cascading Style Sheets that are located in the Web Front End file system
  • in custom Cascading Style Sheets that are stored in the SharePoint 2010 content databases
  • in Cascading Style Sheets that are stored in the SharePoint 2010 content databases but were automatically generated by SharePoint (Themes).
  • within the wiki page client code (<style> tag)

All these locations may be parsed by the client side code of ribbon using XMLHTTP requests when you activate the Edit Mode of a wiki page of a SharePoint 2010 team site. (I have debugged the Ribbon while loading the CSS, so if you want to see it in action you can consult this section of another post)

1.3 Information for web designers and developers - CSS syntax for these styles

If the wiki page HTML editor detects Cascading Style Sheet (CSS) classes whose names have the prefix ms-rteStyle-XXXX, where XXXX is the display name of the classes it populates the Styles menu with an item corresponding to this set of styles. The new item displayed text is the value of the property ms-name.
You can see below, an excerpt of the corev4.css file where you can notice the 2 first elements available in the Styles menu of an Out Of The Box SharePoint 2010 team site.

.ms-rteStyle-Normal

{

-ms-name:"Normal";

font-family:Verdana,Arial,sans-serif;

font-size:8pt;

/* [ReplaceColor(themeColor:"Dark1")] */ color:#676767;

/* [ReplaceColor(themeColor:"Light1")] */ background-color:#fff;

}

.ms-rteStyle-Highlight

{

-ms-name:"Highlight";

/* [ReplaceColor(themeColor:"Dark1-Darker")] */ color:#312a26;

/* [ReplaceColor(themeColor:"Accent6")] */ background-color:#fae032;

}

 

If the wiki page HTML editor detects Cascading Style Sheet (CSS) classes whose names have the prefix ms-rteElement-XXXX, where XXXX is the display name of the classes it populate the Markup Styles menu with an item corresponding to this set of styles. The new item display text is the value of the property ms-name.
You can see below, an excerpt of the corev4.css file where you can notice the 2 first elements available in the Markup Styles menu of  an Out Of The Box SharePoint 2010 team site.

H1.ms-rteElement-H1

{

-ms-name:"Heading 1";

font-size:2em;

font-weight:normal;

}

H2.ms-rteElement-H2

{

-ms-name:"Heading 2";

font-size:1.3em;

font-weight:normal;

}

 

We are now going to examine all these locations their use and their impact on the rendering of the contents published by using the Rich Text Editor within a wiki page of a team site.

2 - How to manage items in the Styles Menus of the wiki pages in SharePoint 2010? (audience: SharePoint developers and Architects)

The goal of the demonstartion is now to examine the different locations where the RTE styles are stored or might be stored and to draw conclusions regarding this location about branding operations.

2.1 The 2 possible locations for the Out Of The Box CSS of  the RTE styles and thus for the definition of the styles menus items

         2.1.1 The first Out Of The Box location is the corev4.css file located at:

C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\1033\STYLES\Themable\corev4.css

If you modify this file, you might modify the styles and the styles menus items of the wiki pages for all the team sites of your SharePoint 2010 Farm except if a theme is applied to the site. Most of all, if you modify this file, and you have later to apply a SharePoint 2010 upgrade, hotfix, or maybe just run the SharePoint Products and Technology Wizard, all your changes will be overwritten by the OOTB corev4.css. So it is a very bad idea to modify the RTE styles that way.

         2.1.2 The second Out Of The Box location if a theme is applied - a /_theme/number site folder

Now we are going to go back to the previous example and change the theme of the site to "Bittersweet"




We obtain this:




Notice that all the styles was changed partially or totally by the new theme, except the "Callout 2" style that remained exactly the same. This is due to several things. Some of the SharePoint 2010 rte styles are explicitly defined to change when the theme is changing, like the Markup style "Paragraph" for which are defined the following instruction regarding the SharePoint themes: 

[ReplaceColor(themeColor:"Dark2-Darker")] */

Some others are defined to remain unchanged while applying a theme. The "Callout 2" style was not planned to change when the theme changes because it overwrites the elements of the theme CSS so it will remain exactly the same even if you change for any theme of SharePoint 2010. 
(The "Callout 1" style that was delivered by Microsoft with an error in the color property that prevents it from overwriting the default text color defined by the theme CSS).
 

Now that the "Bittersweet" theme is applied to the site, if you try to modify the corev4.css file, you won't see any modification because the CSS are now stored in a file automatically generated by SharePoint 2010 and located in a site folder with this kind of url:

/_themes/20/corev4-8A0ABD2F.css?ctag=21

The SharePoint site will reuse the corev4.css file only if you apply the default option for the SharePoint site themes, that is to mean, no theme.

That means that it is really not a good idea to modify the styles by customizing the OOTB themable/corev4.css file since these modifications won't be visible for any sites for which a SharePoint 2010 theme is applied execpted if the theme is applied after the corev4.css customizations. It is not a good idea neither to modify the CSS after having applied a theme by customizing the CSS stored in the theme folder. Were are now considering different approaches to store custom CSS.

2.2 Creating and storing a custom CSS file.

From now, we could either use a <style> tag or  a <link> tag, but assume we have chosen to store the custom CSS in a .css file. We are now going to create a file for the custom styles and try to find the best way to reference it in the SharePoint 2010 wiki page in order to have these custom styles populating the Styles and Markup Styles menus of the Rich text Editor within the SharePoint 2010 ribbon.

Create a sub folder named contoso-marketing in the folder of the themable/corev4.css :

C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\1033\STYLES\Themable





create a new css file named also corev4.css
in this file paste the following code:

/* _lcid="1033" _version="14.0.4536"*/

 

 

DIV.ms-rteElement-mkg-H1

{

    -ms-name: "marketing-header";

    color: #d65c26;

    font-family: Verdana,Geneva,sans-serif;

    font-weight: normal;

    font-size: 2em;

}

2.3 First location for a custom Style CSS: within an HTML Form Web Part inserted in  the wiki page

HTML and JavaScript code and text content are now two things really separated in SharePoint 2010.

A wiki page of a SharePoint 2010 team site provide contributors with a new HTML Editor tool but you cannot add tags like <link>, <style> or JavaScript <script> in the wiki page by using this tool.
It is certainly because some of the great publishing functionalities provided by SharePoint 2010 has been implemented client side by using DHTML and Ajax and this also allows users to write malicious code by using client side code henceforth. So the client side code security has been enhanced and there is consequences with limited HTML and JavaScript code prohibition for the Out Of The Box editing tools.

However there is now the HTML Form Web Part that can be insert into a SharePoint 2010 wiki page, and allows users to write HTML form controls and JavaScript within a wiki page.
I tried then to use this Web Part to insert a <link> tag referencing the custom CSS within the wiki page and it worked like a charm.



Unfortunately, even if it is a good way of testing code in our case, this cannot be used that way in a company, because for each created page you will have to insert a web part with the <link> tag and if a contributor delete the Web Part you will lose your CSS link.
Anyway, having separated the client side code edition in two different Web Parts, one for the HTML tags that contain text and multimedia content (Content Editor Web Part) and one for its layout and publishing improvement like the styles, the DHTML features, etc.(HTML Form Web Part) is a very good idea because you can now limit the use of advanced client side code to power users by tuning the permissions for the HTML Form Web Part.

2.4 Referencing a custom CSS file within the code of the wiki page

Now, we have to reference our custom CSS file in a wiki page in order the styles of this file can be used in the wiki page and can populate one of the two menus of the Rich Text Editor displayed in the SharePoint 2010 ribbon when the wiki page is in edit mode. To be allowed to do that we have to modify one of the wiki page. That can be made in three different ways:

  • Modifying an existing wiki page by using the WebDav and the FrontPage RPC protocols either with SharePoint Designer or Visual Studio
  • Creating a new wki page by writing its code in Visual Studio and then deploying it in the Site Pages library by using a provisioning SharePoint 2010 Feature
  • Finding a way to modify an existing wiki page while letting it in a ghosted state

2.5 Modifying an existing SharePoint 2010 wiki page by using the WebDav and the FrontPage RPC protocols with Visual Studio

Instead of customizing the page with the SharePoint Designer (that uses the WebDav FrontPage RPC protocols) I want to show that it is also possible to do the same with Visual Studio!

You will notice that it is much more difficult to get the code of a SharePoint 2010 Wiki Page than for a SharePoint 2007 Base Page since you are not allowed anymore to open a site page document library by using the Windows Explorer mode or to download a copy of the page on your desktop. But it is still possible by using the following workaround:

Open in Explorer mode one of your site document library.




You will be now allowed to navigate until your SharePoint 2010 Site Pages document library.







Right click the page you want to customize, and open it with Visual Studio. (Now you could also copy and paste a page on your desktop to have the source code of a wiki page)



then in the Place Holder Aditionnal Page Head paste a reference to the the previous custom style sheet and save the page.

        < link type ="text/css" rel="stylesheet" href="/_layouts/1033/styles/themable/contoso-marketing/corev4.css" />





Then, when you refresh the page, SharePoint warns you that the page has been customized and give you a way to revert it to its template (if you do so, you will lose your changes...).



But you can notice when switching to Edit Mode than the Markup menu has been updated and that a new item has been added based on the new style sheet.



And it actually does work!




 So this test shows that you can easily update the menus by creating a custom CSS and reference it by customizing an existing wiki page, but the result is not so good since the page is now customized.
So we will now use a provisioning feature to have a new page within the wiki page document library with the menu updated while preserving its ghosted state .

2.6 - Adding a new wiki page in the Site Pages library by using a provisioning SharePoint 2010 Feature


Previously, we have open a wiki page in Visual Studio. It is a way to get the source code of a wiki page. You can now create 3 new wiki pages in Visual Studio by creating 3 new .aspx pages and pasting the source code of the page we had opened previously, and this time instead of just copying a <link> tag, I propose a cleaner way of referencing the CSS file by duplicating the CSSRegistration component.
So locate the following line:

  <SharePoint:CssRegistration runat="server" Name="wiki.css" />

duplicate it and make the following changes,

<SharePoint:CssRegistration runat="server" Name="/_layouts/1033/styles/themable/contoso-marketing/corev4.css" />

You can eventually also use $SPUrl and ~SiteCollection and ~Language syntax to extend the use of this page but only for the licensed version SharePoint Server 2010 (not for Foundation).

Now, this is the code of the feature and the elements files in order to provision the site pages library with 3 pages.

<?xmlversion="1.0" encoding="utf-8"?>

<FeatureId="00BFEA71-2062-426C-90BF-714C59600AAA"

    Title="test site page"

    Description="test site page"

    Version="1.0.0.0"

    Scope="Web"

    Hidden="false"

    DefaultResourceFile="core"

    xmlns="http://schemas.microsoft.com/sharepoint/">

  <ElementManifests>

    <ElementManifest Location="elements.xml" />

  </ElementManifests>

</Feature>

 

<Elementsxmlns="http://schemas.microsoft.com/sharepoint/">

  <Module Url="SitePages" >

    <File Url="Page01.aspx" Type="GhostableInLibrary"></File>

    <File Url="Page02.aspx" Type="GhostableInLibrary"></File>

    <File Url="Page03.aspx" Type="GhostableInLibrary"></File>

  </Module>

</Elements>

Now you can provision these pages by using stsadm tool to install the feature, then activate it for your site, and will obtain a better result with an updated page in a ghosted state.

This solution is better than the previous one since the provisionned page remained in a ghosted state, but it is not good enough because end users will require a developer each time they want to create a new page, or we might provision several pages, put them in a pending state and they will be approved and published step by step once they are populated, but it is not the best solution. So we have to think about ways of creating wiki pages using the native hyperlink button of the library and have these pages referencing the proper CSS.

However, it might be still interesting sometimes to place a custom wiki page in a wiki library by using a feature if we want a specific wiki page with for example additional server code.

Therefore, it will be fantastic to be able to create custom templates for the wiki pages of a team site in order to place on each the proper reference to the required CSS. Unfortunately as I will explain in the next section, you cannot use only one template for the wiki page of a team site, and as iti is the OOTB template, you cannot imagine to customize it.

2.7 - First limitation of the wiki pages in SharePoint 2010 Foundation: there is only one available template

In SharePoint 2010 Foundation, 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

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 wiht a Page Layout and for the Wiki Pages of the Entreprise Wiki.

 Updated 2011 november 1st--> I have found a workaround that allows to use a custom template: Creating a Wiki Page template For SharePoint 2010 Foundation

2.8 - Second limitation of the wiki page in SharePoint 2010: it is very difficult  to remove the OOTB RTE style

It is really puzzling with SharePoint Foundation, but it is very difficult to REMOVE the OOTB RTE styles. As we have seen before, they are stored in the OOTB corev4.css located at 14\template\layouts\1036\styles\themable\corev4.css, and as we are going to explain, it is very hard to prevent this file from being referenced within a wiki page.

If you use some server code to programmatically specify an alternate css reference for a sharepoint 2010 foudantion team site, you will notice that it works well for a Form page for example, but for a wiki page, the corev4.css will be referenced anyway! (if you disassemble the SharePoint code you will notice that the wiki page adds a reference to the core.css within the onload method of RichTextField control, after that the CssLink control should have changed it into a reference to the corev4.css, although I have not pushed my investigation until that point...)

Anyway, to remove the OOTB RTE style for a wiki page of Foundation you have, as much I can know only two ways:

1 - doing it client side, and there is good approaches like this one

How to leverage Custom Styles & Markup Styles in the SharePoint 2010 CEWP (100% JavaScript Solution)

with good comment in MSDN:

PrefixStyleSheet for ContentEditor web part? (Apply different styles within ContentEditor web part)

2 - Doing it server side by wrapping the CssLink control within a custom one in order to remove the reference to the corev4.css at the rendering time

I have released a draft of this approach on Codeplex. It works well as long as you don't plan to use the SharePoint themes. It has to be completed for that.

 Custom CssLink control for SharePoint 2010 Foundation

 As the custom CssLink used for removing the reference to the corev4.css has to be placed on the masterpage, you will have to use a custom master page anyway, so you will take benefit of it by by using the DefaultUrl property of the control in order to add a reference to your custom CSS.

So, first duplicate the corev4.css and remove the RTE style you don't want anymore. Change the ones you want to keep but modified.
Than register the custom CssLink within a custom master page.

<%@ Register TagPrefix="SharePointCustom" Namespace="CssLinkCustom" Assembly="CssLinkCustom, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3e9566dbc83c01ce" %>

Then, use the custom CssLink control to reference your custom CSS:

<!--csslink custom begin-->
 <SharePointCustom:CssLink runat="server" DefaultUrl="/_LAYOUTS/1033/STYLES/Themable/contoso-marketing/corev4.css"/>
 
<!--csslink custom end-->

You could also have used an alternate CSS, it works also with this control. In the both case here is you will obtain at rendering time:


<!--csslink custom begin-->
<link rel="stylesheet" type="text/css" href="/_layouts/1033/styles/Themable/wiki.css?rev=9pXM9jgtUVYAHk21JOAbIw%3D%3D"/>
<link rel="stylesheet" type="text/css" href="/_LAYOUTS/1033/STYLES/Themable/contoso-marketing/corev4.css"/>
<!--csslink custom end-->

And I am very happy to show you this screen shot obtained with the custom CssLink control:



3 - Workaround to give  its own CSS to each wiki page library of a team site

Let's summarize the case to solve


we have a SharePoint 2010 site page library and we want that all the pages automatically created by end users can reference a custom CSS and of course to have at least a different CSS for each site and if possible for each library.
First of all we cannot use a feature to provision the custom wiki pages that has the reference to the custom CSS although it would let them in a ghosted state because we plan to let end users to create the pages as it is.

We could also place the reference to the custom CSS within the custom master page required to remove the OOTB RTE styles. However, because a master page is defined at least for a site, using a custom master page, we cannot have a CSS for at least a wiki page library or for just a few pages. So let us think to a way allowing each wiki page library of a team site to have its own custom CSS and thus its own style menus.

And a great "nice to have" will be to allow the link to the custon CSS to be typed  within the SharePoint UI so as an administrator of the library could do it.
So, first question, where to type the link to the custom CSS within the SharePoint 2010 UI?

1 - where to type the link to the custom CSS within the SharePoint 2010 UI?

As there is no place to type that kind of reference by using the SharePoint UI at the library level, we will have to use the fields of the wiki pages and there is a workaround that allows us to be sure that all the pages will refer to the same CSS file, and even more, that the contributors won't be able to modify it.

This can be done by creating a custom column with a "choice" type, populating it with only one choice and giving to it this one choice as a default value. Doing that way allows:

  • to have the same value in this field for all the pages
  • only the library administrator can modify the field,
  • have the field automatically populated for all the created page

So let's do it now... (it could also be done with a calculated column...)

Go to the Site Pages library home page and click the button "create a column" located on the SharePoint 2010 ribbon



On the opening Pop Up, set the followings:

"CSS Link" as the name
Remove the choices samples and type the link to the CSS after the _Layouts folder that is to mean in our example:

1033/styles/themable/contoso-marketing/corev4.css



Let the default options for the other controls and clik OK




You can see the new column appear in the default view.




Now, let's try to create a new page.
The page is created with the CCS Link field automatically populated




And this field cannot be modified by a contributor





Now that we are able to have a link to a custom CSS file for each wiki pages library, we have to manage to render this reference in the HTML code of the page. That leads to the second question :

2 - How to use the value of the "CSS Link" field in order to reference the custom CSS file while generating the wiki page HTML?

We could write some server code in the master page but another good solution to solve this is to use a Delegate Control because the Delegate Control is THE way of modifying the HTML code rendered by a SharePoint template without modifying the SharePoint template code.
Although there is no delegate control in the wiki page template (14\TEMPLATE\DocumentTemplates\wkpstd.aspx), there is one in the default master page of SharePoint Foundation 2010 v4.master (14\TEMPLATE\GLOBAL\v4.master), and it seems to have be done for our case because it is located in the <head> section of the page.

<SharePoint:DelegateControl runat="server" ControlId="AdditionalPageHead" AllowMultipleControls="true"/>


Now we have found a Delegate Control at the right place within the master page, the question is to allow the master page to retrieve a value of one of the field of its content page.
This seems to be the vocation of an obscure property of the SPContext object, SPContext.Current.Item about which I have already posted something when I tried to fill the <meta> tags of a page with the fields of a page layout of MOSS 2007. 

Use layout page metadata in masterpages 

We will reuse this property this time to fill the href attribute of the <link> tag with the value of the "CSS Link" field stored at the wiki page level. The <link> tag will be rendered in the <head> section of the master page by using the delegate control.

We can do the Delegate Control and the control in a Visual Studio 2010 project:




Here is the code of the feature files:

Thanks to Chris O'Brien

<Featurexmlns="http://schemas.microsoft.com/sharepoint/" Id="373042ED-718D-46e2-9596-50379DA4D523"

  Title="WikiPageCustomCSS.DelegateControl"

  Description="Replace the master page Header delagate control by WikiPageCustomCSSLink.ascx that get the value of a field within the wiki page"

  Scope="Farm"

  Hidden="FALSE"

  Version="1.0.0.0">

  <ElementManifests>

    <ElementManifest Location="element.xml"/>

  </ElementManifests>

</Feature>

<?xml version="1.0" encoding="utf-8" ?>

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">

  <!-- using a sequence number LOWER than default of 100 so our custom control gets loaded -->

  <Control Id="AdditionalPageHead" Sequence="90" ControlSrc="~/_ControlTemplates/WikiPageCustomCSSLink.ascx" />

</Elements>

And this is the .ascx code:

<%@Control Language="C#" ClassName="WikiPageCustomLink" %>

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

<%@Import Namespace="Microsoft.SharePoint" %>

 

<!-- WikiPageCustomCSSLink.ascx begin -->

 

<script runat="server">   

   

    SPItem myWikiPageItem = SPContext.Current.Item;

    string CSS_link = string.Empty;

    string CSS_Path = string.Empty;

    string HtmlOutput = string.Empty;

    string commentMessage = string.Empty;

 

    protected void GetCustomCSS_Link()

    {

        if (myWikiPageItem == null)

        {

            commentMessage = "<!--WikiPageCustomCSSLink.ascx : the present content page is not stored in a gallery or a library or is not ghostable in its container -->";

            return;

        }

 

        if (myWikiPageItem.Fields.ContainsField("CSS Link"))

        {

            CSS_link = (string)myWikiPageItem["CSS Link"];

        }

        else

        {

            commentMessage = "<!--WikiPageCustomCSSLink.ascx : the present content page does not have a 'CSS Link' field -->";

            return;

        }

 

        if (!string.IsNullOrEmpty(CSS_link))

        {

            CSS_Path = Microsoft.SharePoint.Utilities.SPUrlUtility.CombineUrl(SPContext.Current.Web.Url + "/_Layouts", CSS_link);

            HtmlOutput = "<link rel='stylesheet' type='text/css' href='" + CSS_Path + "' />";

        }

        else

        {

            commentMessage = "<!--WikiPageCustomCSSLink.ascx : the present content page has its 'CSS Link' field empty -->";

        }

    }

 

</script>

 

<% GetCustomCSS_Link(); %>

<%=HtmlOutput %>

<%=commentMessage %>

<!-- WikiPageCustomCSSLink.ascx end -->

 

 

  


Paste the feature and the control within the required folders of your developemnt machine, and install the feature as usual by using the stsadm tool.
Check the farm features and notice that the feature is already activated.



Now navigate to the wiki page previously created and if you view the source code of the page with IE 8 you should see something like that:




But the more interesting is that the Makup Styles menu of the new wiki page is now updated.

Important: The previous code example will not make the custom CSS to be themable. If you want it to be themable, consider using the CssReigstration web control.
For more information, see :Themable CSS Registration and Rendering for SharePoint 2010

4 - To go further

This is some of my new posts on the topic:

--> To manage properly CSS registration and rendering for the theme within SharePoint 2010: Themable CSS Registration and Rendering for SharePoint 2010

--> To perform advanced customization operations (and se the dynamic loading of the rte styles by debugging the SharePoint 2010 Ribbon): Customizing and branding the SharePoint 2010 wiki pages



I have recently started a new set of posts that use all these approach with a real world example of the creation of an Internet-facing web site with SharePoint 2010 foundation.


 

  

18 comments:

Anonymous said...

Thanks a lot! Great info!

Anonymous said...

Very nice post! I'm having trouble removing an item from markup styles, can you enlighten me?

I can't get this to work, "remove the html tag if the same style is applied a second time (this is a way of removing a Markup style)". If it works, please provide a working css example.

Marc Charmois said...

Hi,
what I was writing was at the UI level for end-users. If you apply a style, then apply it again, the second time will cancel the first operation.
But if you want to remove the native styles :

These styles are loaded dynamically

•either from the CSS files by the javascript of the ribbon using AJAX and the XmlHttpRequest object
•or from the wiki page code
, so no way to do it with some code.

The secret is to remove the rteStyle classes from the themable/corev4.css that is referenced by the link tag generated by this control server in the master page (v4.master):

<SharePoint:CssLink runat="server" Version="4" >

So if you want to be compliant with the best practices, you have no other choice than create another corev4.css without the rteStyle classes and to use either an alternate CSS reference if you are using SharePoint Server or to change the master page or do it programmatically if you are using SharePoint 2010 foundation.

It is difficult to use another way because the CSSLink control has become a main component of SharePoint 2010 since it manages other important styles like the CSS of the SharePoint 2010 dialogs, and especially the new SharePoint 2010 themes. Thus, it is dangerous to remove or hide this control to remove the LINK to the native corev4.css

I have now a post on the topic --> Customizing and branding the SharePoint 2010 wiki pages

hope this helps...

Marc

Unknown said...
This comment has been removed by the author.
Unknown said...

Hello,

to remove default style, set the PrefixStyleSheet-Property of the RichHtmlField
(classname has to be lowercase)

PublishingWebControls:RichHtmlFieldFieldName="PublishingPageContent" runat="server" PrefixStyleSheet="xxx-yyyy"

and change :
.xxx-yyyyStyle-Normal-1
.xxx-yyyyFontSize-1
.xxx-yyyyFontFace-1
.xxx-yyyyForeColor-1
H1.xxx-yyyyElement-H1

etc....

Marc Charmois said...

Hi Olive,

thank you,
I have already had the information by Ramun Ocker on a technet forum thread :

http://social.technet.microsoft.com/Forums/en-US/sharepoint2010customization/thread/b98e2c80-bca0-48c6-ae4a-ac7670cbf300

I will update my posts...

Cheers.

Marc

Anonymous said...

Thanks a lot for the great info!

Do you know how to set up the PrefixStyleSheet in the Content Editor Web Part?

Thanks again

Anonymous said...

I cannot get the link tag to work in the HTML FORM Web Part. I am using RTM, and my css file is in the styles library. When I use the CEWP and in the WP properties provide the link to the file it works. Look at the page source, when using the CEWP WP property link it inserts the contents of the file in the page, where as the HTML FORM Web Part leaves it as a link tag. I think link tags only work in head tags.

Anonymous said...

Sorry....just a newbie question. You said "create NEW wiki page using visual studio"...how do I do that? I created an empty SharePoint project. I can add an aspx page but what contents do I need to add to make it a wiki page?

Thanks in advance,
Jake.

Marc Charmois said...

Hi Jake,

you are right, I wasn't clear in my post.
I told about the workaround, but din't reexplain it.
The content of the aspx page that you are creating in Visual Studio can be found by opening the file of a Wiki page within the SharePoint site.
To do this two solutions:
opening the wiki page with SharePoint Designer
copying the page from SharePoint to your desktop, then opening the copy with Visual Studio.

hope this helps...

Marc

Susannah said...

This sounds like exactly what I need! But I'm still at square one because nothing appears for me under Styles or Markup - no OOTB styles, no custom ms-rteStyles...any ideas?

Marc Charmois said...

Hi Susannah,

you say, you have just installed SharePoint, didn't do any customizations, and you just haven't no styles?

Can you confirm, please ?

Thank you.

Marc

Susannah said...

We have several sites up and running with the OOTB branding, and we're in the middle of creating and testing custom branding. Nothing appears for me when I click the "Styles" button in the "Format Text", or "Markup" styles, and I can't apply new colors to text, but I can use "Edit HTML Source". The OOTB styles did appear under the "Styles" button for my coworker, then disappeared the next day. Now I'm wondering if I accidentally cut out an ASP control somewhere. Thanks for responding to comments, by the way - very appreciated!

Matt Stark said...

Hey - great analysis. As an FYI, I posted a solution to the branding pains of the Content Editor Web Part (CEWP)on stackoverflow ... http://stackoverflow.com/questions/7615767/how-to-leverage-custom-styles-markup-styles-in-the-sharepoint-2010-cewp-100-j

Marc Charmois said...

Hi Olive,

your comment is worth for the enterprise wiki page but not for the team site. For the wiki pages of a team site you cannot use a publishing control...

Marc

Marc Charmois said...

Hi Matt, thank you for your client side solution.
I have quite completely rewritten my post and have added a new server side solution for this issue.

Cheers !

Marc

Anonymous said...

Many thanks Marc for a trully fantastic article. Well done. Boris

Marc Charmois said...

Boris,

thank you for reading and encouraging me.

Cheers !

Marc