WEBSITE

Microsoft SharePoint 2010 Web Applications : Presentation Layer Overview - Ribbon (part 2) - Complex Event Handling

12/24/2012 2:53:15 AM

3. Complex Event Handling

The preceding examples have shown you how to handle events using embedded JavaScript; although this works well, as the JavaScript becomes more complex, it gets increasingly difficult to manage. A common approach to dealing with this problem is to maintain scripts as separate files. Let’s look at how we can use external scripts when handling events.

Adding Script Links Using a Delegate Control

The first thing that we need to do when using external scripts is to find a way to add a link to the script to our page. The best method to achieve this is to use a delegate control. The out-of-the-box master page that ships with SharePoint 2010 includes a delegate control named AdditionalPageHead in the page header. By adding our own content to this delegate, we can add references to our external scripts.

  1. The easiest way to implement a delegate control is to add a user control to the %SPROOT%/TEMPLATE/CONTROLTEMPLATES folder. This folder is mounted on all SharePoint sites as/_ControlTemplates/, and user controls contained here can use code-behind in assemblies that are stored in the Global Assembly Cache (GAC). To add a new user control, choose Project | Add New Item. Select User control in the Add New Item dialog and set the name to CustomRibbonHeader.ascx, as shown next:

  2. The new user control will be placed in the ControlTemplates/Example folder by default. In the CustomRibbonHeader.ascx file, add the following markup:

    <SharePoint:ScriptLink Name="SP.js" LoadAfterUI="true"
       OnDemand="false" Localizable="false" runat="server" ID="ScriptLink1" />
    <SharePoint:ScriptLink Name="CUI.js" LoadAfterUI="true"
      OnDemand="false" Localizable="false" runat="server" ID="ScriptLink2" />
    <SharePoint:ScriptLink Name="/_layouts/Example/Example.PageComponent.js"
                           LoadAfterUI="true" OnDemand="false" Localizable="false"
                           runat="server" ID="ScriptLink3" />
    
    
    					  

    This code snippet uses ScriptLink controls to ensure that all required scripts are loaded. SP.js contains core functions for the JavaScript Client Object Model, whereas CUI.js contains functions necessary for the operation of the ribbon.

  3. In the Elements.xml file containing our CustomAction element, add the following element after the closing tag of the CustomAction element:

    <Control Id="AdditionalPageHead"
      Sequence="49"
     ControlSrc="~/_controltemplates/Example/CustomRibbonHeader.ascx"/>
    

    This code hooks up our delegate control to the AdditionalPageHead delegate.

  4. Since the whole purpose of adding a delegate control is to include a link to our custom external script file, our next step is to create the file. Select the Example project node in the Solution Explorer pane, and then choose Project | Add SharePoint Layouts Mapped Folder.

  5. Add a new JavaScript file into the Layouts\Example\ folder named Example. PageComponent.js. The final ScriptLink control in the preceding code snippet will ensure that a reference to this file appears on the page.

Creating a Page Component

A page component is effectively a JavaScript code-behind file for our ribbon customization. Page components are derived from the CUI.Page.PageComponent class that can be found in cui.js, the out-of-the-box JavaScript file that is concerned with delivering the core functionality of the ribbon.

Tip

Many script files used in SharePoint have a debug version that is easier to read. These files commonly have a .debug.js extension, such as CUI.debug.js.


By creating a custom page component and overriding the appropriate methods, we can encapsulate the event handlers for our tab in a separate file. Follow these steps to create a simple page component to support the demo tab that we added earlier.

  1. In the Example.PageComponent.Js file that we created earlier, add the following code:

    Type.registerNamespace('Example.PageComponent');
    Example.PageComponent = function () {
        Example.PageComponent.initializeBase(this);
    }
    Example.PageComponent.initialize = function () {
        ExecuteOrDelayUntilScriptLoaded(Function.createDelegate(null, →
    Example.PageComponent.initializePageComponent), 'SP.Ribbon.js');
    }
    Example.PageComponent.initializePageComponent = function () {
        var ribbonPageManager = SP.Ribbon.PageManager.get_instance();
         if (null !== ribbonPageManager) {
            ribbonPageManager.addPageComponent(Example.PageComponent.instance);
        }
    }
    Example.PageComponent.prototype = {
        init: function () { },
        getFocusedCommands: function () {
            return [''];
        },
        getGlobalCommands: function () {
            return ['Example.HelloWorldCommand']
        },
        canHandleCommand: function (commandId) {
            if (commandId == 'Example.HelloWorldCommand') {
                return true;
            }
            else {
                return false;
            }
        },
        handleCommand: function (commandId, properties, sequence) {
            if (commandId === 'Example.HelloWorldCommand') {
                var notificationId =
            SP.UI.Notify.addNotification('Hello World from page component');
            }
        },
        isFocusable: function () { return true; },
        receiveFocus: function () { return true; },
        yieldFocus: function () { return true; }
    }
    Example.PageComponent.registerClass('Example.PageComponent',
                                          CUI.Page.PageComponent);
    Example.PageComponent.instance = new Example.PageComponent();
    NotifyScriptLoadedAndExecuteWaitingJobs("Example.PageComponent.js");
    
    
    					  

    This script defines a new class, Example.PageComponent, which inherits from CUI.Page.PageComponent. By using this object, we can add all of our event handling code within a separate file rather than having everything contained within the CommandAction attribute of CommandUIHandler elements.

    The getGlobalCommands method returns a list of the commands that are supported by the page component—in our case, we’re supporting only one command. The canHandleCommand method is used to specify whether an item should be disabled or not, and the handleCommand method is where we can add the actual implementations for our event handlers. Commonly, these will take the form of method calls.

  2. Since we’re no longer using the inline script in our CommandUIHandler element, replace the attribute as follows:

    <CommandUIHandlers>
    <CommandUIHandler Command="Example.HelloWorldCommand" CommandAction=""/>
    </CommandUIHandlers>
    
  3. To initialize our custom page component, add the following JavaScript to the CustomRibbonHeader.ascx file after the ScriptLink controls:

    <script type="text/javascript">
    //<![CDATA[
        function initExampleRibbon() {
            Example.PageComponent.initialize();
        }
    ExecuteOrDelayUntilScriptLoaded(initExampleRibbon, 'Example.PageComponent.js');
    //]]></script>
    
    
    					  

