Thursday 28 June 2012

Performance enhancements in Sharepoint 2010 using Css sprites


Today, let's learn a technique that improves the performance of your web page. It's the CSS sprite!

The idea of this technique is to combine all the images that you use in your web page into one single image and seperate out each image using some simple css code.

So, here's how you get started on the sprites in the world of web.

Step 1:
Google for any site that generates a css sprite image for you, you can also download tools for the same purpose but online is much quicker according to me.

I generally use InstantSprite.com. Once you are in the site, upload all your images on it, it immediately creates the sprite image, the corresponding css code. You can also specify the gap between each image if you want.

 


Step 2:
Save the css sprite image on to your desktop from the site, copy paste the css code into a notepad for future reference.

Step 3:
Now, let's make use of what has been generated. In order to use the new image named csssprite.png for ex in your project, add it to the mapped images folder. Then, copy the txt file which contains the css code also into the mapped layouts folder. Open the .aspx page for ex where you have to use the new image. Now, modify the "src" to point to the new image and provide the style containing the "top","left","width" and "height" values, this the most Important step in the whole process.

Make sure you use the corresponding css code which points to that image, this should be fetched from the .txt file which has the css code.

Typical Css Sprite image


Typical Css Sprite code
.sprite { background: url('sprite.png') no-repeat top left; width: 96px; height: 96px;  }
.sprite.Alien1 { background-position: 0px 0px;  }
.sprite.Alien2 { background-position: 0px -106px;  }
.sprite.Balloon { background-position: 0px -212px;  }


Example of a css sprite image being used in an .aspx page
<img id="imgPictY" src="/_layouts/images/MyWebpart/webpartCssSprite.png"
                runat="server" style="top: -52px;left:0px;position:absolute;" /> 

Step 4:
Once the changes have been made and the solution has been updated, you need to now check that the new images are being loaded. You might need to clear your browser's cache before reloading. To make sure the right image is loaded, i generally use HttpWatch and look at the round trip calls which will have the call made to the new css sprite image.

Advantages of using Css sprite
1. Reduces the number of calls to the server.
2. Easy to use, modifying the code is uncomplicated.
3. All you images are stiched into one, hence images called in different locations are loaded even before the page is accessed.

Disadvantages of using css sprite/ Things to be aware of before creating one
1. Adding too many images together in one css sprite image can increase the image size and hence the load time of the page
2. Updating an existing css sprite image is not the easiest and has to done with precision to make sure the css code doesnt change for old images.

All in all, we found that using this techinque in our project has worked wonderfully well and has reduced the calls to the server by 15%. This is a very powerful technique to improve the performance of your site if used in the right way.

Create custom Ribbon groups and show values in the ribbon

This is my first blog on Sharepoint customisations, finally have the time to give back to the Sharepoint community!

Let's play around with our very own Sharepoint 2010 ribbon today!

So bascially, what we are trying to do is add a custom group to an OOTB ribbon tab, show values related to the selected web part in a label or a textbox.
The challenge here is, unlike simple requirements like button click on the ribbon where we get an event to work with, showing values on load of the ribbon is much more difficult
as there is no particular custom event we can work with easily, the only one available is the ribbon on load, and its OOTB!

Lets get started with it then...
1. First we create the ribbon group within a OOTB Ribbon Tab, lets work with the ribbon available on the Media part for this.
    For this, we need to get the 'Location' value which will be specified in our 'CustomUIDefinition' absolutely right. Append '_children' to the 'location' in order to continue
adding the new group. Now, Add the group with required values like 'template' and 'id'. Then, add the required controls under the 'Controls' tab, here we will use a Label and a 
text box. Along with this we also specify the 'command' and the 'querycommand' which actions any required event.
    Next, very important!, to show the contents of the new group, we need to create a new element specifying the max size, this tells which group will have how much spacing in
order to show the contents with in. Again for this the exact location has to be specified


