0

Branding a SharePoint site – Part 2

Last week I wrote the first article in a series of articles about branding your SharePoint site. In the first article we discussed how to brand your site and make it available within SharePoint with a Timer Job. In the following article we will make our theme the default theme by using Feature stapling and we will discuss a way to replace all the out of the box search images without replacing the default one in the 12 hive. To make our theme the default theme we will have to create two features. One feature (feature stapling) will activate a feature that activates our theme when a site is created. First we will create a feature to activate our theme. The feature.xml will look like this:

 <?xml version="1.0" encoding="utf-8"?>
 <Feature  Id="b84c13fd-b1ab-4d90-a2c1-9701c732cb5e"
           Title="motion10 Theme Activator : motion10"
           Description="Feature that will activate the motion10 theme for the web. It will also replace the out of the box search images if you have jQuery enabled."
           Version="12.0.0.0"
           Hidden="FALSE"
           Scope="Web"
           DefaultResourceFile="core"
           ReceiverAssembly="Motion10.SharePoint.Theme, Version=1.0.0.0, Culture=neutral, PublicKeyToken=09e87b786333535e"
           ReceiverClass="Motion10.SharePoint.Theme.ThemeActivator"
           Creator="Maik van der Gaag"
           ImageUrl="motion10/FeaturesIcon.png"
           ImageUrlAltText="http://www.motion10.com"
           xmlns="http://schemas.microsoft.com/sharepoint/">
   <Properties>
     <Property Key="Theme:TemplateID" Value="motion10"/>
   </Properties>
 </Feature>

The feature has a feature receiver that activates the theme that is defined in the feature property called “Theme:TemplateID”. The receiver will activate the theme on the web wherefore the feature is activated. On the deactivation of the feature it will deactivate our theme and activate the default theme.

public static readonly string keyTheme = "Theme:TemplateID";
 public override void FeatureActivated(SPFeatureReceiverProperties properties) {
    try {
         SPWeb web = (SPWeb)properties.Feature.Parent;
         string theme = properties.Definition.Properties[keyTheme].Value;

         if (web.Theme != theme) {
             web.ApplyTheme(theme);
             web.Update();
         }
    } catch {
          throw;
    }
 }

 public override void FeatureDeactivating(SPFeatureReceiverProperties properties) {
     try {
          SPWeb web = (SPWeb)properties.Feature.Parent;
          string theme = properties.Definition.Properties[keyTheme].Value;

          if (web.Theme == theme) {
              web.ApplyTheme("none");
              web.Update();
          }
     } catch {
        throw;
     }
 }

As you can see in the code the theme is activated with the ApplyTheme() method on the Web object that we retrieve from the feature properties. When we deactivate the feature we check if the current theme is our theme because we do not want to change the theme if the current theme is not the one we created. When we have created the feature it is time to create a feature with feature stapling. Feature stapling is a way to activate a feature when a site is created with a certain site template. First we create a feature.xml file with a scope of web application.

 <?xml version="1.0" encoding="utf-8"?>
 <Feature  Id="b84r13fd-b1ab-4d90-a2c1-9701g732cb5e"
           Title="motion10 Theme Activator by defailt : motion10"
           Description="Feature that will activate the motion10 theme by default when a site is created."
           Version="12.0.0.0"
           Hidden="FALSE"
           Scope="WebApplication"
           Creator="Maik van der Gaag"
           ImageUrl="motion10/FeaturesIcon.png"
           ImageUrlAltText="http://www.motion10.com"
           xmlns="http://schemas.microsoft.com/sharepoint/">
   <ElementManifests>
     <ElementManifest Location="elements.xml" />
    </ElementManifests>
 </Feature>

In the feature you can see that we defined an elements manifest. In the elements manifest we will define the feature stapling like this:

 <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
    <FeatureSiteTemplateAssociation Id="b84c13fd-b1ab-4d90-a2c1-9701c732cb5e" TemplateName="STS#0" />
    <FeatureSiteTemplateAssociation Id="b84c13fd-b1ab-4d90-a2c1-9701c732cb5e" TemplateName="STS#1" />
    <FeatureSiteTemplateAssociation Id="b84c13fd-b1ab-4d90-a2c1-9701c732cb5e" TemplateName="STS#2" />
 </Elements>

