In creating records in CRM entities, it’s often useful to unhide hidden tabs/sections/controls based on if you are a certain role, or if certain keys are pressed that a non-developer or system administrator would not be privy to. For instance, you can bind the simultaneous pressing of certain keys, such as SHIFT, ~, and +, to perform a function that may be used only in development or testing of CRM. Note that this requires jQuery and was tested with 1.10 although any version after 1.4 should work.

This guide will involve several steps, which you can omit if unnecessary for your needs.
1. Bind certain simultaneous key press events to a certain function. Use http://www.asquare.net/javascript/tests/KeyCode.html to find the “keycode” for each keyboard button depending on the browser(s) you wish to target.
2. Set the function to unhide all/some controls on a form, or perform other tasks such as showing current user name, etc.
3. Ensure that only certain users are allowed to call this function.

if (!window.console) {//declare variable for console if it does not exist
console = {
log: function () { }
}; 
}
var FEXT = {}; //create global variable for storing data used in this example
var userID = Xrm.Page.context.getUserId().substring(1, 37), //store current user ID
FEXT.currentRoles = [], //used to store current user roles in GetUserRoles functions
DEV_ARRAY = ['C3A808EA-37C9-E211-BB3B-0050568866DA', '86A43F37-AFF3-E211-836F-0050568866DA'], //this should contain an array of any developer's GUIDs that should only be allowed to call the function or certain elements of it.
IS_DEVELOPER = false, //default to false at first, so that the function can set it to true if current user id is in developer array
IS_ADMIN = false; //similar as above
IS_DEVELOPER = (util_arrayContains(userID, DEV_ARRAY)); //use the function, shown below, to check if the DEV_ARRAY contains current userID
IS_ADMIN = function () {
try {
GetUserRoles(); //this sets the user roles in FEXT.currentRoles array as all user roles for current user
return util_arrayContains("System Administrator", FEXT.currentRoles); //this checks the above array for "System Administrator", and returns to IS_ADMIN "true" if is Administrator.
} catch (e) {
custAlert("IS_ADMIN", e); //custom alert function
return false; //if errors out, then set IS_ADMIN to false;
}
}(); // the () part will set ensure this function is ran automatically without being called separately.

if (IS_DEVELOPER || IS_ADMIN) { //if either is true, then run this.
try {
custAlert("Is Admin: " + util_arrayContains("System Administrator", FEXT.currentRoles)); //shows to console if the user is Admin
var keys = {}; //used to store the keys pressed in the below jQuery functions

$(document).keydown(function (e) { //when key is down, this will add it to "keys", and run the devMdChk function mentioned below.
keys[e.keyCode] = true;
devMdChk();
});

$(document).keyup(function (e) { //when key is let go, then this deletes it from "keys" and runs devMdChk.
delete keys[e.keyCode];
devMdChk();
});

function devMdChk() { //this creates a list of all keys in the keys object array, then checks if it equals a certain sequence
var list = '';
for (var i in keys) {
if (!keys.hasOwnProperty(i)) continue;
list = list + i;
}
if (list === "1661192" || list === "16187192") { //this is the list for 16, 187, and 192, which is SHIFT, ~, and +, for IE, respectively.
for (var i in keys) {
delete keys[i]; //if the above IF is matched, then you want to delete all keys in the keys array so that it does not fire again until the next keydown event sequence.
}

if (confirm(
"You have press Shift, ~, and +. Do you wish to enable developer mode? \n\n" +
"This may take a few seconds to load and should only be used for troubleshooting by System Administrators. \n" +
"Saving a form after making modifications during developer mode may result in database corruption. \n\n" +
"DO NOT CLICK OK UNLESS YOU HAVE RECEIVED PRIOR APPROVAL FROM A TECHNICIAN.")) {
try {
FEXT.cons = true; //sets the attribute as true in global variable so it can be "checked" in the future
util_unhideAllControls(); //unhides all controls on form, below
util_DisableAllFormFields(false); //enable all form fields, below
if (Xrm.Page.context.isOutlookOnline()) { //for information purposes, checks if CRM detects Outlook as in online mode.
custAlert("Client online");
}
else custAlert("Client offline");
custAlert("Current server URL is: " + util_getServerUrl());
custAlert("Current user is: " + util_getCurrentUserAJAX());
custAlert("Current owner ID is: " + util_currentOwnerID());
custAlert("Current hub is: " + util_getMyBusinessUnit());
custAlert("Current owner business unit is: " + util_getOwnerBusinessUnit());
} catch (e) {
custAlert("devMdChk", e);
}
}
}
}
}
catch (e) {
custAlert("Cannot check if is developer or admin. ");
}

}
});

function GetUserRoles() {
try {
var roles = Xrm.Page.context.getUserRoles();

for (var i = 0; i < roles.length; i++) {
GetRole(roles[i]);
}
} catch (e) {
console.log("Could not get user roles.");
}

}

