And the first question is WHY?
Yes, that was the first question someone asked me when I posed this question on Twitter [#sphelp]. And, it is a valid question! There are of course other more "approved" ways of creating tabs and buttons, and these options are more supported and have access to the current item or list or webpart that may be selected. However, there are some times when you can not use these methods and it is usually for the same reasons you can't do other things the "approved" way.
- You can not in any way shape form or fashion deploy custom or sandboxed items from Visual Studio.
- You may have SharePoint Designer, but you don't have the time to do this on every site and sub site you want your button on.
- Or, you might want to have something that is always available on as many pages regardless of what the content type is or if you are on a list view or not.
And so the next part is the Good Luck part!
So, if you know me, and understand my "SPEvilGenius" moniker, you will realize that I like a challenge even if the result is not "approved" or may not be fully "future proof"
This challenge was presented to me by a friend of mine who has all 3 of the presented reasons above. He had done a lot of great groundwork getting some good information on the subject. There actually is not a whole lot out there on trying to do this. However, there are javascript libraries in SharePoint that are used to manipulate the ribbon, and why would these not be "approved". Unfortunately the documentation is extremely scarce to non-existent! But that did not mean that it could not be done!
So the solution begins!
So the below code was placed in a CEWP on a simple wiki page in the site pages library. I actually referenced the code as it was uploaded to the site assets library.
<script type="text/javascript"> function createMyTab() { var shtml = ""; shtml += "<a href='#' onclick='SendIt(); return false;'><img src='/Style Library/Images/mail1small.png' /></a>"; var ribbon = SP.Ribbon.PageManager.get_instance().get_ribbon(); if (ribbon !== null) { var tab = new CUI.Tab(ribbon, 'Email.Tab', 'Email', 'Use this tab for emailing users', 'Email.Tab.Command', false, '', null); ribbon.addChildAtIndex(tab, 1); var group = new CUI.Group(ribbon, 'Email.Tab.Group', 'Email Actions', 'Use this group for email operations', 'Email.Group.Command', null); tab.addChild(group); } SelectRibbonTab('Email.Tab', true); $("span[title*='Email']").prev("span").html(shtml); } function SendIt() { alert("Hello from pure javascript/jquery ribbon tab and button!"); } SP.SOD.executeOrDelayUntilScriptLoaded(function () { var pm = SP.Ribbon.PageManager.get_instance(); pm.add_ribbonInited(function () { createMyTab(); }); var ribbon = null; try { ribbon = pm.get_ribbon(); } catch (e) { } if (!ribbon) { if (typeof (_ribbonStartInit) == "function") _ribbonStartInit(_ribbon.initialTabId, false, null); } else { createMyTab(); } }, "sp.ribbon.js"); </script>
So this code does a few things. First I set a variable with the "button" image I am using set on an anchor tag that has a click event to fire a function. Simple jQuery there. The magic is part of the CUI.js file and SP.Ribbon js file. These are supposedly able to allow you to create items in script and for some of this it worked great! However, I had hoped to get a layout, section, and button from them added as well. If anyone knows how this might be done, please let me know! So after getting a tab and group added by the code, I then just use jQuery to add that html from the variable into that "group". This worked great and I got a tab with a group and a button that is clickable with just a few lines of code.
I plan to take the time to try to do more with this and see what I can do. Part 2 of this will be the results of those tests! Any feedback is appreciated!
Great work, Dan! I believe we have all underestimated your sneakiness.
ReplyDeleteHi Daniel,
ReplyDeleteBack in January I reached out to you on Twitter ( https://twitter.com/paul_tavares/status/422445212007677952) to thank you for this post... It provided the evidence I needed to pursue creating a javascript library to create custom Ribbon Tabs... I just finished writing a blog post about a SP App where I use that library to create Ribbons... I'm including a reference to this post and wanted to again thank you for taking the time to write about your experience.
I know you said you were interested on what I came up with, so I will reach out to you on Twitter to get your email and will send you something.
Paul Tavares.
great post! the only thing that dint work for me was the selector for span. So instead of
ReplyDelete$("span[title*='Email']").prev("span").html(shtml);
I made use of the following selector:
$("span:contains('Email Actions')").prev("span").html(shtml);
Cheers