The Id represents the feature Id of the feature that activates our theme. If you would like to make your theme the default theme for every site that is created within your web application you will have to insert a FeatureSiteTemplateAssociation with the template name “GLOBAL”:

 <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
    <FeatureSiteTemplateAssociation Id="b84c13fd-b1ab-4d90-a2c1-9701c732cb5e" TemplateName="GLOBAL" />
 </Elements>

Note: If you use GLOBAL make sure you explicitly make a FeatureSiteTemplateAssociation for STS#1 because the blank site has an attribute “AllowGlobalFeatureAssociations” which is set to false.

Now we have discussed a way to make the theme the default theme we want the search images to be replaced with our own images without replacing the search image in the 12 hive. To accomplish this we will create a jQuery method that replaces the standard gosearch.gif with our own search image. For adding the jQuery method to all of the pages we will use the delegate control AdditionalPageHead to load our jQuery that we add trough a user control. All these components have to be packed into a feature, because we want a minimal count of features we extend our theme activation feature with an elements manifest.

 <?xml version="1.0" encoding="utf-8"?>
 <Feature  Id="b84c13fd-b1ab-4d90-a2c1-9701c732cb5e"
           Title="motion10 Theme Activator : motion10"
           Description="Feature that will activate the motion10 theme for the web. It will also replace the out of the box search images if you have jQuery enabled."
           Version="12.0.0.0"
           Hidden="FALSE"
           Scope="Web"
           DefaultResourceFile="core"
           ReceiverAssembly="Motion10.SharePoint.Theme, Version=1.0.0.0, Culture=neutral, PublicKeyToken=09e87b786333535e"
           ReceiverClass="Motion10.SharePoint.Theme.ThemeActivator"
           Creator="Maik van der Gaag"
           ImageUrl="motion10/FeaturesIcon.png"
           ImageUrlAltText="http://www.motion10.com"
           xmlns="http://schemas.microsoft.com/sharepoint/">
   <ElementManifests>
     <ElementManifest Location="elements.xml"/>
   </ElementManifests>
   <Properties>
     <Property Key="Theme:TemplateID" Value="motion10"/>
   </Properties>
  </Feature>

In the elements file we insert our delegate control.

<?xml version="1.0" encoding="utf-8" ?>
 <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
   <Control Id="AdditionalPageHead"
            ControlClass="Motion10.SharePoint.Theme.SearchImageReplacer"
            ControlAssembly="Motion10.SharePoint.Theme, Version=1.0.0.0, Culture=neutral, PublicKeyToken=09e87b786333535e">
   </Control>
 </Elements>

In the control we place the library off jQuery on the page and also insert our own method. It will search for tags with the attribute src that end with gosearch.gif (default image) and replace the src attribute with our own ImageUrl. Besides that we remove the onmouseover and onmouseout attribute.

public class SearchImageReplacer : UserControl {

         public static readonly string ImageUrl = "/_layouts/images/motion10/Search/gosearch.gif";
         public static readonly string DefaultSearchImageUrl = "/_layouts/images/gosearch.gif";

         protected override void OnPreRender(EventArgs e) {
             base.OnPreRender(e);

             StringBuilder javascript = new StringBuilder();

             javascript.Append("if(typeof jQuery != \"undefined\") {");
             javascript.Append("$(function(){");
             javascript.Append("$(\"[src$='gosearch.gif']\").attr(\"src\", \" " + ImageUrl + " \").removeAttr(\"onmouseover\").removeAttr(\"onmouseout\")");
             javascript.Append("});");
             javascript.Append("}");

             this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "ReplaceSearchImage", javascript.ToString(), true);
         }
     }

Note: If you want to use jQuery in a production environment you have to think about a method for adding the jQuery Library : “ ”. Because when someone creates a webpart that uses jQuery they will insert the declaration into the page. When another user also uses jQuery they will do the same and then you will have two declaration of the jQuery library on the page.

To solve this you can create a feature with a delegate control that inserts the jQuery library into the page. And let the feature you are creating that uses jQuery have an activation dependency to the jQuery feature. If there is enough interest in an article that will explain the above in detail I will write a Branding your SharePoint site – Part 3 so let me know.

Related Posts

Branding a SharePoint site – Part 1 Within SharePoint and WSS you have the possibility to brand your site. You can do this on several ways: A custom style sheet. A custom theme. I thi...

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.