Manipulating the ribbon in SharePoint 2010 with JavaScript: Part 1

This is part 1 of a series I plan to write that covers how to manipulate the ribbon in SharePoint 2010 with JavaScript. I took my inspiration from this post by Chris O’Brien, which also focuses on manipulating the ribbon in SharePoint (but doesn’t cover it from a JavaScript-centric perspective).

This post will introduce the series, explain why I think this topic is important, and give you some quick code samples to get you started.

Why JavaScript?

First, in case you’re wondering about the rationale for messing with the ribbon through JavaScript, I have two words for you: sandboxed solutions. If you weren’t already aware, the SPRibbon class is not available to us in the sandbox. That means if your solution targets SharePoint Online (Office 365), you need an alternative. And so far, almost every blog post and article I’ve found about manipulating the ribbon – especially for adding contextual tabs – relies on using SPRibbon in some capacity.

What about the Declarative/XML Approach?

Many customizations can be done to the ribbon using CustomAction elements in your declarative feature XML. This series on manipulating the ribbon with JavaScript is not intended to replace the declarative approach. Rather, it’s intended to supplement it and give you more options where the declarative approach falls short.

One example is adding a contextual tab that’s associated with a custom web part. Normally this can be done using a combination of declarative XML and some server-side calls to SPRibbon in your web part. However, as I mentioned earlier, SPRibbon isn’t available in the sandbox. The declarative approach alone isn’t enough to get a contextual tab working, so JavaScript can help us fill the gap.

Side note: As a general rule, I try to minimize declarative XML in my SharePoint features anyway. That’s a little tougher to do in sandboxed solutions since you can’t always do everything through code, but even then I’ve found workarounds in most cases by using the client object model or other means. One reason I prefer code over XML is I’ve run into many bugs – as I’m sure many of you have – with how SharePoint processes declarative XML. Another reason is a code-based approach makes feature upgrades easier and more predictable.

The JavaScript Ribbon API

I use the term “API” somewhat loosely because the objects and functions you can use to manipulate the ribbon in JavaScript are not all packaged into a nice clean API like most of the client object model. Finding what you need and using it correctly can be a chore, and that’s why I’ve tried to do a lot of the up-front discovery work for you.

Let’s start with files. The core API is spread throughout the following files in the {SharePointRoot}\TEMPLATE\LAYOUTS folder:

  • Core.js
  • CUI.js
  • Init.js
  • SP.Ribbon.js

As usual, replace “.js” with “.debug.js” to get the non-minimized version of the file that’s more readable for debugging purposes.

It’s also important to know that part of the API is actually embedded directly within the page you’re viewing. To see what I mean, navigate to a page in the SitePages library and view its source. Search for “_ribbonStartInit,” and you’ll see some ribbon initialization code embedded directly within the page. Sometimes you’ll need to make use of that, and if your page doesn’t automatically emit it, you’ll need to add similar code yourself.

It’s also good to know the phrase “Command UI” is often used to refer to the ribbon and its components. Some of the functions, like RefreshCommandUI() in Core.js, don’t use the word “ribbon” in their name.

IMPORTANT: When you’re exploring these files, you’ll see a lot of obfuscated/mangled function and variable names like $K and $10_2. To be safe, always assume that anything mangled is not part of the public API. In my discussion, I’ll stick to the non-mangled items. It’s still possible the non-mangled items may change someday, but it’s less likely… especially because they’re used by many of the OOB web parts.

So far in my testing, I’ve only had to reference “sp.js” and “CUI.js” in my pages to use the API.

One way to include the API is to use ScriptLink tags in the placeholder for additional page head content like this:

<asp:Content ContentPlaceHolderId="PlaceHolderAdditionalPageHead" runat="server">
   <SharePoint:ScriptLink Name="sp.js" LoadAfterUI="true"
                          OnDemand="false" Localizable="false"
                          runat="server" />
   <SharePoint:ScriptLink Name="CUI.js" LoadAfterUI="true"
                          OnDemand="false" Localizable="false"
                          runat="server" />
</asp:Content>

Getting a Reference to the Ribbon

