There’s a JavaScript API for Creating Ribbons!

While the Web is drowning in posts showing how to create ribbons declaratively there’s not a single one mentioning the JavaScript API for this. This API does exist!

Caveat: I haven’t got this to work–the tab won’t show and I don’t have the time to pursue this topic right now. But you would use the API like this:

function createMyTab() {
 debugger;
 var ribbon = SP.Ribbon.PageManager.get_instance().get_ribbon();
 if (ribbon !== null) {
  var contextualGroupIds = ribbon.get_contextualGroupIds();
  if (Array.contains(contextualGroupIds, 'My.ContextualGroup') === false) {
   ribbon.addContextualGroup('My.ContextualGroup', 'Use this ContextualGroup', 'Magenta', 'My.ContextualGroup.Command');
   // Tab object creates default Scaling object
   var tab = new CUI.Tab(ribbon, 'My.Tab', 'A Tab', 'Use this tab', 'My.Tab.Command', true, 'My.ContextualGroup', null);
   ribbon.addChildAtIndex(tab, 0);
   // CUI.GroupProperties isn't defined? CUI.Group's constructor parameters contain values already anyway
   var group = new CUI.Group(ribbon, 'My.Group', 'A Group', 'Use this group', 'My.Group.Command', null);
   tab.addChild(group);
   var layout = new CUI.Layout(ribbon, 'My.Layout', 'A Layout');
   group.addChild(layout);
   var section = new CUI.Section(ribbon, 'My.Section', 2, 'Top'); //2==OneRow
   layout.addChild(section);
   var controlProperties = new CUI.ControlProperties();
   controlProperties.Command = 'My.Button.Command';
   controlProperties.Id = 'My.ControlProperties';
   controlProperties.TemplateAlias = 'control1';
   controlProperties.ToolTipDescription = 'Use this button';
   controlProperties.ToolTipImage32by32 = '/_layouts/$Resources:core,Language;/images/formatmap32x32.png';
   controlProperties.ToolTipImage32by32Left = '-64';
   controlProperties.ToolTipImage32by32Top = '-352';
   controlProperties.ToolTipTitle = 'A Button';
   var button = new CUI.Controls.Button(ribbon, 'My.Button', controlProperties);
   var controlComponent = new CUI.ControlComponent(ribbon, 'My.ControlComponent', 'Large', button);
   var row1 = section.getRow(1);
   row1.addChild(controlComponent);
  }
  contextualGroupIds = ribbon.get_contextualGroupIds();
  if (Array.contains(contextualGroupIds, 'My.ContextualGroup')) {
   ribbon.showContextualGroup('My.ContextualGroup');
  }
 }
 SelectRibbonTab('My.Tab', true);
}

And yes–this sample contains more interesting bugs than my typos and the missing Template and command definitions ;-). But if you are comfortable with the XML to define ribbons the API doesn’t hold many surprises other than the ControlComponent intermediary and the connection of the Layout object–at least that’s what I’ve seen so far.

Most of this is in CUI.debug.js. But the pointers to this kind of API like addChild() methods are not in classes like CUI.Tab or CUI.Group where you would look for them. Instead they are in base classes like CUI.Component.

Microsoft created themselves an infrastructure to implement class hierarchies in JavaScript. Check the calls to registerClass() near the end of CUI.debug.js to get an idea of the inheritance hierarchy. Here are some examples:

null
CUI.ContextualGroup

null
CUI.Component
CUI.RibbonComponent
CUI.Tab

null
CUI.Control
CUI.Controls.Button

null
CUI.Component
CUI.ControlComponent

null
CUI.Component
CUI.Root
CUI.Ribbon

50.000 lines of obfuscated JavaScript in CUI.debug.js, Init.debug.js, SP.debug.js, and SP.Ribbon.debug.js can be a bit overwhelming at first. Just assume the non-obfuscated identifiers mark public interface members aka the API. Happy hacking!

Advertisements
This entry was posted in Uncategorized and tagged , . Bookmark the permalink.

