Wednesday, August 27, 2008

Show / Hide Crm Form Toolbar buttons

This is another feature i really thinks ms should consider adding to crm 5.0.
I'm not talking about the code itself but the ability to provide function level security which should include hiding/displaying toolbar buttons, left navigation items, menu items and crm fields (attributes).

The snippet handles both hiding and showing of buttons and spacers.
Paste the code inside the onload event and use the ShowHideToolbarButton with the relevant parameters.



In order to support a multilingual environment you need to separate the button title values with a pipe ("|"). See the first example (save button) bellow.



var Spacer = {
Right : 1, // hides a right spacer if it exists
Left : 2, // hides a left spacer if it exists
Both : 3, // and so on...
None : 4
}

var Display = {
Show : "inline",
Hide : "none"
}

function OnCrmPageLoad()
{
//Configure Display when the form loads.
ConfigreToolbarDisplay();
//Configure the display each time a user manually changes the window width size.
attachEvent("onresize",ConfigreToolbarDisplay);
}

function ConfigreToolbarDisplay()
{
// Opportunity toolbar buttons
// English | German | Spanish
ShowHideToolbarButton( "Save|Speichern|Guardar" , Spacer.None , Display.Hide );
ShowHideToolbarButton( "Follow Up" , Spacer.Right , Display.Hide );
ShowHideToolbarButton( "Recalculate" , Spacer.Left , Display.Hide );
ShowHideToolbarButton( "Attach a File" , Spacer.Both , Display.Hide );
ShowHideToolbarButton( "Follow Up" , Spacer.Right , Display.Show );
}

function ShowHideToolbarButton( btnTitle , spacer , state )
{
if( isNullOrEmpty( document.all.mnuBar1 ) )
return;
if( isNullOrEmpty( btnTitle ) )
return;
if( isNullOrEmpty( spacer ) )
spacer = ToolbarSpacer.None;
if( isNullOrEmpty( state ) )
state = ButtonDisplay.Hide;

//Get all toolbar buttons
var toolBarButtons = document.all.mnuBar1.rows[0].cells[0].childNodes[0].childNodes;

//Loop through each button
for (var i = 0 ; i < toolBarButtons.length ; i++)
{
var button = toolBarButtons[i];
if( button.title.match(btnTitle) != null ||
button.innerText.match(btnTitle) != null)
{
button.style.display = state;
switch(spacer)
{
case Spacer.Right:
ShowHideSpacer( button.nextSibling );
break;
case Spacer.Left:
ShowHideSpacer( button.previousSibling );
break;
case Spacer.Both:
ShowHideSpacer( button.nextSibling );
ShowHideSpacer( button.previousSibling );
break;
}

return;
}
}
function ShowHideSpacer( btnSpacer ){
if( !isNullOrEmpty( btnSpacer ) )
btnSpacer.style.display = state;
}
function isNullOrEmpty( obj ){
return obj == null || typeof(obj) == "undefined" || obj == "";
}
}

OnCrmPageLoad();

22 comments:

Stephen Maij said...

Hi,

Is this code snippet also multi-language proof.. I don't think so ??

Greetz

Stephen

Adi Katz said...

I’ve changed line 38 to handle matching via RegExp. You can separate the title values using pipes to ensure multilingual support.

Anonymous said...

Hi,

Great piece of code! However, I have a issue with this code when I manually resize the window. The toolbar will then reset to its initial state and all removed buttons will be visible.

I have seen this issue addressed here: http://dmcrm.blogspot.com/2008/01/hiding-buttons-in-mscrm-40.html?showComment=1214994240000#c2136068543955672005

Do you know a way I can rewrite you r code to get pass this issue?

regards,
Stian K. D.

Anonymous said...

Stian,

The solution is easy...
Use the window.onresize for this.

Example (I dont use the code above but a less complex code)


var OnResizeHideOrderButtons = function()
{
Hide('_MBcrmFormSubmitCrmForm1truetruefalse');
Hide('_MBLookupAddress');
Hide('_MIonActionMenuClickdelete1088');
RemoveSpacerAfter('_MIonActionMenuClickdelete1088');
Hide('_MIcrmFormSubmitCrmForm1truetruefalse');
Hide('_MILookupAddress');
Hide('_MIgetProducts43');
Hide('_MIcloseOrder3');
Hide('_MIcloseOrder2');
Hide('_MIlock');
}

window.onresize = OnResizeHideOrderButtons;
OnResizeHideOrderButtons();

Adi Katz said...

Hi Stian,

I've revised the code to handle that as well.

Adi

Unknown said...

Hi Adi,

This code works really well, except when you are creating a new activity off the back of a print quote for customer mail merge via the Outlook client.

You can upload your quote back into CRM via a task activity, but when you click on the activity details from the Create Activities window, you get a javascript error on 'document.all.mnuBar1.rows' is null or not an object.

I think this is because the task activity window that's being opened is a cut down version of the task as it's missing the task toolbar entirely.

Is there any chance you could have a look at this please?

cheers

Unknown said...

Hello again,