The last thing I’m going to talk about in this first post is getting a reference to the ribbon. This is tougher than it might seem. The ribbon uses an on-demand/lazy loading approach to initialize itself, and that often impacts exactly when you can use certain objects and methods in the API. If you don’t use them at the right time, they’ll be null or will contain invalid data.

For now, let’s assume I’m working on a sandboxed solution for Office 365 and I want to manipulate the ribbon from a web part page in the SitePages library.

Here’s a block of code that will get you a reference to the ribbon and get you started:

<asp:Content ContentPlaceHolderId="PlaceHolderAdditionalPageHead" runat="server">

   <!-- ScriptLink tags for sp.js and CUI.js could go here if you wish -->

   <script language="javascript" type="text/javascript">

      function DoSomethingWithRibbon() {
         // Gets a reference to a CUI.Ribbon object (CUI.js)
         var ribbon = SP.Ribbon.PageManager.get_instance().get_ribbon();

         // Show me which tab is selected - will show
         // 'Ribbon.Read' if the Browse tab is selected.
         alert(ribbon.get_selectedTabId());
      }

      // Note: 'SOD' is an abbreviation for "Script on Demand"
      SP.SOD.executeOrDelayUntilScriptLoaded(function() {

         var pm = SP.Ribbon.PageManager.get_instance();

         pm.add_ribbonInited(function() {
            DoSomethingWithRibbon();
         });

         var ribbon = null;
         try
         {
            ribbon = pm.get_ribbon();
         }
         catch (e) { }

         if (!ribbon) {
            if (typeof(_ribbonStartInit) == "function")
               _ribbonStartInit(_ribbon.initialTabId, false, null);
         }
         else {
            DoSomethingWithRibbon();
         }
      },
      "sp.ribbon.js");
   </script>
</asp:Content>

If you’re thinking that seems like a lot of code just to get a reference to the ribbon, you’re right. But it’s necessary. Let’s break down what’s being done here…

First, the code is wrapped in an executeOrDelayUntilScriptLoaded() call to ensure SP.Ribbon.js has been loaded. Nothing too fancy there.

The next piece you should look at is the try/catch block. I copied this code from one of SharePoint’s OOB web parts for the sake of consistency. Essentially we’re checking whether the ribbon has been loaded and is available to us to manipulate. If not, we cause it to load by calling the _ribbonStartInit() function. In case we had to cause it to load, we added a handler for the PageManager’s ribbonInited event above. Up until the point that event is fired, calling get_ribbon() would return null.

Wondering where the _ribbonStartInit() function is defined? The answer is in the page itself (along with the _ribbon.initialTabId variable). I’ve only tested this with pages in the SitePages library so far, but if you view the source on any page in that library, you’ll see that function defined in the page. And the OOB web parts rely on it being there, so I assume it’s there pretty consistently. If you delve into the details of it, you’ll see that it sets some options on a “ribbon builder” object and then dynamically constructs the ribbon. More on that in another post.

And if you’re wondering why the ribbon wasn’t already loaded when the page was first rendered, there’s a reason. Assuming your page comes up with the Browse tab selected first, the ribbon isn’t really loaded. Even if other tabs are present (like the Page tab), if they haven’t been shown yet, the ribbon has had no reason to load any of its controls or page components. Remember everything the ribbon does is on demand. The default behavior is the ribbon isn’t loaded until something happens that forces it to (like clicking the Page tab).

Conclusion

That’s it for this first post. Hopefully you found it helpful. The next one in the series will cover the most common API objects and methods you’ll use in manipulating the ribbon (and a lot of them aren’t documented on MSDN… hence the reason I’ll be doing it here).

About these ads

3 thoughts on “Manipulating the ribbon in SharePoint 2010 with JavaScript: Part 1

  1. Pingback: Set the Ribbon Initial Tab in SharePoint 2010 « All About SharePoint

  2. Great article. Thank you.
    I’ve used your script to activate the ‘Browse’ tab when a user hits the list item Display form.

    I just changed the line alert(ribbon.get_selectedTabId()); with SelectRibbonTab(“Ribbon.Read”, true);

    Works like a charm :-)

  3. Thank you very much for posting this script! I’ve been driving myself nuts trying to set the default tab in a list/library dispform with a client side script, and this was just what I needed.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s