function GetUserRoles() {
try {
var roles = Xrm.Page.context.getUserRoles();

for (var i = 0; i < roles.length; i++) {
GetRole(roles[i]);
}
} catch (e) {
custAlert("GetUserRoles", e);
}

}

function GetRole(roleid) {
try {
var serverUrl = Xrm.Page.context.getServerUrl();
var oDataSelect = serverUrl + "/XRMServices/2011/OrganizationData.svc/RoleSet?$select=Name&$filter=RoleId eq guid'" + roleid + "'";

var retrieveReq = new XMLHttpRequest();
retrieveReq.open("GET", oDataSelect, false);
retrieveReq.setRequestHeader("Accept", "application/json");
retrieveReq.setRequestHeader("Content-Type", "application/json;charset=utf-8");
retrieveReq.onreadystatechange = function () {
GetRoleData(this);
};
retrieveReq.send();
} catch (e) {
custAlert("GetRole", e, roleid);
}

}

function GetRoleData(retrieveReq) {
if (retrieveReq.readyState == 4) {
if (retrieveReq.status == 200) {
var retrieved = this.parent.JSON.parse(retrieveReq.responseText).d;
FEXT.currentRoles.push(retrieved.results[0].Name);
}
}
}

function util_arrayContains(value, arrayName) {
///<summary>
///Checks if an arrayName contains a value, and if so, return true; else, false.
///</summary>
try {
if ($.isArray(value) && $.isArray(arrayName)) {
for (var x = 0; x < value.length; x++) {
for (var y = 0; y < arrayName.length; y++) {
if (arrayName[y] === value[x]) {
return true;
}
}
}
return false;
}
else if ($.inArray(value, arrayName) > -1) {
return true;
}
else return false;
} catch (e) {
//console.log("Could not check if array contains value.");
}

}
function custAlert(funcname, errorObj, param) {
///<summary>
/// Function to hide caught alert messages in console:
/// Can replace funcname with a message. errorObj should be an error object.
/// Parameter is any relevant parameter
///</summary>
/// <param name="funcname" type="string">
/// A string representing the function or message. Required.
/// </param>
/// <param name="errorObj" type="object">
/// The error object. Optional. Use null if not passing errorObj but passing param.
/// </param>
/// <param name="param" type="string">
/// The parameter that is causing issues. Optional.
/// </param>
if (typeof IS_DEVELOPER !== "undefined") {
if (IS_DEVELOPER) {
//if (!window.console) console = { log: function () { } }; //declare variable for console if it does not exist
//Only do this if it is console:
if (typeof errorObj === "undefined") {
var message = funcname;
console.log(message);
}
else if (typeof param === "undefined") {
console.log("ERROR - " + funcname + "() caused error : '" + errorObj.message + "'")
}
else {
if (errorObj === null) {
console.log("ERROR - " + funcname + "() caused error :  on '" + param + "'");
}
else {
console.log("ERROR - " + funcname + "() caused error : '" + errorObj.message + "' on '" + param + "'");
}
}
}
}
}
function util_unhideAllControls() {
    /// <summary>
    /// Testing. Unhide all controls in form.
    /// </summary>
    /// <returns type="void" />

    //unhide all sections/tabs
    var tabs = Xrm.Page.ui.tabs;
    for (var i = 0; i < tabs.getLength() ; i++) {

        //Xrm.Page.ui.tabs.get(i).sections.get(j)
        var tab = tabs.get(i);
        custAlert("tab " + tab.getName() + " being unhidden");
        tab.setVisible(true);
        var sections = tab.sections;
        for (var j = 0; j < sections.getLength() ; j++) {
            try {

                var section = sections.get(j);
                custAlert("section " + section.getName() + " being unhidden");
                section.setVisible(true);
            } catch (e) {
                custAlert("Could not unhide all sections/tabs for " + tab.getName() + " " + section.getName());
            }
        }

    }
    //Unhide all controls
    Xrm.Page.ui.controls.forEach(
         function (control) {
             if (control.getControlType() != "subgrid") {
                 custAlert(control.getName() + " being unhidden");
                 try {
                     control.setVisible(true);

                 } catch (e) {
                     custAlert("Could not hide " + control.getName(), e);
                 }
             }
         });

}
function util_doesControlHaveAttribute(control) {
    var controlType = control.getControlType();
    return controlType != "iframe" && controlType != "webresource" && controlType != "subgrid";
}
function util_DisableAllFormFields(trueFalse) {
    ///<summary>
    ///Disable all form fields
    ///</summary>
    Xrm.Page.ui.controls.forEach(function (control, index) {
        if (util_doesControlHaveAttribute(control)) {
            control.setDisabled(trueFalse);
        }
    });
}
function util_getServerUrl() {
    //  Return Current Server URL formatted to remove trailing slash
    var server = Xrm.Page.context.getServerUrl();
    if (server.match(/\/$/)) {
        server = server.substring(0, server.length - 1);
    }
    return server;
}