The same error as I posted above also occurs when you have a campaign. Once you've selected your campaign channel (letter, email, etc) and saved your campaign you hit the 'distribute campaign activity' button. This brings up the selected channel activity and the javascript error on 'document.all.mnuBar1.rows' is null or not an object appears.

Again, the email activity window doesn't display the toolbar.

I would really appreciate it if you could have a look at this error.

cheers

Anonymous said...

Just add some code before:

//Get all toolbar buttons
var toolBarButtons = document.all.mnuBar1.rows[0].cells[0].childNodes[0].childNodes;

Add in:

if( isNullOrEmpty( document.all.mnuBar1 ) )
return;

Unknown said...

Brilliant, that's done the trick.

many thanks for your help.

Adi Katz said...

Hey,

I missed your comments. Thanks for your help Stephen.
Condition added at the top of the ShowHideToolbarButton function.

Adi

Anonymous said...

Doesn't work with custom buttons (they don't have a "title" attribute). Change:

button.title.match(btnTitle)

to:

button.innerText.match(btnTitle)

To make it work.

Adi Katz said...

Thanks. I modified the code to reflect your comment

Anonymous said...

Hi,
this code works great! But I realized issues when I manually downsize the form - the hided buttons reapear. If I again enlarge the form the buttons disappear again. I thought "resize" works in both directions? Do you have any ideas if that behaviour can be avoided somehow?

Adi Katz said...

You have 2 options:
1. Try to overwrite the window.onresize function to restrict the resizing of the page to a certain width and height. The issue with the crm toolbar is that if the window is too small the text of the buttons is deprecated and thus the script does not find the button.

2. Take a look at the comment above yours. As you see I changed the line to reflect the comment. If this is not a custom entity you can use the previous line of code which should work since it uses the button title and not text

The Spelling Police said...

Great bit of code! However, ConfigreToolbarDisplay should probably read ConfigureToolbarDisplay :-)

Anonymous said...

It looks like everyone is getting this to work. However when I paste it into the contacts form the Dynamics Icon dissapears but everything else stays the same. What am I missing. Below is the exact code I ma placing in the ONLoad event


var Spacer = {
Right : 1, // hides a right spacer if it exists
Left : 2, // hides a left spacer if it exists
Both : 3, // and so on...
None : 4
}

var Display = {
Show : "inline",
Hide : "none"
}

function OnCrmPageLoad()
{
//Configure Display when the form loads.
ConfigureToolbarDisplay();
//Configure the display each time a user manually changes the window width size.
attachEvent("onresize",ConfigureToolbarDisplay);
}

function ConfigureToolbarDisplay()
{
// Opportunity toolbar buttons
// English | German | Spanish
ShowHideToolbarButton( "Save|Speichern|Guardar" , Spacer.None , Display.Hide );
}

function ShowHideToolbarButton( btnTitle , spacer , state )
{
if( isNullOrEmpty( document.all.mnuBar1 ) )
return;
if( isNullOrEmpty( btnTitle ) )
return;
if( isNullOrEmpty( spacer ) )
spacer = ToolbarSpacer.None;
if( isNullOrEmpty( state ) )
state = ButtonDisplay.Hide;

//Get all toolbar buttons
var toolBarButtons = document.all.mnuBar1.rows[0].cells[0].childNodes[0].childNodes;

//Loop through each button
for (var i = 0 ; i < toolBarButtons.length ; i++)
{
var button = toolBarButtons[i];
if( button.title.match(btnTitle) != null ||
button.innerText.match(btnTitle) != null)
{
button.style.display = state;
switch(spacer)
{
case Spacer.Right:
ShowHideSpacer( button.nextSibling );
break;
case Spacer.Left:
ShowHideSpacer( button.previousSibling );
break;
case Spacer.Both:
ShowHideSpacer( button.nextSibling );
ShowHideSpacer( button.previousSibling );
break;
}

return;
}
}
function ShowHideSpacer( btnSpacer ){
if( !isNullOrEmpty( btnSpacer ) )
btnSpacer.style.display = state;
}
function isNullOrEmpty( obj ){
return obj == null || typeof(obj) == "undefined" || obj == "";
}
}

OnCrmPageLoad();

Anonymous said...

having same problem with dynamics icon (File Menu Button) in that it doesn't display it with the code i have used, i did a copy of the code from the top and have only changed the show and hide fields. any idea how to resolve and bring the button back? also can you use this functionality to hide certain features within actions drop down menu?

Anonymous said...

Hi Adi (or anyone else),

I need to hide the 'New' button on the main Opportunity window (ie when you click on Opportunities from the main menu). I need to do this as we are forcing users to create Opportunities from within an Account record only. However there is no OnLoad event to write code.
Any ideas?

Cheers
Marc

Withers said...

THANK YOU!

Withers said...

This is hiding the actions menu in addition to the button i'm trying to hide. Any thoughts?

Killianmcc said...

I'm having the same issue as some users above, the Dynamics button has disappeared and the button I wished to remove remains. Any solution for this?

Killianmcc said...

Anyone having an issue like my comment above the following link has a working method;
http://social.microsoft.com/Forums/en-US/253074a3-c091-4e84-9de3-cbfd165c588b/removinghiding-standard-buttons-crm-4