We’re now ready to deploy the revised solution. This time, clicking the Hello World button will return the message specified in the Example.PageComponent.js file.

Server-Side Event Handling

So far, you’ve seen how to add ribbon customizations and handle events using inline JavaScript as well as via a custom page component. While this is very much the recommended approach, for some functionality, access to the Server Object Model may be a requirement.

As well as creating page component files and manually writing JavaScript to handle our events, SharePoint 2010 also provides server-side objects that can be used to add commands to an existing custom page component. We’ll add a new button for the purposes of this demonstration.

  1. In the Elements.xml file, add the following Group element after the closing tag for the existing Group element:

    <Group Id="Example.SecondDemoGroup"
         Description="Contains Demo controls"
         Title="Demo Group 2"
         Sequence="51"
         Template="Ribbon.Templates.SingleButton">
    <Controls Id="Example.SecondDemoGroup.Controls">
      <Button
        Id="Example.SecondDemoGroup.HelloWorld"
        Command="Example.HelloWorldServerCommand"
        Sequence="15"
        Image16by16="/_layouts/images/NoteBoard_16x16.png"
        Image32by32="/_layouts/images/NoteBoard_32x32.png"
        Description="Displays a Hello World message"
        LabelText="Hello World"
        TemplateAlias="c1"/>
    </Controls>
    </Group>
    
  2. So that the new group will display properly, we need to add a Scaling/MaxSize element. Between the existing MaxSize and Scale elements, add the following element:

    <MaxSize Id="Example.SecondDemoGroup.MaxSize"
             GroupId="Example.SecondDemoGroup" Size="OneLarge"/>
    
  3. Add the following code to the CustomRibbonHeader.ascx.cs file:

    public partial class CustomRibbonHeader : UserControl,IPostBackEventHandler
      {
        public void RaisePostBackEvent(string eventArgument)
         {
          SPRibbonPostBackEvent pbEvent =
            SPRibbonPostBackCommand.DeserializePostBackEvent(eventArgument);
           SPContext.Current.List.Title = "Updated " + DateTime.Now;
          SPContext.Current.List.Update();
         }
         protected override void OnPreRender(EventArgs e)
         {
           List<IRibbonCommand> commands = new List<IRibbonCommand>();
           commands.Add(new SPRibbonPostBackCommand("Example.HelloWorldServerCommand",
                                                    this, "true"));
           SPRibbonScriptManager sm = new SPRibbonScriptManager();
           sm.RegisterGetCommandsFunction(this.Page, "getGlobalCommands", commands);
           sm.RegisterCommandEnabledFunction(this.Page, "canHandleCommand", commands);
           sm.RegisterHandleCommandFunction(this.Page, "handleCommand", commands);
         }
      }
    
    
    					  
  4. Make the following modification to the Example.PageComponent.js file:

    Example.PageComponent.prototype = {
        init: function () { },
        getFocusedCommands: function () {return [''];},
        isFocusable: function () { return true; },
        receiveFocus: function () { return true; },
        yieldFocus: function () { return true; },
        getGlobalCommands: function () {
            var commands = getGlobalCommands();
            return commands.concat(['Example.HelloWorldCommand']);
         },
         canHandleCommand: function (commandId) {
             if (commandId == 'Example.HelloWorldCommand') {
                 return true;
             }
             else {
                 return commandEnabled(commandId);
             }
         },
         handleCommand: function (commandId, properties, sequence) {
            if (commandId === 'Example.HelloWorldCommand') {
                var notificationId =
            SP.UI.Notify.addNotification('Hello World from page component');
            }
             else {
                return handleCommand(commandId, properties, sequence);
            }
         }
     }
    
    
    					  
  5. Deploy the revised solution. The Example tab will now contain two buttons: When the first button is clicked, a notification will be displayed as before. When the second button is clicked, the name of the current list will be updated to include a time stamp, confirming that our server-side code is being executed.

In this sample, we’ve used the SPRibbonPostBackCommand to create a command programmatically that emits the JavaScript code necessary to perform a server post back. When using this technique, bear in mind that a custom page component is required. The page component must make calls into the base class for getGlobalCommands, commandEnabled, and handleCommand to hook up the server side event handler properly.

Other  
 
Video
Top 10
SG50 Ferrari F12berlinetta : Prancing Horse for Lion City's 50th
The latest Audi TT : New angles for TT
Era of million-dollar luxury cars
Game Review : Hearthstone - Blackrock Mountain
Game Review : Battlefield Hardline
Google Chromecast
Keyboards for Apple iPad Air 2 (part 3) - Logitech Ultrathin Keyboard Cover for iPad Air 2
Keyboards for Apple iPad Air 2 (part 2) - Zagg Slim Book for iPad Air 2
Keyboards for Apple iPad Air 2 (part 1) - Belkin Qode Ultimate Pro Keyboard Case for iPad Air 2
Michael Kors Designs Stylish Tech Products for Women
REVIEW
- First look: Apple Watch

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
Popular Tags
Video Tutorail Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Exchange Server Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe Photoshop CorelDRAW X5 CorelDraw 10 windows Phone 7 windows Phone 8 Iphone