function util_getCurrentUserAJAX() {
    ///<summary>
    ///Returns the full name of the user running this script
    ///</summary>
    try {
        var serverUrl;
        if (Xrm.Page.context.getClientUrl !== undefined) {
            serverUrl = Xrm.Page.context.getClientUrl();
        } else {
            serverUrl = Xrm.Page.context.getServerUrl();
        }
        var ODataPath = serverUrl + "/XRMServices/2011/OrganizationData.svc";
        var userRequest = new XMLHttpRequest();
        userRequest.open("GET", ODataPath + "/SystemUserSet(guid'" + Xrm.Page.context.getUserId() + "')", false);
        userRequest.setRequestHeader("Accept", "application/json");
        userRequest.setRequestHeader("Content-Type", "application/json; charset=utf-8");
        userRequest.send();
        if (userRequest.status === 200) {
            var retrievedUser = JSON.parse(userRequest.responseText).d;
            var userFullName = retrievedUser.FullName;
            return userFullName;
        }
        else {
            return "error";
        }
    } catch (e) {
        custAlert('util_getcurrentUserAJAX', e)
    }
}
function util_currentUserId() {
    ///<summary>
    ///Get current user ID.
    ///</summary>
    var userID = Xrm.Page.context.getUserId();
    return userID;
}
function util_currentOwnerID() {
    ///<summary>
    ///Find current Owner ID of form.
    ///</summary>
    var ownerID = Xrm.Page.getAttribute("ownerid").getValue()[0].id;
    return ownerID;
}
function util_getMyBusinessUnit() {
    try {
        var xml = "" +
            "<?xml version='1.0' encoding='utf-8'?>" +
            "<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'" +
            " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'" +
            " xmlns:xsd='http://www.w3.org/2001/XMLSchema'>" +
            GenerateAuthenticationHeader() +
            "<soap:Body>" +
            "<Fetch xmlns='http://schemas.microsoft.com/crm/2007/WebServices'>" +
            "<fetchXml>" +
            " &lt;fetch mapping='logical' count='1'&gt;" +
            " &lt;entity name='businessunit'&gt;" +
            " &lt;attribute name='name' /&gt;" +
            " &lt;filter&gt;" +
            " &lt;condition attribute='businessunitid' operator='eq-businessid' /&gt;" +
            " &lt;/filter&gt;" +
            " &lt;/entity&gt;" +
            " &lt;/fetch&gt;" +
            "</fetchXml>" +
            "</Fetch>" +
            "</soap:Body>" +
            "</soap:Envelope>";

        var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
        xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
        xmlHttpRequest.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2007/WebServices/Fetch");
        xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
        xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
        xmlHttpRequest.send(xml);

        var resultXml = xmlHttpRequest.responseXML;

        var resultSet = resultXml.text;
        resultSet.replace('&lt;', '< ');
        resultSet.replace('&gt;', '>');

        var oXmlDoc = new ActiveXObject("Microsoft.XMLDOM");
        oXmlDoc.async = false;
        oXmlDoc.loadXML(resultSet);

        var result = oXmlDoc.getElementsByTagName('name');

        return result[0].text;
    } catch (e) {
        custAlert("util_getMyBusinessUnit", e);
    }

}

function util_getOwnerBusinessUnit() {
    try {
        var ownerid = new Array();
        ownerid = Xrm.Page.getAttribute("ownerid").getValue();
        var ownerHub = null;
        var id, odataSelect, retrieveReq, name;
        var getFieldData = function getFieldData(retrieveReq) {
            if (retrieveReq.readyState == 4) {
                if (retrieveReq.status == 200) {
                    var retrieved = this.parent.JSON.parse(retrieveReq.responseText).d;
                    if (retrieved.results.length > 0) {
                        var retrievedValue = retrieved.results[0].BusinessUnitId;
                        var id = retrievedValue.Id;
                        name = retrievedValue.Name;
                        return name;
                    }

                }
            }
        }
        if (ownerid != null && ownerid.length > 0) {
            id = ownerid[0].id;
            odataSelect = Xrm.Page.context.getServerUrl() + "/XRMServices/2011/OrganizationData.svc/SystemUserSet?$select=BusinessUnitId&$filter=SystemUserId eq guid'" + id + "'";
            retrieveReq = new XMLHttpRequest();
            retrieveReq.open("GET", odataSelect, false);
            retrieveReq.setRequestHeader("Accept", "application/json");
            retrieveReq.setRequestHeader("Content-Type", "application/json; charset=utf-8");
            retrieveReq.onreadystatechange = function () {
                ownerHub = getFieldData(this);

            };
            retrieveReq.send();
        }
        //return ownerHub;
        if (name != null) {
            return name;
        }
    } catch (e) {
        custAlert('util_getOwnerBusinessUnit', e);
    }

}

