Friday, January 17, 2014

Hide Specific Buttons on a SharePoint 2010 Ribbon Using Javascript

I recently had a project where I needed to have the user take action on SharePoint data using a custom form, and then have a workflow handle the updates into another library, thus preventing the user from directly managing the main body of data. Contribute permissions were required because SharePoint Workflows don't have the ability to 'run as' admin or service or any other user or to set permissions on an item in the workflow. Both of those would be great additions to the SharePoint Workflow foundation.

So I used a combination of custom forms, specific permission levels, audience targeted web parts and other means to show the user only what they need to see and create "security through obscurity."

Contribute(edit) permissions are required in this case, but I wanted to allow a user to "view" a list item without having the prominent "Manage" ribbon group and the "Edit" button at the top of the form page (dispform.aspx, etc...)

There are fairly easy ways to hide the ribbon from certain users which work well but it's not granular enough and my permissions on this site are not that simple. It is also possible to create a custom ribbon and/or code and deploy to achieve these things.

BUT:
I wanted an easy, quick, and non-invasive means of shutting off certain buttons. So here is what I did.

The ribbon is split up into tabs. Each tab can have one or more groups of controls, and each group can hold one or more controls.




It's easy to find the id of any one of these and then use javascript to edit the object.

In Internet Explorer, hit F12 (developer tools) or use Firebug or some other equivalent in another browser.
Find the ribbon using the click tool or search for "<div class="loaded" id="RibbonContainer">"


You can see the structure of the whole ribbon there along with all of the element IDs. Pay attention to the CSS classes for an easy way to pick out the pieces.



OK, so anyone familiar with javascript knows that you can grab the object and set a style parameter like this:
object.style.parameter = value;
So it is logical that to hide the group, I just set object.style.display = 'none'; and it will disappear.

Not too complex, except that SharePoint ribbons are loaded when needed, not on page load, so you can't just put some javascript at the end of the page and hide the element. So first you need to make sure the object exists. If it does not exist, wait and try it again in some period of time. And lastly, if you don't want a looping script, so set a counter to make sure it only tries a few times before completely giving up.

Here is my example using the "Clipboard" group

<script language="javascript">
var cntr = 0; //set counter
function hidegroup(){
    if(document.getElementById('Ribbon.EditingTools.CPEditTab.Clipboard') != null){ //check to make sure object exists
        document.getElementById('Ribbon.EditingTools.CPEditTab.Clipboard').style.display = 'none'; //hide it
    }else if(cntr<6){//does not exist, check counter
        cntr++;//increment counter
        setTimeout('hidegroup()', 1000); //wait 1 sec and then repeat
    }
}
</script>
  • The counter starts at zero and once it runs 5 times, it quits.
  • If the object exists, it hides it. I noticed that if you set innerHTML to an empty string, the other buttons may not function.
  • If the object doesn't exist it increases the counter by one and then waits 1,000 miliseconds and then calls the function again.
To use this on a page, edit and place a content editor web part on the page under the form web part, edit the HTML of the content editor web part and put the script into the HTML field.



Set the web part to hidden (Edit Web Part -> layout (section) -> Hidden) so that nobody sees it. Hidden web parts are still on the page and the javascript will run just fine.

The last step is to use the web part's audience targeting field (in the "Advanced" section) to decide who will see the web part. The targeting can be done on groups and/or users. Whoever is targeted will have the web part, and whoever has the web part will have the ribbon group disabled.



This is perfect for a form like dispform.aspx or editform.aspx that automatically displays the ribbon. The only delay is in loading the ribbon. Other pages have ribbons that load contextually whenever the user interacts with a control that has a ribbon. Removing controls or groups for those pages could be done by removing the counter, which would cause a constant loop waiting for the element to show up.



For me, this works perfectly because it was a quick fix, can be targeted to a SharePoint security group, can remove specific items, and is all done in the browser.

Disclaimer: this is by no means the best way, but it is very simple and quick.