Further to previous posts HERE on how to hide ISV buttons, I recently came across a new wrinkle in the problem, essentially, I needed to be able to access the properties of that ISV button in order to create a toggle button. Knowing as we do that CRM4 adds some random number to the definition of a button, I really needed to find a way around this.
The Problem
If you create a new ISV button for yourself (on accounts in this case), and you use the Developer Toolbar to access the information about it, you will notice the following :
This number ‘increments’ every time the page is loaded so it you dont have a static name any longer. This presents something of a problem when it comes to creating a toggle button and changing the styles. So, how can we do something about it?
The first question is….what doesnt change? Well, the tooltip definition doesn’t change for a start. When you create the ISV button in ISV.config, you add your tooltip variable right into the XML, like so.
The Solution
As well as the ToolTip variable, we also know that the menu bar is always designated as mnuBar1. We can iterate through a collection to find our particular button.
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()
{//Toolbar buttons that are to be affected - referenced by the ToolTip value
//assigned in the ISV.config
ShowHideToolbarButton( "ISV Button" );
}function ShowHideToolbarButton( btnTitle )
{//Get all toolbar buttons
var toolBarButtons = document.all.mnuBar1.rows[0].cells[0].childNodes[0].childNodes;
for (var i = 0 ; i < toolBarButtons.length ; i++){var button = toolBarButtons[i];
//Loop through the collection and find the btnTitle we are interested in
if( button.title.match(btnTitle) != null ){//Assign our button to the ButtonID variable
var ButtonID = button.id;
}}}OnCrmPageLoad();
Lovely, we have a basic structure for defining our custom ISV button.
Now, lets have some fun.
I want my button font colour to be RED
Now we have the definition for our ISV button, we can do almost anything else we want with it despite CRM shenanigans with spurious numbers. However, there is one more fundamental problem and that is ‘how’ CRM creates the pages at run time. If you were to use the following code under the ‘var ButtonID….’ line, you would be able to change the text as expected, but your icon would disappear.
document.all[ButtonID].children[0].innerHTML = "Do Something";
Not really very helpful. You can also change the colour quite happily by using the following additional line :
document.all[ButtonID].children[0].style.color = "red";
Lets take a look at the developer toolbar and see what code is actually being generated when a normal ISV button is displayed.
As you can see, there is a SPAN class, then an A class, then the IMG and another SPAN which actually holds the text property which we want to influence.
By looking at the code generated when we use the lines above, we see the following :
Where did our IMG class go? Good question, and the short answer is, I dont know. However, it still leaves us with the problem of how to overcome this little limitation and the answer is to cheat. We know that the text is contained in the SPAN element, but we also want the IMG element to display. Luckily, there is an element called innerHTML which will do very well for our purposes. So, we create a new function called, ModifyButton with some additional parameters.
function ModifyButton (btnName, btnTitle, btnIcon){
try
{//find the button we have specified
var navigationBar = document.getElementById(btnName);
//find the correct element of the menubar/button we have specified
var textArray = navigationBar.getElementsByTagName("SPAN");//read our variables
var buttonIcon = "http://crm:5555/_imgs/" + btnIcon; //change this referencevar buttonText = btnTitle;
for (i = 0; i < textArray.length; i++) {
textArray[i].innerText = buttonText;textArray[i].innerHTML = "<A class=ms-crm-Menu-Label><IMG class=ms-crm-Menu-ButtonFirst src='" + buttonIcon + "'><SPAN class=ms-crm-MenuItem-TextRTL>" + textArray[i].innerText + "</A></></SPAN>";}}catch(ex){
}}
This function can be invoked from within the original ShowHideToolBarButton function like so
function FindToolBarButton( btnTitle )
{//Get all toolbar buttons
var toolBarButtons = document.all.mnuBar1.rows[0].cells[0].childNodes[0].childNodes;
for (var i = 0 ; i < toolBarButtons.length ; i++){var button = toolBarButtons[i];
//Loop through the collection and find the btnTitle we are interested in
if( button.title.match(btnTitle) != null ){//Assign our button to the ButtonID variable
var ButtonID = button.id;
}}//Invoke ModifyButton function....
ModifyButton(ButtonID,"My New Button","ico_16_4200.gif");}
So, what do we get when we put all of this together?
My New Button now has the text that we specified above as well as the IMG tag containing the correct icon, but it still isnt red. Well, that is now fairly easy to handle. Just add the following line just above the ‘innerHTML’ element within the ModifyButton function.
textArray[i].style.color = "red";
In fact, you can now add any DOM style you want to your new button
textArray[i].style.backgroundColor = "Navy";
Practical Applications
Now that we know we can influence the title of the ISV button and it’s style, it’s really a question of how to use this. The original premise that took me off down this path was that I required a toggle button. I wanted to be able to change the caption of an ISV button and it’s function based on the value in another attribute on the form. This lends itself very nicely to setting account flags, changing addresses, updating records etc. Coupled with the power of SQL stored procedures, you could update the database directly although this is highly unsupported.
Recent Comments