Code:
<CommandUIDefinition Location="Ribbon.ContextualTabs.Media.Options.Scaling._children">
            <MaxSize Id="Ribbon.ContextualTabs.Media.Options.Scaling.Url" GroupId="Ribbon.ContextualTabs.Media.Options.Url" Size="MediumMedium" Sequence="50"/>
        </CommandUIDefinition>
        <CommandUIDefinition Location="Ribbon.ContextualTabs.Media.Options.Groups._children">
          <Group
              Id="Ribbon.ContextualTabs.Media.Options.Url"
              Sequence="40"
              Template="Ribbon.Templates.Flexible2"
              Title="Url"
              Description="">
            <Controls Id="Ribbon.ContextualTabs.Media.Options.Url.Controls" >
              <Label
                Id="Ribbon.ContextualTabs.Media.Options.Url.UrlLabel"
                Sequence="10"
                LabelText="Url"
                TemplateAlias="o1"
                />
              <TextBox
                Id="Ribbon.ContextualTabs.Media.Options.Url.UrlValue"
                Sequence="20"
                Command="Media.GetUrl"
                QueryCommand="Media.GetUrl.Query"
                TemplateAlias="o2"
                ToolTipTitle="Url"
                ToolTipDescription="To change the url of the video, go to 'Change Media' -> 'From Address'"
                ShowAsLabel="true"
                />
            </Controls>
          </Group>
        </CommandUIDefinition>

This is what you see when the above code is deployed

 
2. The next step is to create the javascript code required to show the values which we need on the ribbon. 
 The first step for this is to load the required javascript file through our CustomAction tab. This would be a loader file which would call all the required methods which in turn loads other javascript files which contains code for the actual work done behind.
One more challenge we might face here is how to load the .js files and when to load them, for us this file has to load only when the media web part is selected and not any where else as that can cause unnecessary memory blocks within the page load. The best way to do this is use _spBodyOnLoadFunctionNames.push() method. Then we need to register the .js file which contains the code for the init(), handlecommands(), etc. In the handlecommand we need to specify the 'command' and 'querycommand' used earlier, here the required code is added to get/set values in
our textbox.


Code:
  <CustomAction ScriptSrc="/_layouts/myRibbon/js/.PageComponent.Loader.js"
        Location="ScriptLink"  
        Sequence="1000" />
Code to be added in PageComponent.Loader.js
function myInit() {
    RegisterSod("myRibbon.pagecomponent.js", "/_layouts/myRibbon/js/myRibbon.PageComponent.js");
    SP.SOD.executeFunc("myRibbon.pagecomponent.js", null, null);
    ExecuteOrDelayUntilScriptLoaded(initRibbon, 'myRibbon.PageComponent.js');
}
function initRibbon() {
    myRibbon.PageComponent.initialize();
}
_spBodyOnLoadFunctionNames.push("myInit");


Code to be added in myRibbon.pagecomponent.js
Type.registerNamespace('myRibbon.PageComponent');
myRibbon.PageComponent = function () {
    myRibbon.PageComponent.initializeBase(this);
};
myRibbon.PageComponent.initialize = function () {
    ExecuteOrDelayUntilScriptLoaded(myRibbon.PageComponent.initializePageComponent, 'SP.Ribbon.js');
};
myRibbon.PageComponent.initializePageComponent = function () {
    var ribbonPageManager = SP.Ribbon.PageManager.get_instance();
    if (null !== ribbonPageManager) {
        ribbonPageManager.addPageComponent(myRibbon.PageComponent.instance);
    }
};
myRibbon.PageComponent.prototype = {
    init: function () {
    },
    getFocusedCommands: function () {
        return ['Media.GetUrl', 'Media.GetUrl.Query'];
    },
    getGlobalCommands: function () {
        return ['Media.GetUrl', 'Media.GetUrl.Query'];
    },
    canHandleCommand: function (commandId) {
        if (commandId === 'Media.GetUrl' ||
            commandId === 'Media.GetUrl.Query') {
            return true;
        } else {
            return false;
        }
    },
    handleCommand: function (commandId, properties, sequence) {
        if (commandId === 'Media.GetUrl.Query') {
            alert('the textbox values will show!')
        }
    },
    isFocusable: function () {
        return true;
    },
    receiveFocus: function () {
        return true;
    },
    yieldFocus: function () {
        return true;
    }
};
myRibbon.PageComponent.registerClass('myRibbon.PageComponent', CUI.Page.PageComponent);
myRibbon.PageComponent.instance = new myRibbon.PageComponent();
NotifyScriptLoadedAndExecuteWaitingJobs('myRibbon.pagecomponent.js');

This is the end result what you see...


Well, thats it for now with Ribbons in Sharepoint 2010.