Creating a custom CRM 2011 button that performs JavaScript functions can be tedious in CRM 2011.  Most guides that I found on the internet for CRM 2011 still included the antiquated crmForm.all method, which is unsupported.

So far the best method I have found of adding a button, or multiple buttons, to a form created in Dynamics CRM UR12 and possibly higher, is by utilizing an HTML Web resource that will store a generic button and the JavaScript required to change the functionality/text/etc. Borrowed and adapted from Ray and Razvan on the CRM Development forums

The code for the HTML Web Resource (let’s just call it WebResource_ButtonHTML):

<HTML xmlns="http://www.w3.org/1999/xhtml"><HEAD><TITLE></TITLE>
<SCRIPT type=text/javascript src="ClientGlobalContext.js.aspx"></SCRIPT>
<SCRIPT type=text/javascript>
    function setText(text) {
        if (text === undefined) {
            text = decodeURI(location.search).replace("?data=", "").replace('%3a', ':').replace('[br]', '<br>');
        }
        var msg = document.getElementById('crmButton');
        msg.value = text;
    }
    //Set the text for the button & attach event
    function initializeButton(text, clickEvent) {
        if (text !== undefined) {
            document.getElementById('crmButton').value = text;
        }
        if (clickEvent !== undefined) {
            try {
                document.getElementById('crmButton').attachEvent("onclick", clickEvent); //Legacy IE code
                    }
    }

    function enable() {
        document.getElementById('crmButton').disabled = false;
    }

    function disable() {
        document.getElementById('crmButton').disabled = true;
    }
</SCRIPT>
<META charset=utf-8></HEAD>
<BODY style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; BACKGROUND-COLOR: rgb(246,248,250); MARGIN: 0px; PADDING-LEFT: 0px; FONT-FAMILY: Segoe UI, Tahoma, Arial; COLOR: #3b3b3b; FONT-SIZE: 11px; BORDER-TOP: 0px; FONT-WEIGHT: normal; BORDER-RIGHT: 0px; PADDING-TOP: 0px" onload=setText(); contentEditable=true>
    <BUTTON style="WIDTH: 100%; HEIGHT: 100%" id="crmButton">CRM Button</BUTTON>
</BODY></HTML>

Go into the development page for your form, and then insert this HTML Web Resource and call it ButtonName.  Note that this HTML web resource has code that is normally not supported by CRM 2011 (using the native DOM), but this is okay since this HTML web resource is being used directly and does not have to go through the XRM.Page model.

Now that we have the button that will be inserted onto the frame, we can add custom code in our form’s Javascript library to be able to access the new_ButtonHTML for each button and modify accordingly:

function GetWebResource(name)
{
    try
    {
        var wrt = Xrm.Page.getControl("WebResource_" + name );//automatically adds WebResource_
        if ( wrt != null )
        {
            if ( wrt.getObject().contentWindow.window != undefined )
            {
                return wrt.getObject().contentWindow.window;
            }
            else
            {
                return null;
            }
        }
        else
            return null;
    }
    catch ( e )
    {
        //debugger;
        alert("Error encountered(GetWebResource): " + e.message);
    }
}
var btnName = GetWebResource("ButtonName"); 
if (typeof btnName.initializeButton !== "undefined") {
btnName.initializeButton("Do Stuff", functionToRun); 
}
function functionToRun() {
btnName.disable();
}

The preceding JavaScript defined a function that will check if the web resource has loaded (GetWebResource(“ButtonName”)) and, if the function initializeButton is not undefined, then it will run it and assign it a text value and an event.

Note that with CRM UR12 to UR14 you may have problems with the load order, where initializeButton will sporadically not be defined. If this is the case, you might want to consider setting a timeout to check that the new_ButtonHTML web resource has loaded in the form. That would probably look like this:

function initBtns()  //creating a function so that it can be easily referenced in a timer
{
var btnName = GetWebResource("ButtonName"); 
if (typeof btnName.initializeButton !== "undefined") {
btnName.initializeButton("Do Stuff", functionToRun); 
} else {
setTimeout(initBtns,100); //sets a timeout to run the initBtns function every 100ms
}
}

With these functions, you should be able to reuse the HTML web resource new_ButtonHTML and simply use custom JavaScript to modify them. Make sure that when you add the buttons that you allow the defaults (aside from formatting) such as allowing cross-side scripting or it may not work properly. The page is essentially an iframe or inline frame, hence the GetWebResource function. You might also be able to use other Javascript functions to access the iframe and run the JavaScript for each instance of your new_ButtonHTML.