10 Responses to There’s a JavaScript API for Creating Ribbons!

  1. James Milne says:

    Drop me a line on email.

    I have managed to get the ribbon to stay, but now I am missing buttons on the ribbon.

  2. Kosich Deadsky says:

    Love such comments. Will you, by any chance, share your solution? =)

  3. Pingback: Creating SharePoint ribbon elements in JavaScript at UMT CG Software Blog

  4. Dan says:

    I can see one problem with your code:

    You have:

    if (ribbon !== null) {

    There are two equals signs in there. Shouldn’t there only be one?

    Of course, if the rest of it is working, that means my minor nitpick means nothing, but just saying.

  5. Pingback: Intro to Manipulating the SharePoint 2010 Ribbon with JavaScript | The SharePoint Tap Room

  6. Ryan Byrd says:

    I just got this to work in 2013 using the solutions from this page and the others included in the pingbacks. The main difference was I added a button with a control component to the section and then used the getDOMElementForDisplayMode method using the display mode of the Control Component. I hope this helps you guys make something coherent from my chickenscratch…

    _spBodyOnLoadFunctionNames.push(“loadScripts()”);
    function loadScripts(){
    RegisterSod(“jquery-1.8.3.js”, “jquery-1.8.3.js”);
    SP.SOD.executeFunc(“jquery-1.8.3.js”,null,function () {console.log(“Starting custom script”);

    SP.SOD.executeOrDelayUntilScriptLoaded(function () { console.log(“Ribbon Loaded”);
    Type.registerNamespace(‘Foo.Ribbon’);
    Foo.Ribbon.CustomChild = function () {this.customChildren = [];};
    Foo.Ribbon.EnableControl = function (control) {
    if (control) {
    control.set_enabled(true);
    if (control.set_enabledInternal) {control.set_enabledInternal(true);}
    if (control.customChildren) {
    var length = control.customChildren.length;
    if (length < 1) {control.set_enabled(false);} else {
    var element = null;
    var tempChildren = [];
    for (var i = 0; i < length; i++) {
    element = control.customChildren[i];
    Foo.Ribbon.EnableControl(element);
    }
    }
    }
    }
    };
    var pm = SP.Ribbon.PageManager.get_instance();
    pm.add_ribbonInited(function () {afterTabLoaded(); });

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

    if (!ribbon) {if (typeof (_ribbonStartInit) == "function"){_ribbonStartInit(_ribbon.initialTabId, false, null);}}
    else {afterTabLoaded();}
    function afterTabLoaded(){
    var pageManager = SP.Ribbon.PageManager.get_instance();
    var ribbon = pageManager.get_ribbon();

    var tab = new CUI.Tab(ribbon, 'Email.Tab', 'TMS', 'Use this tab for TMS actions', 'Email.Tab.Command', false, '', null);

    ribbon.addChildAtIndex(tab, 1);
    var group = new CUI.Group(ribbon, 'Email.Tab.Group', 'Add to Task', 'Use this group for email operations', 'Email.Group.Command', null);
    var layout = new CUI.Layout(ribbon, 'Foo.Layout', 'Foo.Layout');
    var section = new CUI.Section(ribbon, 'Foo.Section.Small', 2, 'Top');
    $.extend(section, new Foo.Ribbon.CustomChild());

    layout.addChild(section);
    group.addChild(layout);
    group.selectLayout(layout.get_title(), layout);
    tab.addChild(group);

    var row1 = section.getRow(1);
    var fooButton = new CUI.Controls.Button(ribbon, 'Foo.Button',new CUI.ControlProperties());
    var controlComponent = new CUI.ControlComponent(ribbon, 'Foo.MenuItem.Button', 'Large', fooButton);
    v=fooButton.getDOMElementForDisplayMode("Large")

    $(v).html("”)
    $(v).click(function(){
    alert(“Something”)
    })

    section.customChildren.push(fooButton);
    row1.addChild(controlComponent);

    var cmd = new Object();

    cmd.handleCommand = function (commandId, properties, sequenceNumber) {
    var length = section.customChildren.length;
    if (length > 0) {
    var element = null;
    for (var i = 0; i < length; i++) {
    if (section.customChildren[i]) {Foo.Ribbon.EnableControl(section.customChildren[i]);}
    }
    }
    };

    var dispatcher = pageManager.get_commandDispatcher();
    dispatcher.registerCommandHandler(Commands.CommandIds.ApplicationStateChanged, cmd);

    var buttonCmd = new Object();
    buttonCmd.canHandleCommand = function (commandId) {return true;}
    buttonCmd.handleCommand = function (commandId, properties, sequenceNumber) {alert("Button Clicked");}
    dispatcher.registerCommandHandler('Foo.Button.Command', buttonCmd);
    console.log(CUI.Page.ICommandHandler)
    RefreshCommandUI();

    }
    },"sp.ribbon.js");
    });

    }

    • Joseph says:

      I got the tab to display, the group is there too because I see the ‘add to task’ at the bottom. it does NOT have the button coming through. I don’t see an error in the console either.

      • Jaya Borra says:

        Hi Joseph did you get it to work ? I have same problem that you described here .
        if you solved it could you please give some direction what worked for you ?
        Thanks a lot

  7. Joseph says:

    ran your example but also no button. it did write out the HTML for the button but it is disabled. How to enable?

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 )

Google+ photo

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

Connecting to %s