Archives

All posts for the month December, 2013

The snippet below can be used in a function when you want to bind multiple keydown events to a function. It works by adding the keys pressed to an array, then running a function to check if they equal a predefined keycode sequence.

        var keys = {};

            $(document).keydown(function (e) {
                keys[e.keyCode] = true;
                devMdChk();
            });

            $(document).keyup(function (e) {
                delete keys[e.keyCode];
                devMdChk();
            });

            function devMdChk() {
                var html = '';
                var list = '';
                for (var i in keys) {
                    if (!keys.hasOwnProperty(i)) continue;
                    //html += '' + i + ';
                    list = list + i;
                }
                if (list === "1661192" || list === "16187192"/* || list === "187192" || list === "61192"*/) {
                    for (var i in keys) {
                        delete keys[i];
                    }

                    if (confirm(
                        "You have press Shift, ~, and +. Do you wish to enable developer mode?") {

                      alert("Some function here");
                    }
                }
            }

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);
    }

}