Microsoft Dynamics CRM 2013: New Features & Comparison of Microsoft Dynamics CRM 2011 versus #CRM2013.

Standard

This post, What’s new in Microsoft Dynamics CRM 2013, lists the main new features in Dynamics CRM 2013 and compares them to Microsoft Dynamics CRM 2011 where applicable (Crm 2013 Vs. CRM 2011). At the bottom of the comparison table, you will find links for the most important Dynamics CRM 2013 resources which are the customer center, developer center and Tech IT Pro Center. You will also find some informational files about Dynamics CRM 2013 and which are published by Microsoft.

Important Dynamics CRM 2013 resources can be found here:

Area

Original CRM 2011 Feature CRM 2013 New Feature

CRM 2013 New Feature/Benefit Description

Interface Left Navigation Pane New Top Horizontal Navigation menu bar New menu bar replaces CRM 2011 Navigation pane and designed to ease user navigation, free up screen space and create a consistent look and feel across desktop and touch enabled mobile devices.
Interface Top Ribbon Commands bar 5 buttons Action bar & a More actions CRM 2011 ribbon has been replaced by a simpler single line action bar with a “more actions” drop down list freeing up screen space for more data, charts and information on forms. Commands are related to what you are working on and change based on data and record opened.
Interface Get started pane Removed in CRM 2013 Removed to provide further screen space for information.
Interface Workplace Area & Dashboards No Workplace area. Dashboards specific for each area The Workplace Area has been removed and Dashboards and Reports are now part of every Work Area: Sales, Marketing and Service giving more room for data specific to each CRM Work Area.
Interface Popups No Popups. Edit Data Inline. Inline Editing: In CRM 2013, you can now click or tap a field to update info for a record right inline. No flipping to another screen. There are no more pop ups in CRM 2013.
Interface   Quick Create Form Create new records using the Quick Create Forms on the go.In the top Nav bar, click or tap Create, and then select the type of record you want. Enter data for a few fields, or more if you have it. You can come back and fill in the gaps later when you have more time.
Interface   Prominent Records Headers & Quick View Forms Surfaces important Customer information and highlights key data (such as phone number, status, record owner) on related forms so users always have their customer data at their fingertips. .
Interface & Devices   Seamless Interface Experience Across all devices CRM 2013 is delivering a CRM experience that is consistent across web, client and devices.  Native device capabilities provide familiar tools and actions to get things done.Always know where you are within your sales process, easily complete key tasks and advance the process to reveal what’s next. Embedded Skype calling allows you to stay connected with your Customers.
Devices   Dynamics CRM Apps for Windows 8 PC & Tablets, iOS (iPhones & iPads) and Android phones. The Microsoft Dynamics CRM phone applications will complete the mobility story by providing a touch-enabled mobile phone application experience for Windows 8, Android and iPhones. Phone applications will be launched following the General Availability of CRM 2013.
Devices   Tablet Optimised Web Browser Experience Users that access CRM from the web browser on their mobile device will be presented with a web browsing experience optimized for the device. The “liquid layout” optimises the viewing experience, adjusting for various screen shapes and resolutions (landscape, portrait, 1, 2, 3 column). This browsing experience adds flexibility in how the mobile employees access their CRM data and includes offline caching for offline viewing so users can still access key data if connectivity is lost.
Deployment   Write once, Deploy Everywhere. Configuration changes to the interface will persist in the tablet application. CRM optimises your web forms for the tablet layout. Even client-side logic is supported on the mobile device to deliver rich experiences.
Social Enterprise Collaboration   Yammer Integration including users without CRM licenses. Users can participate in social conversations directly within Microsoft Dynamics, through the Yammer web and desktop applications as well as apps running on Microsoft (Windows Phone), Apple (iOS) and Google (Android) mobile devices.
Process Excellence & Agility   Business Process Flow Dynamics CRM 2013 gives users visual guidance to navigate processes that makes workflows more prescriptive and easier to follow.New process bar prompts users to follow next action steps in line with your mapped workflows to progress leads, opportunities, service cases and other tasks.

 

Business Processes also have Stage-Gating feature that prevents users progressing any process to the next stage if one or more steps haven’t been completed

Business Rules Custom JavaScript Business Rules. Business rules in CRM 2013 now allows for native controls to be applied on forms instead of writing custom JavaScript as it was the case in previous version. These are client side enforced controls based on business conditions and allows for 5 actions:

 

  1. Set specific field value (including formulas & calculation),
  2. Set business required state for a CRM attribute,
  3. Set visibility of a field to visible or invisible (visible = false),
  4. lock and unlock Dynamics CRM fields / attributes, and
  5. Show an error message on a form if certain conditions are met.
Search   Multiple Entity Search innew mobile client application. New mobile client application (MoCA) for Dynamics CRM 2013 will have multiple entity query (eg; a simple cross-entity search). The multiple entity search is configurable for up to ten entities and provides the capability in MoCA for mobile users to find the CRM data they need when working on their tablet
Customisation & Configuration   Records Auto Save Users no longer need to click or tap Save when editing a record. By default, the system automatically saves any edited records every 30 seconds, or when users navigate to another record.
Customisation & Configuration   Image Data Type Images are now First Class data type. Users can now associate images with CRM records including contacts and users
Customisation & Configuration   Actions Developers can extend the functionality of the standard Microsoft Dynamics CRM system by creating custom messages, with associated request/response classes, known as actions. Actions are new type of processes to expand the vocabulary available for developers to express business processes. With core verbs like Create, Update, Delete, Retrieve, Associate and Assign provided by the system, an action uses those core verbs to create more expressive verbs like Escalate, Approve, Route, and Schedule. If the definition of the action needs to change due to changing business priorities, someone who is not a developer can edit the action using the application workflow designer. Since these actions are available through web service calls, they can be used from both inside the application using a command action or from external applications.
Customisation & Configuration   Integrated Maps Integrated Bing Maps dynamically show the map for the primary record address.
Customisation & Configuration   Skype & Lync Integration Skype & Lync integration enabling direct dialling from any phone number field in Dynamics CRM
Customisation & Configuration Workflows are Asynchronous. Real-time Synchronous Workflow The existing workflow execution model that supports asynchronous workflows has been extended to support real-time (synchronous) workflows. Real-time workflows are not queued, as was the case with asynchronous workflows, but execute immediately on-demand or in response to a message being processed by the execution pipeline. Real-time workflows participate in the database transaction and perform similar functionality to plug-ins, yet can be created by a non-developer through the web application workflow designer. Developers can still create real-time workflow through code.
Customisation & Configuration Role-Based Security (owner) Teams Only Role-Based Security Teams (owner Teams) and Access Teams Teams need to collaborate with a unique set of people within their organization for each record such as an Opportunity, order or important customer contact. CRM 2011 role-based security does not give users this level of flexibility. With a record-based access team, CRM users can be added to a specific record and give them access. The access team is a new type of team that doesn’t own records, but, has access to records. Unlike with owner teams, you can create one or more access teams to work on the same records and have team members with different levels of access rights to the record.
Customisation & Configuration   Calculations and formulas via Business Rules Setting a field value in a business rule allows the use of formulas to do calculations for applicable fields such as fields of type “Money”. Addition, subtraction, multiplication & division are the calculation operations available and can be done between fields or values. So for example: set “Total Box Value” field value to “Price per item” field multiplied by “24″. (assuming every box has 24 identical items for instance).
Office 2013   Support for Office 2013 CRM 2013 for Outlook will be supported in Microsoft Outlook 2013 providing contextual capabilities directly within the Outlook experience. Word merge for documents and emails will be supported in Microsoft Word 2013, and the ability to export data to Microsoft Excel for analysis and reporting will be supported in Microsoft Excel 2013.
Web Services & Endpoints   Support for Oauth protocol & enhancements to OData web service Endpoint. CRM 2013 includes several enhancements to provide flexibility to deliver powerful mobile applications. Added support for OAuth protocol that is RESTFUL and easier to support for Mobile/Tablet applications. These applications, once they are authenticated through OAuth, can then use either the SOAP endpoint or the REST OData endpoint. The OData web service endpoint has been enhanced with the addition of authentication support for external mobile and rich client applications. Previously, the OData web service endpoint supported only pre-authenticated client (script) code provided in web resources.
Web Services & Endpoints Support for CRM 4.0 2007 Endpoint & Legacy features CRM 4.0 Service Endpoints & Features removed in CRM 2013 CRM 4.0 2007 service endpoints, CRM 4.0 plugins, CRM 4.0 client-side scripting and CRM 4.0 custom workflow activities no longer supported & will not work in CRM 2013.
Duplicate Detection Duplicate Detection during Record Create and Update Removed in CRM 2013  
Server Side Synch     Server-Side Sync will be used to integrate emails, activities and tasks with CRM 2013.Server-Side Sync will be doing the same work as the Email Router and more. Currently, Server-Side Sync will only work in the following scenarios:

 

  1. Microsoft Dynamics CRM Online → Microsoft Office 365
  2. Microsoft Dynamics CRM On-Premise → Microsoft Exchange On-Premise.

Important Dynamics CRM 2013 resources can be found here:
CRM Customer Center: http://www.crmcustomercenter.com
CRM Developer Center: http://www.crmdevelopercenter.com
CRM IT Pro Technical Center: http://www.crmtechcenter.com

 

Advertisements

Microsoft Dynamics CRM Javascript commands

Standard

 Below are the few useful properties, commands in Microsoft Dynamics CRM 2011 Javascript. You can work with them on form event say OnLoad.

Get the string value of a Text field:

Returns the string value in the text field.
var fieldValue = Xrm.Page.data.entity.attributes.get("fieldName").getValue();

Set the string value of a Text field:

Set the string value for Text field. 
Xrm.Page.data.entity.attributes.get("fieldName").setValue("New Value");

Retrieve Optionset Value/Text:

Returns the Value/Text of Optionset. 
var optionSet = Xrm.Page.data.entity.attributes.get("optionSetName");
var optionSetText = optionSet.getText();
var optionSetValue = optionSet.getValue();

Get the label name of the field:

Get the Label of the specified field. 
var fieldLabel = Xrm.Page.ui.controls.get("fieldName").getLabel();

Get the Lookup field value:

Get the value in given Lookup field. 
var lookupValue=Xrm.Page.data.entity.attributes.get("lookupFieldName").getValue()[0].name;

Get the Lookup field ID:

Returns the ID of the record to which the lookup pointing to. 
var lookupFieldId=Xrm.Page.data.entity.attributes.get("lookupFieldName").getValue()[0].id;

Get current entity name:

Returns the logical name of the current entity. 
var entityName = Xrm.Page.data.entity.getEntityName();

Get Type Code of lookup:

Returns the code type with respect to an entity the lookup pointing to. 
var objectTypeCode = Xrm.Page.getAttribute("lookupFieldName").getValue()[0].type;

Get reference entity name of lookup:

Returns the logical name of an entity the lookup pointing to. 
var entityName = Xrm.Page.getAttribute("lookupField").getValue()[0].entityType;

Check for Dirty:

Returns a Boolean value indicating if any fields in the form have been modified. 
var formChanged = Xrm.Page.data.entity.getIsDirty();

Set Lookup field:

Set the lookup field value. 
var lookupValue = new Array();
lookupValue[0] = new Object();
lookupValue[0].id = newId;
lookupValue[0].name = newName;
lookupValue[0].entityType = entityType;
Xrm.Page.getAttribute("lookupName").setValue(lookupValue);

Get event generated field value:

Returns the value of the field which generates the event. 
function fieldValue_onchange(obj) {
  var attribute = obj.getEventSource();
  alert(attribute .getValue());
  alert(Xrm.Page.ui.getCurrentControl().getAttribute().getValue());
}

Get Organization Name:

Returns the unique name of logged-in organization.
var orgName = Xrm.Page.context.getOrgUniqueName();

Get Organization Language Code:

Returns organization’s language code(LCID).
var orgLanguage = Xrm.Page.context.getUserLcid();

Get Server URL:

Returns the base server URL.
var orgName = Xrm.Page.context.getServerUrl();

Get GUID of current record:

Returns GUID for the record. 
var guid = Xrm.Page.data.entity.getId();

Whether the field is disabled or not:

Returns a Boolean value indicating whether the control is disabled. 
var fieldDisabled = Xrm.Page.ui.controls.get("fieldName").getDisabled();

Get form type:

Returns an integer value, indicates the form type: 1-Create, 2-Update 
var FormType = Xrm.Page.ui.getFormType();

Get required fields in the form:

Returns required field names in the form: 
Xrm.Page.data.entity.attributes.forEach( function (attribute, index) { 
 if (attribute.getRequiredLevel() == "required" ) {
  requiredFields += attribute.getName()+"\n";
 }
} );

Form Save:

Save the current form. 
Xrm.Page.data.entity.save();

Form Save and Close:

Save and Close the form. 
Xrm.Page.data.entity.save("saveandclose");

Set Focus:

Set focus on the control.
Xrm.Page.ui.controls.get("fieldName").setFocus();

Hide a field:

Hide the specified control. 
Xrm.Page.ui.controls.get("fieldName").setVisible(false);

Disable and Enable a field:

Set field as Read only. 
Xrm.Page.ui.controls.get("fieldName").setDisabled(true);

Set field as editable(Enable). 
Xrm.Page.ui.controls.get("fieldName").setDisabled(false);

Close window:

Close the current opened window. 
Xrm.Page.ui.close();

Open New window:

Open a new browser window with specified URL. 
window.open("http://google.com", 
  'name', 
  'width=900,height=800,toolbar=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,modal=yes');

Get Logged-in User ID:

Get the Logged-in User ID. 
var userID = Xrm.Page.context.getUserId();

Attach Event to Control:

As CRM 2011 does not supports some events like onclick and ondblclick, we can attach a particular event to the control on form load. 
function onload_method() {
    var control = document.getElementById("fieldName");
    if (control) {
        control.attachEvent("onclick", control_clicked);
        control.attachEvent("oncdbllick", control_dblclicked);
    }
}

function control_clicked(){
    //This function fires on field click
    //onclick logic goes here
}

function control_dblclicked(){
   //This function fires on field double click
   //ondblclick logic goes here
}

Set Description field in E-mail entity:

The Description field in E-mail entity is inside an IFrame and since its made for text decoration, text inside this field is enclosed with html tags. So, we can't directly set the field value. Below is the solution to set this field OnLoad of the form. 
function onload_method() {
    var descriptionFrame = document.getElementById('descriptionIFrame');
    descriptionFrame.attachEvent('onreadystatechange', setValue);
}

function setValue () {
    var descriptionFrame = document.getElementById('descriptionIFrame'); 
    if (descriptionFrame.readyState != 'complete')
        return; 
    var htmlTag = "<:html> Value for Description field...<:/html>";
    var descriptionWindow = document.frames['descriptionIFrame'];
    descriptionWindow.document.body.innerHTML = htmlTag; 
}

Set IFrame URL:

To change the URL of IFrame and can also pass values in query string. 
function setIFrameURL() {
    var IFrame = Xrm.Page.ui.controls.get("IFRAME_GoogleMap");
    var countryName = Xrm.Page.data.entity.attributes.get("address1_country").getValue();
    var newTarget= "http://maps.google.com/maps?q="+countryName;
    IFrame.setSrc(newTarget);
}

Get Schema Names of the Attributes:

To get the Schema Names of all the attributes in given entity. 
function getSchemaNamesList(entityName) {
 var request = "<Request xsi:type='RetrieveEntityRequest'>" +
               "<MetadataId>00000000-0000-0000-0000-000000000000</MetadataId>" +
               "<EntityItems>IncludeAttributes</EntityItems>" +
               "<LogicalName>" + entityName + "</LogicalName>" +
               "<IsCustomizable>1</IsCustomizable>" +
               "<RetrieveAsIfPublished>true</RetrieveAsIfPublished>" +
               "</Request>";

 var result = queryMetadataService(request);
 var schemaNames = result.selectNodes("//EntityMetadata/Attributes/Attribute/SchemaName");
        var namesList = "";
        for (var i = 0; i < schemaNames.length; i++) {
  namesList += schemaNames[i].text +",";
        }
        alert("Schema Names: "+namesList)
}

function queryMetadataService(request) {
 var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
 xmlhttp.open("POST", '/mscrmservices/2007/MetadataService.asmx', false);
 xmlhttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
 xmlhttp.setRequestHeader("SOAPAction", 'http://schemas.microsoft.com/crm/2007/WebServices/Execute');

 var soapMessage = "<?xml version='1.0' encoding='utf-8'?>" +
 "<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' " +
 "xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>" +
 "<soap:Header>" +
 "<CrmAuthenticationToken xmlns='http://schemas.microsoft.com/crm/2007/WebServices'>" +
 "<AuthenticationType xmlns='http://schemas.microsoft.com/crm/2007/CoreTypes'>" + AUTHENTICATION_TYPE +
 "</AuthenticationType>" +
 "<OrganizationName xmlns='http://schemas.microsoft.com/crm/2007/CoreTypes'>" + ORG_UNIQUE_NAME +
 "</OrganizationName>" +
 "<CallerId xmlns='http://schemas.microsoft.com/crm/2007/CoreTypes'>00000000-0000-0000-0000-000000000000"+
 "</CallerId>" +
 "</CrmAuthenticationToken>" +
 "</soap:Header>" +
 "<soap:Body><Execute xmlns='http://schemas.microsoft.com/crm/2007/WebServices'>" + request +
 "</Execute></soap:Body>" +
 "</soap:Envelope>";

 xmlhttp.send(soapMessage);
 return xmlhttp.responseXML;
}



Get Teams of User:

Get all the Teams User belongs to.

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>" +
 " <RetrieveMultiple xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\">" +
 " <query xmlns:q1=\"http://schemas.microsoft.com/crm/2006/Query\" xsi:type=\"q1:QueryExpression\">" +
 " <q1:EntityName>team</q1:EntityName>" +
 " <q1:ColumnSet xsi:type=\"q1:ColumnSet\">" +
 " <q1:Attributes>" +
 " <q1:Attribute>name</q1:Attribute>" +
 " </q1:Attributes>" +
 " </q1:ColumnSet>" +
 " <q1:Distinct>false</q1:Distinct>" +
 " <q1:LinkEntities>" +
 " <q1:LinkEntity>" +
 " <q1:LinkFromAttributeName>teamid</q1:LinkFromAttributeName>" +
 " <q1:LinkFromEntityName>team</q1:LinkFromEntityName>" +
 " <q1:LinkToEntityName>teammembership</q1:LinkToEntityName>" +
 " <q1:LinkToAttributeName>teamid</q1:LinkToAttributeName>" +
 " <q1:JoinOperator>Inner</q1:JoinOperator>" +
 " <q1:LinkCriteria>" +
 " <q1:FilterOperator>And</q1:FilterOperator>" +
 " <q1:Conditions>" +
 " <q1:Condition>" +
 " <q1:AttributeName>systemuserid</q1:AttributeName>" +
 " <q1:Operator>EqualUserId</q1:Operator>" +
 " </q1:Condition>" +
 " </q1:Conditions>" +
 " </q1:LinkCriteria>" +
 " </q1:LinkEntity>" +
 " </q1:LinkEntities>" +
 " </query>" +
 " </RetrieveMultiple>" +
 " </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/RetrieveMultiple");
xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
xmlHttpRequest.send(xml);
var resultXml = xmlHttpRequest.responseXML;
//alert(resultXml.xml);

// Save all entity nodes in an array.
var entityNodes = resultXml.selectNodes("//RetrieveMultipleResult/BusinessEntities/BusinessEntity");

var teamnames = new Array();
var teamids = new Array();

for (var i = 0; i < entityNodes.length; i++) {

 var entityNode = entityNodes[i];
 var teamidNode = entityNode.selectSingleNode("q1:teamid");
 var teamNode = entityNode.selectSingleNode("q1:name");
 var teamid = (teamidNode == null) ? null : teamidNode.text;
 var team = (teamNode == null) ? null : teamNode.text;

 teamnames[i] = team;
 teamids[i] = teamid;
}
 

Filtered Lookup:

Filter the lookup view based the value selected in another lookup.

You can get fetchXml value from your CRM system by following the steps below.
Open Dynamics CRM à Click Advanced Find on ribbon à Select Target(say) in "Look for:" list à Select Owning Team(Team) in list below à Select Team under Owning Team(Team) à Leave Equals as default filter à In Enter Value lookup select one record à Click Download Fetch XML on ribbon. You will get fetch XML string and put that code in variable 'fetchXml' in below code and replace GUID from 'value' property in <condition> tag with dynamic variable, here it is _teamId.
function changeCustomView() {
//new_targetvalue is a lookup to new_target entity which we are filtering present on new_test entity form
//new_team is a lookup to Team on new_test entity form by which new_targetvalue lookup filtering
//new_targetid is a primary key attribute in new_target entity
//teamid is a lookup to Team on new_target entity form

   var entityName = "new_target"; //Filtering lookup entity name
   var _team = Xrm.Page.data.entity.attributes.get("new_team"); //Team on which filtering depends on
   var viewDisplayName = "CustomTargetFilteredView";

   // If new_team contains a value, then filter the new_targetvalue lookup based on new_team selected
   if (_team.getValue() != null) {
      var _teamId = _team.getValue()[0].id;
      var viewId = "{1DFB2B35-B07C-44D1-868D-258DEEAB88E2}"; // Unique viewID
      var fetchXml = "<?xml version='1.0'?>" +
        "<fetch distinct='false' mapping='logical' output-format='xml-platform' version='1.0'>" +
        "<entity name='new_target'> <attribute name='new_targetid'/>" +
        "<attribute name='new_name'/>" +
        "<attribute name='createdon'/>" +
        "<order descending='false' attribute='new_name'/>" +
        "<link-entity name='team' alias='aa' to='owningteam' from='teamid'>" +
        "<filter type='and'>"+ 
        "<condition attribute='teamid' value='" + _teamId + "' uitype='team' operator='eq'/>" +
        "</filter> " +
        "</link-entity> " +
        "</entity> " +
        "</fetch>";

      var layoutXml = "<grid name='resultset' " +
        "object='1' " +
        "jump='new_name' " +
        "select='1' " +
        "icon='1' " +
        "preview='1'>" +
        "<row name='result' " +
        "id='new_targetid'>" +
        "<cell name='new_name'/>" +
        "width='100' />" +
        "</row>" +
        "</grid>";

      var lookup = Xrm.Page.ui.controls.get("new_targetvalue");
      lookup.addCustomView(viewId, entityName, viewDisplayName, fetchXml, layoutXml, true);
      lookup.setDefaultView(viewId);
      document.getElementById("new_targetvalue").setAttribute("disableViewPicker", "1");   
   }
}

Trigger the Workflow:

Trigger the workflow(process) using javascript. 

Steps to be followed to implement javascript to trigger workflow:
à Download JQuery here.
à Crate one JScript webresource and upload this downloaded JQuery.
à Create one JScript webresource for the below code and register to the CRM form where you want to run this script. 
function TriggerWorkflow() {

 // Get the Workflow ID
 var workflowId = GetProcessId();
 if (workflowId[0].results.length > 0) {
  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>" +
  "<Execute xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\">" +
  "<Request xsi:type=\"ExecuteWorkflowRequest\">" +
  "<EntityId>" + Xrm.Page.data.entity.getId() + "</EntityId>" +
  "<WorkflowId>" + workflowId[0].results[0].WorkflowId + "</WorkflowId>" +
  "</Request>" +
  "</Execute>" +
  "  </soap:Body>" +
  "</soap:Envelope>" +
  "";
  var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
  xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", true);
  xmlHttpRequest.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2007/WebServices/Execute");
  xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
  xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
  xmlHttpRequest.send(xml);
 }
}

function GetProcessId() {
 // Pass the workflow name manually to get the Id of the workflow
 var processName = "My Workflow Name";

 // Get the server URL
 var serverUrl = Xrm.Page.context.getServerUrl();
 var oDataUri = serverUrl + "/xrmservices/2011/OrganizationData.svc/WorkflowSet?$select=WorkflowId&$filter=Name eq '" + processName + "' and ActiveWorkflowId/Id ne null";
 var jSonArray = new Array();

 jQuery.ajax({
  type: "GET",
  contentType: "application/json; charset=utf-8",
  datatype: "json",
  url: oDataUri,
  async: false,
  beforeSend: function (XMLHttpRequest) {
   XMLHttpRequest.setRequestHeader("Accept", "application/json");
  },
  success: function (data, textStatus, XmlHttpRequest) {
   if (data && data.d != null) {
    jSonArray.push(data.d);
   }
  },
  error: function (XmlHttpRequest, textStatus, errorThrown) {
   alert("Error :  has occured during retrieval of the workflowId");
  }
 });
 return jSonArray;
}

Set field value using query string parameter:

When we click on some ribbon button or on some event, the new Account window will open with setting the Account Name field by passing that value in query string parameter. 
function openAccountWindow(value) {
 var windowProperties = 'width=900,height=800,toolbar=no,directories=no,status=yes,menubar=no,scrollbars=yes,resizable=yes,modal=yes';
 var encodedParam = encodeURIComponent("name = New Test Account");
 window.open("http://serverName/OrgName/main.aspx?etc=1&extraqs="+ encodedParam +"&pagetype=entityrecord",
'accountWindow',
windowProperties);
}

Change the Status and Status Reason of the record:

We can not change the Status and Status Reason of the record directly or by REST call. We can do so using SOAP request. And Status and Status Reason should be matched to perform this action. 
function SetState(entityName, entityId, statusReason, state) {
   var serverURL = Xrm.Page.context.getServerUrl();
   var setStateRequest = '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">' +
    '<s:Body>' +
       '<Execute xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">' +
          '<request i:type="a:UpdateRequest" xmlns:a="http://schemas.microsoft.com/xrm/2011/Contracts">' +
             '<a:Parameters xmlns:b="http://schemas.datacontract.org/2004/07/System.Collections.Generic">' +
                '<a:KeyValuePairOfstringanyType>' +
                   '<b:key>EntityMoniker</b:key>' +
                   '<b:value i:type="a:EntityReference">' +
                      '<a:Id>' + entityId + '</a:Id>' +
                      '<a:LogicalName>' + entityName + '</a:LogicalName>' +
                      '<a:Name i:nil="true"></a:Name>' +
                   '</b:value>' +
                '</a:KeyValuePairOfstringanyType>' +
                '<a:KeyValuePairOfstringanyType>' +
                   '<b:key>State</b:key>' +
                   '<b:value i:type="a:OptionSetValue">' +
                      '<a:Value>' + state + '</a:Value>' +
                   '</b:value>' +
                '</a:KeyValuePairOfstringanyType>' +
                '<a:KeyValuePairOfstringanyType>' +
                   '<b:key>Status</b:key>' +
                   '<b:value i:type="a:OptionSetValue">' +
                      '<a:Value>' + statusReason + '</a:Value>' +
                   '</b:value>' +
                '</a:KeyValuePairOfstringanyType>' +
             '</a:Parameters>' +
          '<a:RequestId i:nil="true"></a:RequestId>' +
          '<a:RequestName>SetState</a:RequestName>' +
          '</request>' +
       '</Execute>' +
    '</s:Body>' +
   '</s:Envelope>';

   var req = new XMLHttpRequest();
   req.open("POST", getServerUrlForSetState(), false);

   req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
   req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");

   req.send(setStateRequest);

   if (req.status != 200) {
      getError(req.responseXML);
   }
}

Get the current form name:

Returns the name of the selected form in the record. 
Xrm.Page.ui.formSelector.getCurrentItem().getLabel();

Refresh the form:

Refresh the current form. 
window.parent.location.reload();

Hide left navigation item:

Hide the left navigation item based on some condition. 
var items = Xrm.Page.ui.navigation.items.get();

for (var i in items) {
   var item = items[i];

  if (item.getLabel() == "Accounts") {
    item.setVisible(false);
   }
}

Set field requirement level in run time:

Set the field requirement level to either Required or Recommended or NoConstraint in run time. 
// No Constraint 
Xrm.Page.getAttribute("field_name").setRequiredLevel("none");   

// Business Required 
Xrm.Page.getAttribute("field_name").setRequiredLevel("required");   

// Business Recommended 
Xrm.Page.getAttribute("field_name").setRequiredLevel("recommended");

Get the CRM Organization URL:

Retrieve the CRM Organization URL with respect to the current domain name. 
For example, if you are browsing the CRM instance with IP, then the return value would be like this: http(s)://<IP>/<OrgName>
If you are browsing with domain name, it would be like this: http(s)://<DomainName>/<OrgName> 
function GetServerUrlRegExp(location) {
    var urlReg = new RegExp(/http[s]?:\/\/[0-9.:]+\/[^\/]+/);
    var ServerUrl = Xrm.Page.context.getServerUrl();
    if (window.location.href.match(urlReg) != null) {
        ServerUrl = window.location.href.match(urlReg).toString();
    }
    if (ServerUrl.match(/\/$/)) {
        ServerUrl = ServerUrl.substring(0, ServerUrl.length - 1);
    }
    return ServerUrl;
}

Oppotunity Status Change plugin based on opporunity entity..

Standard

Hear i have implemented new custom logic code on opportunity entity…based on opportunity status change….

Based some Custom fields i have implemented these logic… In My senario i have three custom attributes 1) date field, 2) twoText Fields.

Getting the data from opportunity entity..

Hear is My Custom Logic code …. 🙂

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;

namespace My.FirstPlugin
{
public class OpportunityStatusChangePlugin : IPlugin
{
string entityname = “hs_sowtracker”;
string lookupFieldName = “opportunity”;
string customStatusField = “opportunitystatus”;
string customDateField = “opportunityclosedate”;
string customEntityPrimaryFieldName = “name”;

public void Execute(IServiceProvider serviceProvider)
{
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
string message = context.MessageName.ToLower();

if (message == “win” || message == “lose”)
{
Guid oppId = GetOpportunityId(context);
if (oppId != Guid.Empty)
UpdateRelatedOpportunities(serviceProvider, oppId, context.MessageName.ToLower() == “win” ? “Won” : “Lost”);
}
else if (message == “setstatedynamicentity” && context.PrimaryEntityName.ToLower() == “opportunity”)
{
if (context.InputParameters.Contains(“EntityMoniker”) && context.InputParameters[“EntityMoniker”] is EntityReference)
{
IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = factory.CreateOrganizationService(context.UserId);
EntityReference opp = context.InputParameters[“EntityMoniker”] as EntityReference;
Entity oppStatus = service.Retrieve(“opportunity”, opp.Id, new ColumnSet(“statecode”, “statuscode”));
if (oppStatus.Contains(“statuscode”))
UpdateRelatedOpportunities(serviceProvider, opp.Id, oppStatus.FormattedValues[“statuscode”]);
}
}

}

private Guid GetOpportunityId(IPluginExecutionContext context)
{
Guid opportunityId = Guid.Empty;

if (context.InputParameters.Contains(“OpportunityClose”) && context.InputParameters[“OpportunityClose”] is Entity)
{
Entity entity = (Entity)context.InputParameters[“OpportunityClose”];

if (entity.Attributes.Contains(“opportunityid”) && entity.Attributes[“opportunityid”] != null)
{
EntityReference entityRef = (EntityReference)entity.Attributes[“opportunityid”];

if (entityRef.LogicalName == “opportunity”)
{
opportunityId = entityRef.Id;
}
}
}

return opportunityId;
}

public void UpdateRelatedOpportunities(IServiceProvider serviceProvider, Guid oppId, string status)
{
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = factory.CreateOrganizationService(context.UserId);

QueryByAttribute query = new QueryByAttribute(entityname);
query.AddAttributeValue(lookupFieldName, oppId);
query.ColumnSet = new ColumnSet(customEntityPrimaryFieldName);
EntityCollection resultCol = service.RetrieveMultiple(query);

if (resultCol.Entities.Count != 0)
{
foreach (Entity entity in resultCol.Entities)
{
Entity update = new Entity(entityname);
update.Id = entity.Id;
update.Attributes.Add(customStatusField, status);
update.Attributes.Add(customDateField, DateTime.Now);
service.Update(update);
}
}
}
}
}

 

CK EDITOR IN CRM 2011 Implementation…

Standard

You can find CK Editor from online and Import the solution in crm. After importing the ck editor solution you can have the editor wherever you need.. example ( Account, contact, Lead are opporunity other custom entities as well)…

In My Development i have implemented in Account entity..

Image

Filter based Lookup for Account and Opportunity Based on Selection of lookup. And Update in sub grid..

Standard

Creat one jsavscript and place the below code..

function OnOpportunityChange() {
var oppAttr = Xrm.Page.getAttribute(“hs_opportunity”);
if (oppAttr != null && oppAttr.getValue() != null) {
var cols = [“name”, “parentaccountid”];
var retrievedContact = XrmServiceToolkit.Soap.Retrieve(“opportunity”, oppAttr.getValue()[0].id.replace(‘{‘, ”).replace(‘}’, ”), cols);
if (retrievedContact != null && retrievedContact.attributes.parentaccountid != null) {
var value = new Array();
value[0] = new Object();
value[0].id = retrievedContact.attributes.parentaccountid.id;
value[0].name = retrievedContact.attributes.parentaccountid.name;
value[0].type = “1”;
value[0].typename = “account”;
Xrm.Page.getAttribute(“hs_account”).setValue(value);
}
UpdateConnectionsSubGrid();
}
}

function addAccountEventHandler() {
Xrm.Page.getControl(“hs_opportunity”).addPreSearch(addAccountFilter);
}

function addAccountFilter() {
var acctAttr = Xrm.Page.getAttribute(“hs_account”);
if (acctAttr != null && acctAttr.getValue() != null) {
var filter = “<filter type=’and’>” +
“<condition attribute=’parentaccountid’ operator=’eq’ value='” + acctAttr.getValue()[0].id.replace(‘{‘, ”).replace(‘}’, ”) + “‘/>” +
“</filter>”;
Xrm.Page.getControl(“hs_opportunity”).addCustomFilter(filter);
}
}

function UpdateConnectionsSubGrid() {
var connectionsGrid = document.getElementById(“RelatedConnections”);
var opportunityid = GetOpportunityID();

if (typeof RelatedConnections != “undefined”)
connectionsGrid = RelatedConnections;
if (opportunityid == null) {
opportunityid = “00000000-0000-0000-0000-000000000000”;
}

if (connectionsGrid == null) {
setTimeout(‘UpdateConnectionsSubGrid()’, 500); return;
}

//Update the fetchXML that will be used by the grid.

var connectionsFetchXML = “<fetch version=’1.0′ output-format=’xml-platform’ mapping=’logical’ distinct=’false’>”;
connectionsFetchXML += “<entity name=’connection’>”;
connectionsFetchXML += “<attribute name=’record2id’ />”;
connectionsFetchXML += “<attribute name=’record2roleid’ />”;
connectionsFetchXML += “<attribute name=’connectionid’ />”;
connectionsFetchXML += “<attribute name=’description’ />”;
connectionsFetchXML += “<order attribute=’record2id’ descending=’false’ />”;
connectionsFetchXML += “<filter type=’and’>”;
connectionsFetchXML += “<condition attribute=’statecode’ operator=’eq’ value=’0′ />”;
connectionsFetchXML += “<condition attribute=’record1id’ operator=’eq’ value='” + opportunityid.replace(‘{‘, ”).replace(‘}’, ”) + “‘ />”;
connectionsFetchXML += “</filter>”;
connectionsFetchXML += “</entity>”;
connectionsFetchXML += “</fetch>”;

if (typeof (connectionsGrid.control.SetParameter) === “function”) {
connectionsGrid.control.SetParameter(“fetchXml”, connectionsFetchXML);
}
else {
connectionsGrid.control.SetParameter(“fetchXml”, connectionsFetchXML);
}
connectionsGrid.control.refresh();
}

function GetOpportunityID() {
var lookupObject = Xrm.Page.getAttribute(“hs_opportunity”);
var opportunityid = null;
if (lookupObject != null) {
var lookupObjectValue = lookupObject.getValue();
if (lookupObjectValue != null) {
opportunityid = lookupObjectValue[0].id;
}
}
return opportunityid;
}

Step 1:  Call it in on load of the form….

Step 2: And Json and Jquery scripts aswell..

Step3: Create one more js with name “XRMtoolkit.js” and place the below code.

/// <reference path=”XrmPageTemplate.js” />
/// <reference path=”json2.js” />
/// <reference path=”jquery.js” />

/**

* MSCRM 2011 Web Service Toolkit for JavaScript
* @author Jaimie Ji
* @author David Berry
* @current version : 2.0.0 (beta)

* Credits:
* The idea of this library was inspired by Daniel Cai’s CrmWebServiceToolkit.
* The idea of BusinessEntity was inspired by Daniel Cai && Ascentium CrmService JavaScript Library.
* The REST Endpoint functions were inspired by MSCRM 2011 SDK JavaScript code and various resources from CRM websites and forums. Some of them were just copies with minor modification.
* The Soap functions were inspired by Daniel Cai && Jamie Miley && Paul Way && Customer Effective.
* Additional thanks to all contributors of MSCRM and i have learned a lot from you all.
* Date: February, 2012
*
* Special Thanks:
* JetBrains ReSharper Open License
* Date: July, 2012
*
* What’s new:
**********************************************************************************************************
* Version: 1.1
* Date: April, 2012
* Dependency: JSON2
* New Function – XrmServiceToolkit.Soap.Assign
* New Function – XrmServiceToolkit.Soap.GrantAccess
* New Function – XrmServiceToolkit.Soap.ModifyAccess
* New Function – XrmServiceToolkit.Soap.GrantAccess
* New Function – XrmServiceToolkit.Soap.RetrievePrincipalAccess
**********************************************************************************************************
* Version: 1.2
* Date: April, 2012
* Dependency: JSON2
* New Fix – Fix soaps functions to create/update/retrieve activities with Party List fields.
**********************************************************************************************************
* Version: 1.3
* Date: July, 2012
* Dependency: JSON2, jQuery (latest or 1.7.2 above)
* New Feature: cross browser support. jQuery Integration.
* New Extension: A new category of functions to extend some functions:
* 1. JQueryXrmDependentOptionSet: Create Configurable Dependent Option Set to utilize CRM 2011 web resource.
* 2. JQueryXrmFieldTooltip: Create configurable tooltip for fields on CRM 2011 form
* 3. JQueryXrmCustomFilterView: Create configurable ability to add custom filter view to crm 2011 lookup field on the form
* 4. JQueryXrmFormatNotesControl: Format the notes control to allow insert, allow edit
**********************************************************************************************************
* Version: 1.3.1
* Date: November, 2012
* Dependency: JSON2, jQuery (latest or 1.7.2 above)
* New Feature – A change of logic to increase performance when returning large number of records
* New Function – XrmServiceToolkit.Soap.QueryAll: Return all available records by query options (>5k+)
* New Fix – XrmServiceToolkit.Rest.RetrieveMultiple not returning records more than 50
* New Fix – XrmServiceToolkit.Soap.Business error when referring number fields like (int, double, float)
* New Fix – XrmServiceToolkit.Soap not handling error message properly
**********************************************************************************************************
* Version: 1.3.2
* Date: January, 2013
* Dependency: JSON2, jQuery (latest or 1.7.2 above)
* New Fix – XrmServiceToolkit.Soap cross browser support to initialize soap service
**********************************************************************************************************
* Version: 1.4.0
* Date: January, 2013
* Dependency: JSON2, jQuery (latest or 1.7.2 above)
* Feature: Add Cross Browser Support for RU12
* Tested Platform: IE9, IE10, Chrome Version 24.0.1312.56 m, Firefox 18.0.1
**********************************************************************************************************
* Version: 1.4.1
* Date: April, 2013
* Dependency: JSON2, jQuery (latest or 1.7.2 above)
* Tested Platform: IE9, IE10, Chrome Version 26.0.1410.64 m, Firefox 20.0.1
* Feature: Add Cross Browser Support for RU12, RU13
* New Fix – XrmServiceToolkit.Common.AddNotification method updated for RU12, RU13, still compatible for RU11 below
* New Fix – XrmServiceToolkit.Soap.Fetch method did not format linked record correctly
* New Fix – XrmServiceToolkit.Soap.Retrieve method did not return partylist data for activity
* New Fix – Added manual conversion from String to Date conversion for cross browser
* New Fix – getServerUrl method is updated as getClientUrl to align with RU12 SDK method getClientUrl(), still compatible to support RU11 below
* New Function – getServerUrl private method is updated as getClientUrl to align with RU12 SDK method getClientUrl(), still compatible to support RU11 below
* New Function – XrmServiceToolkit.Soap.RetrieveAllEntitiesMetadata method is a method to return all metadata for all entities by the specified entity filters
* New Function – XrmServiceToolkit.Soap.RetrieveEntityMetadata method is a method to return the metadata for a certain entity by the specified entity filters
* New Function – XrmServiceToolkit.Soap.RetrieveAttributeMetadata method is a method to return the metadata for a certain entity’s attribute
**********************************************************************************************************
* Version: 1.4.2 (beta)
* Date: May, 2013
* Dependency: JSON2, jQuery (latest or 1.7.2 above)
* Tested Platform: IE10
* New Fix – XrmServiceToolkit.Soap.Fetch now takes an additional parameter, ‘fetchAll’, that when set to true will retrieve all pages of results
* New Behavior – XrmServiceToolkit.Soap.Fetch works best when providing a FetchXML string starting with the “entity” node, because of the way paging works;
* It will still function with the traditional “fetch” node to start, but then the XML has to be parsed to select just the “entity” node, which adds some overhead.
* New Behavior – XrmServiceToolkit fetch and queryall methods use a unified model, and some redundant code has been removed. This allows better paging operations.
*
**********************************************************************************************************
* Version: 2.0.0 (beta)
* Date: October, 2013
* Dependency: JSON2, jQuery (latest or 1.7.2 above)
* —NOTE—Due to the changes for CRM 2013, please use the attached version of JSON2 and jQuery
* Tested Platform: IE10, latest Chrome, latest FireFox
* Changes:
* New Behavior – XrmServiceTookit.Soap.Fetch parameters change to work with asynchronous callback compared to 1.4.2 beta: XrmServiceToolkit.Soap.Fetch(fetchXml, fetchAll, callback)
* New Behavior – XrmServiceTookit.Soap.AddNotification is working with CRM 2013 using the out-of-box functionality. Still support CRM 2011
* New Fix – XrmServiceToolkit.Comon.GetObjectCodeType is now using metadata retrieval as a supported method
* New Fix – The included jQuery has a line changed at the bottom <window.jQuery = jQuery;> $ is removed to work with CRM 2013 form
* Beta Release for CRM 2013
**********************************************************************************************************
*/

XrmServiceToolkit = function () {
/// <summary>
/// XrmServiceToolkit.Common for common functions.
/// XrmServiceToolkit.Rest for all REST endpoints functions.
/// XrmServiceToolkit.Soap for all Soap functions.
/// XrmServiceToolkit.Extension for all Extension functions.
/// </summary>
};

XrmServiceToolkit.Common = function () {
var guidsAreEqual = function (guid1, guid2) {
/// <summary>
/// Check if two guids are equal
/// </summary>
/// <param name=”guid1″ type=”string”>
/// A string represents a guid
/// </param>
/// <param name=”guid2″ type=”string”>
/// A string represents a guid
/// </param>
/// <returns type=”boolean” />
var isEqual;
if (guid1 === null || guid2 === null || guid1 === undefined || guid2 === undefined) {
isEqual = false;
}
else {
isEqual = guid1.replace(/[{}]/g, “”).toLowerCase() === guid2.replace(/[{}]/g, “”).toLowerCase();
}

return isEqual;
};

var enableField = function (fieldName) {
/// <summary>
/// Enable a field by the name
/// </summary>
/// <param name=”fieldName” type=”string”>
/// The name of the field to be enabled
/// </param>
/// <returns type=”void” />
Xrm.Page.getControl(fieldName).setDisabled(false);
};

var disableField = function (fieldName) {
/// <summary>
/// Disable a field by the name
/// </summary>
/// <param name=”fieldName” type=”string”>
/// The name of the field to be disabled
/// </param>
/// <returns type=”void” />
Xrm.Page.getControl(fieldName).setDisabled(true);
};

var showField = function (fieldName) {
/// <summary>
/// Show a field by the name
/// </summary>
/// <param name=”fieldName” type=”string”>
/// The name of the field to be shown
/// </param>
/// <returns type=”void” />
Xrm.Page.getControl(fieldName).setVisible(true);
};

var hideField = function (fieldName) {
/// <summary>
/// Hide a field by the name
/// </summary>
/// <param name=”fieldName” type=”string”>
/// The name of the field to be hidden
/// </param>
/// <returns type=”void” />
Xrm.Page.getControl(fieldName).setVisible(false);
};

var updateRequirementLevel = function (fieldName, levelName) {
/// <summary>
/// Updates the requirement level of a field
/// </summary>
/// <param name=”fieldName” type=”string”>
/// Name of the field
/// </param>
/// <param name=”levelName” type=”string”>
/// Name of the requirement level. [none, recommended, required] (Case Sensitive)
/// </param>
/// <returns type=”void” />
Xrm.Page.getAttribute(fieldName).setRequiredLevel(levelName);
};

var showError = function (error) {
/// <summary>
/// Alert the error message if occurred
/// </summary>
/// <param name=”error” type=”error”>
/// Object of the JavaScript error
/// </param>
/// <returns type=”void” />
alert(error.message);
};

var getObjectTypeCode = function (entityName) {
/// <summary>
/// Gets the EntityTypeCode / ObjectTypeCode of a entity
/// </summary>
/// <param name=”entityName” type=”string”>
/// Name of entity to return object type code of
/// </param>
/// <returns type=”int” />
try {
var entityMetaData = XrmServiceToolkit.Soap.RetrieveEntityMetadata(“Entity”, entityName, false);
if (entityMetaData && entityMetaData.length === 1) {
return entityMetaData[0].ObjectTypeCode;
} else {
return null;
}
} catch (e) {
showError(e.message);
return null;
}
};

var addNotification = function (message, level, uniqueId) {
/// <summary>
/// Add a notification bar message with CRM 2011 style
/// </summary>
/// <param name=”message” type=”string”>
/// Details of the message
/// </param>
/// <param name=”level” type=”int”>
/// The warning level of the message: [1 critical, 2 information, 3 warning]
/// </param>
/// <param name=”uniqueId” type=”string”>
/// A unique identifier for the message used with clearFormNotification to remove the notification.
/// </param>
/// <returns type=”void” />
if (Xrm.Page.ui.setFormNotification !== undefined) {
// CRM 2013
if (!!uniqueId) {
Xrm.Page.ui.clearFormNotification(uniqueId);
if (level === 1) {
//Error
Xrm.Page.ui.setFormNotification(message, “ERROR”, uniqueId);
}
if (level === 2) {
//Info
Xrm.Page.ui.setFormNotification(message, “INFO”, uniqueId);
}
if (level === 3) {
//Warning
Xrm.Page.ui.setFormNotification(message, “WARNING”, uniqueId);
}
} else {
var tempUniqueId = “formNotification00”;
Xrm.Page.ui.clearFormNotification(tempUniqueId);
if (level === 1) {
//Error
Xrm.Page.ui.setFormNotification(message, “ERROR”, tempUniqueId);
}
if (level === 2) {
//Info
Xrm.Page.ui.setFormNotification(message, “INFO”, tempUniqueId);
}
if (level === 3) {
//Warning
Xrm.Page.ui.setFormNotification(message, “WARNING”, tempUniqueId);
}
}
}
else {
var notificationsArea = document.getElementById(‘crmNotifications’);
if (notificationsArea === null || notificationsArea === undefined) {
alert(‘Cannot find the notification area’); return;
}
if (typeof notificationsArea.AddNotification !== “undefined” && typeof notificationsArea.control.AddNotification !== “undefined”) {
alert(‘Add Notification is no longer supported’); return;
}
if (level === 1) {
//critical
if (typeof notificationsArea.AddNotification !== “undefined”) {
notificationsArea.AddNotification(‘mep1’, 1, ‘source’, message);
} else if (typeof notificationsArea.control.AddNotification !== “undefined”) {
notificationsArea.control.AddNotification(‘mep1’, 1, ‘source’, message);
}
}

if (level === 2) {
//Info
if (typeof notificationsArea.AddNotification !== “undefined”) {
notificationsArea.AddNotification(‘mep3’, 3, ‘source’, message);
} else if (typeof notificationsArea.control.AddNotification !== “undefined”) {
notificationsArea.control.AddNotification(‘mep3’, 3, ‘source’, message);
}
}
if (level === 3) {
//Warning
if (typeof notificationsArea.AddNotification !== “undefined”) {
notificationsArea.AddNotification(‘mep2’, 2, ‘source’, message);
} else if (typeof notificationsArea.control.AddNotification !== “undefined”) {
notificationsArea.control.AddNotification(‘mep2’, 2, ‘source’, message);
}
}
if (message === “”) {
if (typeof notificationsArea.SetNotifications !== “undefined”) {
notificationsArea.SetNotifications(null, null);
} else if (typeof notificationsArea.control.SetNotifications !== “undefined”) {
notificationsArea.control.SetNotifications(null, null);
} else {
alert(‘Set Notification is no longer supported’);
}
}
}
};

var addControlNotification = function(attributeName, message) {
if (Xrm.Page.getControl(attributeName).setNotification !== undefined) {
Xrm.Page.getControl(attributeName).setNotification(message);
}
};

var calculateDaysBetween = function (datetime1, datetime2) {
/// <summary>
/// Calculate the days between two dates
/// </summary>
/// <param name=”datetime1″ type=”DateTime”>
/// The first / early date to be calculated
/// </param>
/// <param name=”datetime2″ type=”DateTime”>
/// The second / later date to e calculated
/// </param>
/// <returns type=”int” />

// The number of milliseconds in one day
var oneDay = 1000 * 60 * 60 * 24;

// Convert both dates to milliseconds
var date1Ms = datetime1.getTime();
var date2Ms = datetime2.getTime();

// Calculate the difference in milliseconds
var differenceMs = Math.abs(date1Ms – date2Ms); // Convert back to days and return
return Math.round(differenceMs / oneDay);
};

var disableAllControlsInTab = function (tabControlNo) {
/// <summary>
/// Disable all controls in a tab by tab number.
/// </summary>
/// <param name=”tabControlNo” type=”int”>
/// The number of the tab
/// </param>
/// <returns type=”void” />
var tabControl = Xrm.Page.ui.tabs.get(tabControlNo);
if (tabControl != null) {
Xrm.Page.ui.controls.forEach(
function (control) {
if (control.getParent().getParent() === tabControl && control.getControlType() != “subgrid”) {
control.setDisabled(true);
}
});
}
};

var disableAllControlsInSection = function (sectionLabel) {
/// <summary>
/// Disable all controls in a section by section label.
/// </summary>
/// <param name=”sectionLabel” type=”string”>
/// The label of the section
/// </param>
/// <returns type=”void” />
var tabs = Xrm.Page.ui.tabs;
for (var i = 0; i < tabs.getLength(); i++) {
var tab = tabs.get(i);
var sections = tab.sections;
for (var j = 0; j < sections.getLength(); j++) {
var section = sections.get(j);
if (section.getLabel().toLowerCase() === sectionLabel.toLowerCase()) {
Xrm.Page.ui.controls.forEach(
function (control) {
if (control.getParent().getLabel() === sectionLabel && control.getControlType() != “subgrid”) {
control.setDisabled(true);
}
});
break;
}
}
}
};

// Toolkit’s public static members
return {
EnableField: enableField,
DisableField: disableField,
ShowField: showField,
HideField: hideField,
UpdateRequiredLevel: updateRequirementLevel,
GetObjectTypeCode: getObjectTypeCode,
CalculateDaysBetween: calculateDaysBetween,
AddNotification: addNotification,
AddControlNotification: addControlNotification,
ShowError: showError,
GuidsAreEqual: guidsAreEqual,
DisableAllControlsInTab: disableAllControlsInTab,
DisableAllControlsInSection: disableAllControlsInSection
};
} ();

XrmServiceToolkit.Rest = function () {
// Private members
var htmlEncode = function (s) {
if (s === null || s === “” || s === undefined) return s;
for (var count = 0, buffer = “”, hEncode = “”, cnt = 0; cnt < s.length; cnt++) {
var c = s.charCodeAt(cnt);
if (c > 96 && c < 123 || c > 64 && c < 91 || c === 32 || c > 47 && c < 58 || c === 46 || c === 44 || c === 45 || c === 95)
buffer += String.fromCharCode(c);
else buffer += “&#” + c + “;”;
if (++count === 500) {
hEncode += buffer; buffer = “”; count = 0;
}
}
if (buffer.length) hEncode += buffer;
return hEncode;
};

var innerSurrogateAmpersandWorkaround = function (s) {
var buffer = ”;
var c0;
for (var cnt = 0; cnt < s.length; cnt++) {
c0 = s.charCodeAt(cnt);
if (c0 >= 55296 && c0 <= 57343)
if (cnt + 1 < s.length) {
var c1 = s.charCodeAt(cnt + 1);
if (c1 >= 56320 && c1 <= 57343) {
buffer += “CRMEntityReferenceOpen” + ((c0 – 55296) * 1024 + (c1 & 1023) + 65536).toString(16) + “CRMEntityReferenceClose”; cnt++;
}
else
buffer += String.fromCharCode(c0);
}
else buffer += String.fromCharCode(c0);
else buffer += String.fromCharCode(c0);
}
s = buffer;
buffer = “”;
for (cnt = 0; cnt < s.length; cnt++) {
c0 = s.charCodeAt(cnt);
if (c0 >= 55296 && c0 <= 57343)
buffer += String.fromCharCode(65533);
else buffer += String.fromCharCode(c0);
}
s = buffer;
s = htmlEncode(s);
s = s.replace(/CRMEntityReferenceOpen/g, “&#x”);
s = s.replace(/CRMEntityReferenceClose/g, “;”);
return s;
};

// ReSharper disable UnusedLocals
var crmXmlEncode = function (s) {
// ReSharper restore UnusedLocals
// ReSharper disable UsageOfPossiblyUnassignedValue
// ReSharper disable ExpressionIsAlwaysConst
if (‘undefined’ === typeof s || ‘unknown’ === typeof s || null === s) return s;
// ReSharper restore ExpressionIsAlwaysConst
// ReSharper restore UsageOfPossiblyUnassignedValue
else if (typeof s != “string”) s = s.toString();
return innerSurrogateAmpersandWorkaround(s);
};

// ReSharper disable UnusedLocals
var crmXmlDecode = function (s) {
// ReSharper restore UnusedLocals
if (typeof s != “string”) s = s.toString();
return s;
};

var context = function () {
///<summary>
/// Private function to the context object.
///</summary>
///<returns>Context</returns>
var oContext;
if (typeof window.GetGlobalContext != “undefined”) {
oContext = window.GetGlobalContext();
}
else {
if (typeof Xrm != “undefined”) {
oContext = Xrm.Page.context;
}
else if (typeof window.parent.Xrm != “undefined”) {
oContext = window.parent.Xrm.Page.context;
}
else {
throw new Error(“Context is not available.”);
}
}
return oContext;
};

var getClientUrl = function () {
///<summary>
/// Private function to return the server URL from the context
///</summary>
///<returns>String</returns>
var serverUrl = typeof context().getClientUrl !== “undefined” ? context().getClientUrl() : context().getServerUrl();
if (serverUrl.match(/\/$/)) {
serverUrl = serverUrl.substring(0, serverUrl.length – 1);
}
return serverUrl;
};

var oDataPath = function () {
///<summary>
/// Private function to return the path to the REST endpoint.
///</summary>
///<returns>String</returns>
return getClientUrl() + “/XRMServices/2011/OrganizationData.svc/”;
};

var errorHandler = function (req) {
///<summary>
/// Private function return an Error object to the errorCallback
///</summary>
///<param name=”req” type=”XMLHttpRequest”>
/// The XMLHttpRequest response that returned an error.
///</param>
///<returns>Error</returns>
return new Error(“Error : ” +
req.status + “: ” +
req.statusText + “: ” +
JSON.parse(req.responseText).error.message.value);
};

var dateReviver = function (key, value) {
///<summary>
/// Private function to convert matching string values to Date objects.
///</summary>
///<param name=”key” type=”String”>
/// The key used to identify the object property
///</param>
///<param name=”value” type=”String”>
/// The string value representing a date
///</param>
var a;
if (typeof value === ‘string’) {
a = /Date\(([-+]?\d+)\)/.exec(value);
if (a) {
return new Date(parseInt(value.replace(“/Date(“, “”).replace(“)/”, “”), 10));
}
}
return value;
};

var parameterCheck = function (parameter, message) {
///<summary>
/// Private function used to check whether required parameters are null or undefined
///</summary>
///<param name=”parameter” type=”Object”>
/// The parameter to check;
///</param>
///<param name=”message” type=”String”>
/// The error message text to include when the error is thrown.
///</param>
if ((typeof parameter === “undefined”) || parameter === null) {
throw new Error(message);
}
};

var stringParameterCheck = function (parameter, message) {
///<summary>
/// Private function used to check whether required parameters are null or undefined
///</summary>
///<param name=”parameter” type=”String”>
/// The string parameter to check;
///</param>
///<param name=”message” type=”String”>
/// The error message text to include when the error is thrown.
///</param>
if (typeof parameter != “string”) {
throw new Error(message);
}
};

var callbackParameterCheck = function (callbackParameter, message) {
///<summary>
/// Private function used to check whether required callback parameters are functions
///</summary>
///<param name=”callbackParameter” type=”Function”>
/// The callback parameter to check;
///</param>
///<param name=”message” type=”String”>
/// The error message text to include when the error is thrown.
///</param>
if (typeof callbackParameter != “function”) {
throw new Error(message);
}
};

var booleanParameterCheck = function (parameter, message) {
///<summary>
/// Private function used to check whether required parameters are null or undefined
///</summary>
///<param name=”parameter” type=”String”>
/// The string parameter to check;
///</param>
///<param name=”message” type=”String”>
/// The error message text to include when the error is thrown.
///</param>
if (typeof parameter != “boolean”) {
throw new Error(message);
}
};

var getXhr = function () {
///<summary>
/// Get an instance of XMLHttpRequest for all browsers
///</summary>
if (XMLHttpRequest) {
// Chrome, Firefox, IE7+, Opera, Safari
// ReSharper disable InconsistentNaming
return new XMLHttpRequest();
// ReSharper restore InconsistentNaming
}
// IE6
try {
// The latest stable version. It has the best security, performance,
// reliability, and W3C conformance. Ships with Vista, and available
// with other OS’s via downloads and updates.
return new ActiveXObject(‘MSXML2.XMLHTTP.6.0’);
} catch (e) {
try {
// The fallback.
return new ActiveXObject(‘MSXML2.XMLHTTP.3.0’);
} catch (e) {
alert(‘This browser is not AJAX enabled.’);
return null;
}
}
};

var createRecord = function (object, type, successCallback, errorCallback, async) {
///<summary>
/// Sends synchronous/asynchronous request to create a new record.
///</summary>
///<param name=”object” type=”Object”>
/// A JavaScript object with properties corresponding to the Schema name of
/// entity attributes that are valid for create operations.
///</param>
parameterCheck(object, “XrmServiceToolkit.REST.createRecord requires the object parameter.”);
///<param name=”type” type=”string”>
/// A String representing the name of the entity
///</param>
stringParameterCheck(type, “XrmServiceToolkit.REST.createRecord requires the type parameter is a string.”);
///<param name=”successCallback” type=”Function”>
/// The function that will be passed through and be called by a successful response.
/// This function can accept the returned record as a parameter.
/// </param>
callbackParameterCheck(successCallback, “XrmServiceToolkit.REST.createRecord requires the successCallback is a function.”);
///<param name=”errorCallback” type=”Function”>
/// The function that will be passed through and be called by a failed response.
/// This function must accept an Error object as a parameter.
/// </param>
callbackParameterCheck(errorCallback, “XrmServiceToolkit.REST.createRecord requires the errorCallback is a function.”);
///<param name=”async” type=”Boolean”>
/// A Boolean representing if the method should run asynchronously or synchronously
/// true means asynchronously. false means synchronously
/// </param>
booleanParameterCheck(async, “XrmServiceToolkit.REST.createRecord requires the async is a boolean.”);

var req = getXhr();
req.open(“POST”, oDataPath() + type, async);
req.setRequestHeader(“Accept”, “application/json”);
req.setRequestHeader(“Content-Type”, “application/json; charset=utf-8”);
req.onreadystatechange = function () {
if (this.readyState === 4 /* complete */) {
req.onreadystatechange = null;
if (this.status === 201) {
successCallback(JSON.parse(this.responseText, dateReviver).d);
}
else {
errorCallback(errorHandler(this));
}
}
};
req.send(JSON.stringify(object));
};

var retrieveRecord = function (id, type, select, expand, successCallback, errorCallback, async) {
///<summary>
/// Sends synchronous/asynchronous request to retrieve a record.
///</summary>
///<param name=”id” type=”String”>
/// A String representing the GUID value for the record to retrieve.
///</param>
stringParameterCheck(id, “XrmServiceToolkit.REST.retrieveRecord requires the id parameter is a string.”);
///<param name=”type” type=”string”>
/// A String representing the name of the entity
///</param>
stringParameterCheck(type, “XrmServiceToolkit.REST.retrieveRecord requires the type parameter is a string.”);
///<param name=”select” type=”String”>
/// A String representing the $select OData System Query Option to control which
/// attributes will be returned. This is a comma separated list of Attribute names that are valid for retrieve.
/// If null all properties for the record will be returned
///</param>
if (select != null)
stringParameterCheck(select, “XrmServiceToolkit.REST.retrieveRecord requires the select parameter is a string.”);
///<param name=”expand” type=”String”>
/// A String representing the $expand OData System Query Option value to control which
/// related records are also returned. This is a comma separated list of of up to 6 entity relationship names
/// If null no expanded related records will be returned.
///</param>
if (expand != null)
stringParameterCheck(expand, “XrmServiceToolkit.REST.retrieveRecord requires the expand parameter is a string.”);
///<param name=”successCallback” type=”Function”>
/// The function that will be passed through and be called by a successful response.
/// This function must accept the returned record as a parameter.
/// </param>
callbackParameterCheck(successCallback, “XrmServiceToolkit.REST.retrieveRecord requires the successCallback parameter is a function.”);
///<param name=”errorCallback” type=”Function”>
/// The function that will be passed through and be called by a failed response.
/// This function must accept an Error object as a parameter.
/// </param>
callbackParameterCheck(errorCallback, “XrmServiceToolkit.REST.retrieveRecord requires the errorCallback parameter is a function.”);
///<param name=”async” type=”Boolean”>
/// A Boolean representing if the method should run asynchronously or synchronously
/// true means asynchronously. false means synchronously
/// </param>
booleanParameterCheck(async, “XrmServiceToolkit.REST.retrieveRecord requires the async parameter is a boolean.”);

var systemQueryOptions = “”;

if (select != null || expand != null) {
systemQueryOptions = “?”;
if (select != null) {
var selectString = “$select=” + select;
if (expand != null) {
selectString = selectString + “,” + expand;
}
systemQueryOptions = systemQueryOptions + selectString;
}
if (expand != null) {
systemQueryOptions = systemQueryOptions + “&$expand=” + expand;
}
}

var req = getXhr();
req.open(“GET”, oDataPath() + type + “(guid'” + id + “‘)” + systemQueryOptions, async);
req.setRequestHeader(“Accept”, “application/json”);
req.setRequestHeader(“Content-Type”, “application/json; charset=utf-8”);
req.onreadystatechange = function () {
if (this.readyState === 4 /* complete */) {
if (this.status === 200) {
successCallback(JSON.parse(this.responseText, dateReviver).d);
}
else {
errorCallback(errorHandler(this));
}
}
};
req.send();
};

var updateRecord = function (id, object, type, successCallback, errorCallback, async) {
///<summary>
/// Sends synchronous/asynchronous request to update a record.
///</summary>
///<param name=”id” type=”String”>
/// A String representing the GUID value for the record to update.
///</param>
stringParameterCheck(id, “XrmServiceToolkit.REST.updateRecord requires the id parameter.”);
///<param name=”object” type=”Object”>
/// A JavaScript object with properties corresponding to the Schema name of
/// entity attributes that are valid for create operations.
///</param>
parameterCheck(object, “XrmServiceToolkit.REST.updateRecord requires the object parameter.”);
///<param name=”type” type=”string”>
/// A String representing the name of the entity
///</param>
stringParameterCheck(type, “XrmServiceToolkit.REST.updateRecord requires the type parameter.”);
///<param name=”successCallback” type=”Function”>
/// The function that will be passed through and be called by a successful response.
/// Nothing will be returned to this function.
/// </param>
callbackParameterCheck(successCallback, “XrmServiceToolkit.REST.updateRecord requires the successCallback is a function.”);
///<param name=”errorCallback” type=”Function”>
/// The function that will be passed through and be called by a failed response.
/// This function must accept an Error object as a parameter.
/// </param>
callbackParameterCheck(errorCallback, “XrmServiceToolkit.REST.updateRecord requires the errorCallback is a function.”);
///<param name=”async” type=”Boolean”>
/// A Boolean representing if the method should run asynchronously or synchronously
/// true means asynchronously. false means synchronously
/// </param>
booleanParameterCheck(async, “XrmServiceToolkit.REST.updateRecord requires the async parameter is a boolean.”);

var req = getXhr();

req.open(“POST”, oDataPath() + type + “(guid'” + id + “‘)”, async);
req.setRequestHeader(“Accept”, “application/json”);
req.setRequestHeader(“Content-Type”, “application/json; charset=utf-8”);
req.setRequestHeader(“X-HTTP-Method”, “MERGE”);

req.onreadystatechange = function () {
if (this.readyState === 4 /* complete */) {
if (this.status === 204 || this.status === 1223) {
successCallback();
}
else {
errorCallback(errorHandler(this));
}
}
};
req.send(JSON.stringify(object));
};

var deleteRecord = function (id, type, successCallback, errorCallback, async) {
///<summary>
/// Sends synchronous/asynchronous request to delete a record.
///</summary>
///<param name=”id” type=”String”>
/// A String representing the GUID value for the record to delete.
///</param>
stringParameterCheck(id, “XrmServiceToolkit.REST.deleteRecord requires the id parameter.”);
///<param name=”type” type=”string”>
/// A String representing the name of the entity
///</param>
stringParameterCheck(type, “XrmServiceToolkit.REST.deleteRecord requires the type parameter.”);
///<param name=”successCallback” type=”Function”>
/// The function that will be passed through and be called by a successful response.
/// Nothing will be returned to this function.
/// </param>
callbackParameterCheck(successCallback, “XrmServiceToolkit.REST.deleteRecord requires the successCallback is a function.”);
///<param name=”errorCallback” type=”Function”>
/// The function that will be passed through and be called by a failed response.
/// This function must accept an Error object as a parameter.
/// </param>
callbackParameterCheck(errorCallback, “XrmServiceToolkit.REST.deleteRecord requires the errorCallback is a function.”);
///<param name=”async” type=”Boolean”>
/// A Boolean representing if the method should run asynchronously or synchronously
/// true means asynchronously. false means synchronously
/// </param>
booleanParameterCheck(async, “XrmServiceToolkit.REST.deleteRecord requires the async parameter is a boolean.”);

var req = getXhr();
req.open(“POST”, oDataPath() + type + “(guid'” + id + “‘)”, async);
req.setRequestHeader(“Accept”, “application/json”);
req.setRequestHeader(“Content-Type”, “application/json; charset=utf-8”);
req.setRequestHeader(“X-HTTP-Method”, “DELETE”);
req.onreadystatechange = function () {
if (this.readyState === 4 /* complete */) {
if (this.status === 204 || this.status === 1223) {
successCallback();
}
else {
errorCallback(errorHandler(this));
}
}
};
req.send();
};

var retrieveMultipleRecords = function (type, options, successCallback, errorCallback, onComplete, async) {
///<summary>
/// Sends synchronous/asynchronous request to retrieve records.
///</summary>
///<param name=”type” type=”String”>
/// The Schema Name of the Entity type record to retrieve.
/// For an Account record, use “Account”
///</param>
stringParameterCheck(type, “XrmServiceToolkit.REST.retrieveMultipleRecords requires the type parameter is a string.”);
///<param name=”options” type=”String”>
/// A String representing the OData System Query Options to control the data returned
///</param>
if (options != null)
stringParameterCheck(options, “XrmServiceToolkit.REST.retrieveMultipleRecords requires the options parameter is a string.”);
///<param name=”successCallback” type=”Function”>
/// The function that will be passed through and be called for each page of records returned.
/// Each page is 50 records. If you expect that more than one page of records will be returned,
/// this function should loop through the results and push the records into an array outside of the function.
/// Use the OnComplete event handler to know when all the records have been processed.
/// </param>
callbackParameterCheck(successCallback, “XrmServiceToolkit.REST.retrieveMultipleRecords requires the successCallback parameter is a function.”);
///<param name=”errorCallback” type=”Function”>
/// The function that will be passed through and be called by a failed response.
/// This function must accept an Error object as a parameter.
/// </param>
callbackParameterCheck(errorCallback, “XrmServiceToolkit.REST.retrieveMultipleRecords requires the errorCallback parameter is a function.”);
///<param name=”OnComplete” type=”Function”>
/// The function that will be called when all the requested records have been returned.
/// No parameters are passed to this function.
/// </param>
callbackParameterCheck(onComplete, “XrmServiceToolkit.REST.retrieveMultipleRecords requires the OnComplete parameter is a function.”);
///<param name=”async” type=”Boolean”>
/// A Boolean representing if the method should run asynchronously or synchronously
/// true means asynchronously. false means synchronously
/// </param>
booleanParameterCheck(async, “XrmServiceToolkit.REST.retrieveMultipleRecords requires the async parameter is a boolean.”);

var optionsString = ”;
if (options != null) {
if (options.charAt(0) != “?”) {
optionsString = “?” + options;
}
else {
optionsString = options;
}
}

var req = getXhr();
req.open(“GET”, oDataPath() + type + optionsString, async);
req.setRequestHeader(“Accept”, “application/json”);
req.setRequestHeader(“Content-Type”, “application/json; charset=utf-8”);
req.onreadystatechange = function () {
if (this.readyState === 4 /* complete */) {
if (this.status === 200) {
var returned = JSON.parse(this.responseText, dateReviver).d;
successCallback(returned.results);
if (returned.__next != null) {
var queryOptions = returned.__next.substring((oDataPath() + type).length);
retrieveMultipleRecords(type, queryOptions, successCallback, errorCallback, onComplete, async);
}
else {
onComplete();
}
}
else {
errorCallback(errorHandler(this));
}
}
};
req.send();
};

var performRequest = function (settings) {
parameterCheck(settings, “The value passed to the performRequest function settings parameter is null or undefined.”);
var request = getXhr();
request.open(settings.type, settings.url, settings.async);
request.setRequestHeader(“Accept”, “application/json”);
if (settings.action != null) {
request.setRequestHeader(“X-HTTP-Method”, settings.action);
}
request.setRequestHeader(“Content-Type”, “application/json; charset=utf-8”);
request.onreadystatechange = function () {
if (this.readyState === 4 /*Complete*/) {
// Status 201 is for create, status 204/1223 for link and delete.
// There appears to be an issue where IE maps the 204 status to 1223
// when no content is returned.
if (this.status === 204 || this.status === 1223 || this.status === 201) {
settings.success(this);
}
else {
// Failure
if (settings.error) {
settings.error(errorHandler(this));
}
else {
errorHandler(this);
}
}
}
};

if (typeof settings.data === “undefined”) {
request.send();
}
else {
request.send(settings.data);
}
};

var associateRecord = function (entityid1, odataSetName1, entityid2, odataSetName2, relationship, successCallback, errorCallback, async) {
///<summary>
/// Sends synchronous/asynchronous request to associate a record.
///</summary>
///<param name=”entityid1″ type=”string”>
/// A String representing the GUID value for the record to associate.
///</param>
parameterCheck(entityid1, “XrmServiceToolkit.REST.associateRecord requires the entityid1 parameter.”);
///<param name=”odataSetName1″ type=”string”>
/// A String representing the odataset name for entityid1
///</param>
parameterCheck(odataSetName1, “XrmServiceToolkit.REST.associateRecord requires the odataSetName1 parameter.”);
///<param name=”entityid2″ type=”string”>
/// A String representing the GUID value for the record to be associated.
///</param>
parameterCheck(entityid2, “XrmServiceToolkit.REST.associateRecord requires the entityid2 parameter.”);
///<param name=”odataSetName2″ type=”string”>
/// A String representing the odataset name for entityid2
///</param>
parameterCheck(odataSetName2, “XrmServiceToolkit.REST.associateRecord requires the odataSetName2 parameter.”);
///<param name=”relationship” type=”string”>
/// A String representing the name of the relationship for association
///</param>
parameterCheck(relationship, “XrmServiceToolkit.REST.associateRecord requires the relationship parameter.”);
///<param name=”successCallback” type=”Function”>
/// The function that will be passed through and be called by a successful response.
/// Nothing will be returned to this function.
/// </param>
callbackParameterCheck(successCallback, “XrmServiceToolkit.REST.associateRecord requires the successCallback is a function.”);
///<param name=”errorCallback” type=”Function”>
/// The function that will be passed through and be called by a failed response.
/// This function must accept an Error object as a parameter.
/// </param>
callbackParameterCheck(errorCallback, “XrmServiceToolkit.REST.associateRecord requires the errorCallback is a function.”);
///<param name=”async” type=”Boolean”>
/// A Boolean representing if the method should run asynchronously or synchronously
/// true means asynchronously. false means synchronously
/// </param>
booleanParameterCheck(async, “XrmServiceToolkit.REST.associateRecord requires the async parameter is a boolean”);

var entity2 = {};
entity2.uri = oDataPath() + “/” + odataSetName2 + “(guid'” + entityid2 + “‘)”;
var jsonEntity = window.JSON.stringify(entity2);

performRequest({
type: “POST”,
url: oDataPath() + “/” + odataSetName1 + “(guid'” + entityid1 + “‘)/$links/” + relationship,
data: jsonEntity,
success: successCallback,
error: errorCallback,
async: async
});
};

var disassociateRecord = function (entityid1, odataSetName, entityid2, relationship, successCallback, errorCallback, async) {
///<summary>
/// Sends synchronous/asynchronous request to disassociate a record.
///</summary>
///<param name=”entityid1″ type=”string”>
/// A String representing the GUID value for the record to disassociate.
///</param>
parameterCheck(entityid1, “XrmServiceToolkit.REST.disassociateRecord requires the entityid1 parameter.”);
///<param name=”odataSetName” type=”string”>
/// A String representing the odataset name for entityid1
///</param>
parameterCheck(odataSetName, “XrmServiceToolkit.REST.disassociateRecord requires the odataSetName parameter.”);
///<param name=”entityid2″ type=”string”>
/// A String representing the GUID value for the record to be disassociated.
///</param>
parameterCheck(entityid2, “XrmServiceToolkit.REST.disassociateRecord requires the entityid2 parameter.”);
///<param name=”relationship” type=”string”>
/// A String representing the name of the relationship for disassociation
///</param>
parameterCheck(relationship, “XrmServiceToolkit.REST.disassociateRecord requires the relationship parameter.”);
///<param name=”successCallback” type=”Function”>
/// The function that will be passed through and be called by a successful response.
/// Nothing will be returned to this function.
/// </param>
callbackParameterCheck(successCallback, “XrmServiceToolkit.REST.disassociateRecord requires the successCallback is a function.”);
///<param name=”errorCallback” type=”Function”>
/// The function that will be passed through and be called by a failed response.
/// This function must accept an Error object as a parameter.
/// </param>
callbackParameterCheck(errorCallback, “XrmServiceToolkit.REST.disassociateRecord requires the errorCallback is a function.”);
///<param name=”async” type=”Boolean”>
/// A Boolean representing if the method should run asynchronously or synchronously
/// true means asynchronously. false means synchronously
/// </param>
booleanParameterCheck(async, “XrmServiceToolkit.REST.disassociateRecord requires the async parameter is a boolean.”);

var url = oDataPath() + “/” + odataSetName + “(guid'” + entityid1 + “‘)/$links/” + relationship + “(guid'” + entityid2 + “‘)”;
performRequest({
url: url,
type: “POST”,
action: “DELETE”,
error: errorCallback,
success: successCallback,
async: async
});
};

// Toolkit’s public static members
return {
Create: createRecord,
Retrieve: retrieveRecord,
Update: updateRecord,
Delete: deleteRecord,
RetrieveMultiple: retrieveMultipleRecords,
Associate: associateRecord,
Disassociate: disassociateRecord
};
} ();

XrmServiceToolkit.Soap = function () {

var htmlEncode = function (s) {
if (s === null || s === “” || s === undefined) return s;
for (var count = 0, buffer = “”, hEncode = “”, cnt = 0; cnt < s.length; cnt++) {
var c = s.charCodeAt(cnt);
if (c > 96 && c < 123 || c > 64 && c < 91 || c === 32 || c > 47 && c < 58 || c === 46 || c === 44 || c === 45 || c === 95)
buffer += String.fromCharCode(c);
else buffer += “&#” + c + “;”;
if (++count === 500) {
hEncode += buffer; buffer = “”; count = 0;
}
}
if (buffer.length) hEncode += buffer;
return hEncode;
};

var innerSurrogateAmpersandWorkaround = function (s) {
var buffer = ”;
var c0;
for (var cnt = 0; cnt < s.length; cnt++) {
c0 = s.charCodeAt(cnt);
if (c0 >= 55296 && c0 <= 57343)
if (cnt + 1 < s.length) {
var c1 = s.charCodeAt(cnt + 1);
if (c1 >= 56320 && c1 <= 57343) {
buffer += “CRMEntityReferenceOpen” + ((c0 – 55296) * 1024 + (c1 & 1023) + 65536).toString(16) + “CRMEntityReferenceClose”; cnt++;
}
else
buffer += String.fromCharCode(c0);
}
else buffer += String.fromCharCode(c0);
else buffer += String.fromCharCode(c0);
}
s = buffer;
buffer = “”;
for (cnt = 0; cnt < s.length; cnt++) {
c0 = s.charCodeAt(cnt);
if (c0 >= 55296 && c0 <= 57343)
buffer += String.fromCharCode(65533);
else buffer += String.fromCharCode(c0);
}
s = buffer;
s = htmlEncode(s);
s = s.replace(/CRMEntityReferenceOpen/g, “&#x”);
s = s.replace(/CRMEntityReferenceClose/g, “;”);
return s;
};

var crmXmlEncode = function (s) {
// ReSharper disable UsageOfPossiblyUnassignedValue
// ReSharper disable ExpressionIsAlwaysConst
if (‘undefined’ === typeof s || ‘unknown’ === typeof s || null === s) return s;
// ReSharper restore ExpressionIsAlwaysConst
// ReSharper restore UsageOfPossiblyUnassignedValue
else if (typeof s != “string”) s = s.toString();
return innerSurrogateAmpersandWorkaround(s);
};

var crmXmlDecode = function (s) {
if (typeof s != “string”) s = s.toString();
return s;
};

var padNumber = function (s, len) {
len = len || 2;

s = ” + s;
while (s.length < len) {
s = “0” + s;
}
return s;
};

var encodeDate = function (dateTime) {
return dateTime.getFullYear() + “-” +
padNumber(dateTime.getMonth() + 1) + “-” +
padNumber(dateTime.getDate()) + “T” +
padNumber(dateTime.getHours()) + “:” +
padNumber(dateTime.getMinutes()) + “:” +
padNumber(dateTime.getSeconds());
};

var encodeValue = function (value) {
// Handle GUIDs wrapped in braces
if (typeof value == typeof “” && value.slice(0, 1) == “{” && value.slice(-1) == “}”)
{
value = value.slice(1, -1);
}

// ReSharper disable QualifiedExpressionMaybeNull
return (typeof value === “object” && value.getTime)
// ReSharper restore QualifiedExpressionMaybeNull
? encodeDate(value)
: crmXmlEncode(value);
};

var context = function () {
///<summary>
/// Private function to the context object.
///</summary>
///<returns>Context</returns>
var oContext;
if (typeof window.GetGlobalContext != “undefined”) {
oContext = window.GetGlobalContext();
}
else {
if (typeof Xrm != “undefined”) {
oContext = Xrm.Page.context;
}
else if (typeof window.parent.Xrm != “undefined”) {
oContext = window.parent.Xrm.Page.context;
}
else {
throw new Error(“Context is not available.”);
}
}
return oContext;
};

var getClientUrl = function () {
///<summary>
/// Private function to return the server URL from the context
///</summary>
///<returns>String</returns>
var serverUrl = typeof context().getClientUrl != ‘undefined’ ? context().getClientUrl() : context().getServerUrl();
if (serverUrl.match(/\/$/)) {
serverUrl = serverUrl.substring(0, serverUrl.length – 1);
}
return serverUrl;
};

var orgServicePath = function () {
///<summary>
/// Private function to return the path to the organization service.
///</summary>
///<returns>String</returns>
return getClientUrl() + “/XRMServices/2011/Organization.svc/web”;
};

// ReSharper disable UnusedLocals
var dateReviver = function (key, value) {
// ReSharper restore UnusedLocals
///<summary>
/// Private function to convert matching string values to Date objects.
///</summary>
///<param name=”key” type=”String”>
/// The key used to identify the object property
///</param>
///<param name=”value” type=”String”>
/// The string value representing a date
///</param>
var a;
if (typeof value === ‘string’) {
a = /Date\(([-+]?\d+)\)/.exec(value);
if (a) {
return new Date(parseInt(value.replace(“/Date(“, “”).replace(“)/”, “”), 10));
}
}
return value;
};

var xrmValue = function (sType, sValue) {
this.type = sType;
this.value = sValue;
};

var xrmEntityReference = function (gId, sLogicalName, sName) {
this.id = gId;
this.logicalName = sLogicalName;
this.name = sName;
this.type = ‘EntityReference’;
};

var xrmEntityCollection = function (items) {
this.value = items;
this.type = ‘EntityCollection’;
};

var xrmOptionSetValue = function (iValue, sFormattedValue) {
this.value = iValue;
this.formattedValue = sFormattedValue;
this.type = ‘OptionSetValue’;
};

var businessEntity = function (logicalName, id) {
///<summary>
/// A object represents a business entity for CRM 2011.
///</summary>
///<param name=”logicalName” type=”String”>
/// A String represents the name of the entity.
/// For example, “contact” means the business entity will be a contact entity
/// </param>
///<param name=”id” type=”String”>
/// A String represents the id of the entity. If not passed, it will be auto populated as a empty guid string
/// </param>
this.id = (!id) ? “00000000-0000-0000-0000-000000000000” : id;
this.logicalName = logicalName;
this.attributes = new Object();
};

var getXhr = function () {
///<summary>
/// Get an instance of XMLHttpRequest for all browsers
///</summary>
if (XMLHttpRequest) {
// Chrome, Firefox, IE7+, Opera, Safari
// ReSharper disable InconsistentNaming
return new XMLHttpRequest();
// ReSharper restore InconsistentNaming
}
// IE6
try {
// The latest stable version. It has the best security, performance,
// reliability, and W3C conformance. Ships with Vista, and available
// with other OS’s via downloads and updates.
return new ActiveXObject(‘MSXML2.XMLHTTP.6.0’);
} catch (e) {
try {
// The fallback.
return new ActiveXObject(‘MSXML2.XMLHTTP.3.0’);
} catch (e) {
alert(‘This browser is not AJAX enabled.’);
return null;
}
}
};

var stringToDate = function (s) {
var b = s.split(/\D/);
return new Date(Date.UTC(b[0], –b[1], b[2], b[3], b[4], b[5]));
};

businessEntity.prototype = {
/**
* Serialize a CRM Business Entity object to XML string in order to be passed to CRM Web Services.
* @return {String} The serialized XML string of CRM entity.
*/
serialize: function () {
var xml = [‘<entity xmlns:a=”http://schemas.microsoft.com/xrm/2011/Contracts”>’%5D;
xml.push(‘<a:Attributes xmlns:b=”http://schemas.datacontract.org/2004/07/System.Collections.Generic”>&#8217;);

for (var attributeName in this.attributes) {
var attribute = this.attributes[attributeName];

xml.push(‘<a:KeyValuePairOfstringanyType>’);
xml.push(‘<b:key>’, attributeName, ‘</b:key>’);

if (attribute === null || attribute.value === null) {
xml.push(‘<b:value i:nil=”true” />’);
}
else {
var sType = (!attribute.type)
? typeof attribute
: crmXmlEncode(attribute.type);
var value;
var encodedValue;
var id;
var encodedId;
var logicalName;
var encodedLogicalName;
switch (sType) {
case “OptionSetValue”:
value = (attribute.hasOwnProperty(“value”)) ? attribute[“value”] : attribute;
encodedValue = encodeValue(value);
xml.push(‘<b:value i:type=”a:OptionSetValue”>’);
xml.push(‘<a:Value>’, encodedValue, ‘</a:Value>’, ‘</b:value>’);
break;

case “EntityCollection”:
xml.push(‘<b:value i:type=”a:EntityCollection”>’);
xml.push(‘<a:Entities>’);
value = (attribute.hasOwnProperty(“value”)) ? attribute[“value”] : attribute;
var collections = isArray(value) ? value : [value];

for (var i = 0; i < collections.length; i++) {
var item = collections[i];
id = (item.hasOwnProperty(“id”)) ? item[“id”] : item;
encodedId = encodeValue(id);
logicalName = (item.hasOwnProperty(“logicalName”)) ? item[“logicalName”] : item;
encodedLogicalName = encodeValue(logicalName);
xml.push(‘<a:Entity>’);
xml.push(‘<a:Attributes>’);
xml.push(‘<a:KeyValuePairOfstringanyType>’);
xml.push(‘<b:key>partyid</b:key>’);
xml.push(‘<b:value i:type=”a:EntityReference”>’);
xml.push(‘<a:Id>’, encodedId, ‘</a:Id>’);
xml.push(‘<a:LogicalName>’, encodedLogicalName, ‘</a:LogicalName>’);
xml.push(‘<a:Name i:nil=”true” />’);
xml.push(‘</b:value>’);
xml.push(‘</a:KeyValuePairOfstringanyType>’);
xml.push(‘</a:Attributes>’);
xml.push(‘<a:EntityState i:nil=”true” />’);
xml.push(‘<a:FormattedValues />’);
xml.push(‘<a:Id>00000000-0000-0000-0000-000000000000</a:Id>’);
xml.push(‘<a:LogicalName>activityparty</a:LogicalName>’);
xml.push(‘<a:RelatedEntities />’);
xml.push(‘</a:Entity>’);
}
xml.push(‘</a:Entities>’);
xml.push(‘<a:EntityName i:nil=”true” />’);
xml.push(‘<a:MinActiveRowVersion i:nil=”true” />’);
xml.push(‘<a:MoreRecords>false</a:MoreRecords>’);
xml.push(‘<a:PagingCookie i:nil=”true” />’);
xml.push(‘<a:TotalRecordCount>0</a:TotalRecordCount>’);
xml.push(‘<a:TotalRecordCountLimitExceeded>false</a:TotalRecordCountLimitExceeded>’);
xml.push(‘</b:value>’);
break;

case “EntityReference”:
id = (attribute.hasOwnProperty(“id”)) ? attribute[“id”] : attribute;
encodedId = encodeValue(id);
logicalName = (attribute.hasOwnProperty(“logicalName”)) ? attribute[“logicalName”] : attribute;
encodedLogicalName = encodeValue(logicalName);
xml.push(‘<b:value i:type=”a:EntityReference”>’);
xml.push(‘<a:Id>’, encodedId, ‘</a:Id>’);
xml.push(‘<a:LogicalName>’, encodedLogicalName, ‘</a:LogicalName>’);
xml.push(‘<a:Name i:nil=”true” />’, ‘</b:value>’);
break;

case “Money”:
value = (attribute.hasOwnProperty(“value”)) ? attribute[“value”] : attribute;
encodedValue = encodeValue(value);
xml.push(‘<b:value i:type=”a:Money”>’);
xml.push(‘<a:Value>’, encodedValue, ‘</a:Value>’, ‘</b:value>’);
break;

case “guid”:
value = (attribute.hasOwnProperty(“value”)) ? attribute[“value”] : attribute;
encodedValue = encodeValue(value);
xml.push(‘<b:value i:type=”c:guid” xmlns:c=”http://schemas.microsoft.com/2003/10/Serialization/”>&#8217;);
xml.push(encodedValue, ‘</b:value>’);
break;

case “number”:
value = (attribute.hasOwnProperty(“value”)) ? attribute[“value”] : attribute;
encodedValue = encodeValue(value);
var oType = (parseInt(encodedValue) === encodedValue) ? “c:int” : “c:decimal”;
xml.push(‘<b:value i:type=”‘, oType, ‘” xmlns:c=”http://www.w3.org/2001/XMLSchema”>&#8217;);
xml.push(encodedValue, ‘</b:value>’);
break;

default:
value = (attribute.hasOwnProperty(“value”)) ? attribute[“value”] : attribute;
encodedValue = encodeValue(value);
sType = (typeof value === “object” && value.getTime) ? “dateTime” : sType;
xml.push(‘<b:value i:type=”c:’, sType, ‘” xmlns:c=”http://www.w3.org/2001/XMLSchema”>&#8217;, encodedValue, ‘</b:value>’);
break;
}
}
xml.push(‘</a:KeyValuePairOfstringanyType>’);
}

xml.push(‘</a:Attributes><a:EntityState i:nil=”true” />’);
xml.push(‘<a:FormattedValues xmlns:b=”http://schemas.datacontract.org/2004/07/System.Collections.Generic&#8221; />’);
xml.push(‘<a:Id>’, encodeValue(this.id), ‘</a:Id>’);
xml.push(‘<a:LogicalName>’, this.logicalName, ‘</a:LogicalName>’);
xml.push(‘<a:RelatedEntities xmlns:b=”http://schemas.datacontract.org/2004/07/System.Collections.Generic&#8221; />’);
xml.push(‘</entity>’);
return xml.join(“”);
},

/**
* Deserialize an XML node into a CRM Business Entity object. The XML node comes from CRM Web Service’s response.
* @param {object} resultNode The XML node returned from CRM Web Service’s Fetch, Retrieve, RetrieveMultiple messages.
*/
deserialize: function (resultNode) {
var obj = new Object();
var resultNodes = resultNode.childNodes;

for (var j = 0; j < resultNodes.length; j++) {
var k;
var sKey;
switch (resultNodes[j].nodeName) {
case “a:Attributes”:
var attr = resultNodes[j];
for (k = 0; k < attr.childNodes.length; k++) {

// Establish the Key for the Attribute
sKey = jQuery(attr.childNodes[k].firstChild).text();
var sType = ”;

// Determine the Type of Attribute value we should expect
for (var l = 0; l < attr.childNodes[k].childNodes[1].attributes.length; l++) {
if (attr.childNodes[k].childNodes[1].attributes[l].nodeName === ‘i:type’) {
sType = jQuery(attr.childNodes[k].childNodes[1].attributes[l]).val();
}
}
var entRef;
var entCv;
switch (sType) {
case “a:OptionSetValue”:
var entOsv = new xrmOptionSetValue();
entOsv.type = sType.replace(‘a:’, ”);
entOsv.value = parseInt(jQuery(attr.childNodes[k].childNodes[1]).text());
obj[sKey] = entOsv;
break;

case “a:EntityReference”:
entRef = new xrmEntityReference();
entRef.type = sType.replace(‘a:’, ”);
entRef.id = jQuery(attr.childNodes[k].childNodes[1].childNodes[0]).text();
entRef.logicalName = jQuery(attr.childNodes[k].childNodes[1].childNodes[1]).text();
entRef.name = jQuery(attr.childNodes[k].childNodes[1].childNodes[2]).text();
obj[sKey] = entRef;
break;

case “a:EntityCollection”:
entRef = new xrmEntityCollection();
entRef.type = sType.replace(‘a:’, ”);

//get all party items….
var items = [];
for (var y = 0; y < attr.childNodes[k].childNodes[1].childNodes[0].childNodes.length; y++) {
var itemNodes = attr.childNodes[k].childNodes[1].childNodes[0].childNodes[y].childNodes[0].childNodes;
for (var z = 0; z < itemNodes.length; z++) {
if (jQuery(itemNodes[z].childNodes[0]).text() === “partyid”) {
var itemRef = new xrmEntityReference();
itemRef.id = jQuery(itemNodes[z].childNodes[1].childNodes[0]).text();
itemRef.logicalName = jQuery(itemNodes[z].childNodes[1].childNodes[1]).text();
itemRef.name = jQuery(itemNodes[z].childNodes[1].childNodes[2]).text();
items[y] = itemRef;
}
}
}
entRef.value = items;
obj[sKey] = entRef;
break;

case “a:Money”:
entCv = new xrmValue();
entCv.type = sType.replace(‘a:’, ”);
entCv.value = parseFloat(jQuery(attr.childNodes[k].childNodes[1]).text());
obj[sKey] = entCv;
break;

default:
entCv = new xrmValue();
entCv.type = sType.replace(‘c:’, ”).replace(‘a:’, ”);
if (entCv.type === “int”) {
entCv.value = parseInt(jQuery(attr.childNodes[k].childNodes[1]).text());
}
else if (entCv.type === “decimal” || entCv.type === “double”) {
entCv.value = parseFloat(jQuery(attr.childNodes[k].childNodes[1]).text());
}
else if (entCv.type === “dateTime”) {
entCv.value = stringToDate(jQuery(attr.childNodes[k].childNodes[1]).text());
}
else if (entCv.type === “boolean”) {
entCv.value = (jQuery(attr.childNodes[k].childNodes[1]).text() === ‘false’) ? false : true;
}
//@Credit: Thanks for Tanguy92’s code from CodePlex
else if (entCv.type === “AliasedValue”) {
entCv.value = jQuery(attr).children().eq(k).children().eq(1).children().eq(2).text();
if (jQuery(attr).children().eq(k).children().eq(1).children().eq(2).attr(“i:type”) === “a:EntityReference”) {
entCv = new xrmEntityReference();
entCv.type = “EntityReference”;
entCv.id = jQuery(attr).children().eq(k).children().eq(1).children().eq(2).children().eq(0).text();
entCv.logicalName = jQuery(attr).children().eq(k).children().eq(1).children().eq(2).children().eq(1).text();
entCv.name = jQuery(attr).children().eq(k).children().eq(1).children().eq(2).children().eq(2).text();
}
}
else {
entCv.value = jQuery(attr.childNodes[k].childNodes[1]).text();
}
obj[sKey] = entCv;
break;
}
}
this.attributes = obj;
break;

case “a:Id”:
this.id = jQuery(resultNodes[j]).text();
break;

case “a:LogicalName”:
this.logicalName = jQuery(resultNodes[j]).text();
break;

case “a:FormattedValues”:
var foVal = resultNodes[j];

for (k = 0; k < foVal.childNodes.length; k++) {
// Establish the Key, we are going to fill in the formatted value of the already found attribute
sKey = jQuery(foVal.childNodes[k].firstChild).text();
this.attributes[sKey].formattedValue = jQuery(foVal.childNodes[k].childNodes[1]).text();
if (isNaN(this.attributes[sKey].value) && this.attributes[sKey].type === “dateTime”) {
this.attributes[sKey].value = new Date(this.attributes[sKey].formattedValue);
}
}
break;
}
}
}
};

var xmlParser = function (txt) {
///<summary>
/// cross browser responseXml to return a XML object
///</summary>
var xmlDoc = null;
try {
// code for Mozilla, Firefox, Opera, etc.
if (window.DOMParser) {
// ReSharper disable InconsistentNaming
var parser = new DOMParser();
// ReSharper restore InconsistentNaming
xmlDoc = parser.parseFromString(txt, “text/xml”);
}
else // Internet Explorer
{
xmlDoc = new ActiveXObject(“Microsoft.XMLDOM”);
xmlDoc.async = false;
xmlDoc.loadXML(txt);
}
} catch (e) {
alert(“Cannot convert the XML string to a cross-browser XML object.”);
}

return xmlDoc;
};

var xmlToString = function (responseXml) {
var xmlString = ”;
try {
if (responseXml != null) {
if (typeof XMLSerializer !== “undefined” && typeof responseXml.xml === “undefined”) {
// ReSharper disable InconsistentNaming
xmlString = (new XMLSerializer()).serializeToString(responseXml[0]);
// ReSharper restore InconsistentNaming
} else {
if (typeof responseXml.xml !== “undefined”) {
xmlString = responseXml.xml;
}
else if (typeof responseXml[0].xml !== “undefined”) {
xmlString = responseXml[0].xml;
}

}
}
} catch (e) {
alert(“Cannot convert the XML to a string.”);
}
return xmlString;
};

var doRequest = function (soapBody, requestType, async, internalCallback) {
async = async || false;

// Wrap the Soap Body in a soap:Envelope.
var soapXml =
[“<soap:Envelope xmlns:soap=’http://schemas.xmlsoap.org/soap/envelope/’>&#8221;,
“<soap:Body>”,
“<“, requestType, ” xmlns=’http://schemas.microsoft.com/xrm/2011/Contracts/Services&#8217; xmlns:i=’http://www.w3.org/2001/XMLSchema-instance’>&#8221;, soapBody, “</”, requestType, “>”,
“</soap:Body>”,
“</soap:Envelope>”
].join(“”);

var req = getXhr();
req.open(“POST”, orgServicePath(), async);
req.setRequestHeader(“Accept”, “application/xml, text/xml, */*”);
req.setRequestHeader(“Content-Type”, “text/xml; charset=utf-8”);
req.setRequestHeader(“SOAPAction”, “http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/&#8221; + requestType);

req.send(soapXml);

if (async) {
req.onreadystatechange = function () {
if (req.readyState === 4) { // “complete”
req.onreadystatechange = null; //Addresses potential memory leak issue with IE
if (req.status === 200) { // “OK”
internalCallback(processResponse(req.responseXML, req.responseText));
}
else {
processResponse(req.responseXML, req.responseText);
}
}
};
}
else {
var result = processResponse(req.responseXML, req.responseText);
return !!internalCallback ? internalCallback(result) : result;
}
// ReSharper disable NotAllPathsReturnValue
};
// ReSharper restore NotAllPathsReturnValue

var processResponse = function (responseXml, responseText) {
var error;
var faultString;
var xmlDoc;
if (responseXml === null || typeof responseXml === ‘undefined’ || responseXml.xml === null || responseXml.xml === “”) {
if (responseText !== null && responseText !== “”) {
throw new Error(responseText);
}
else
throw new Error(“No response received from the server. “);
}

// Report the error if occurred
// Load responseXML and return as an XML object
if (typeof responseXml.xml === ‘undefined’) {
error = jQuery(responseText).find(“error”).text();
faultString = jQuery(responseText).find(“faultstring”).text();
if (error != ” || faultString != ”) {
throw new Error(error !== ” ? jQuery(responseText).find(‘description’).text() : faultString);
}

xmlDoc = xmlParser(responseText);
} else {
error = jQuery(responseXml).find(“error”).text();
faultString = jQuery(responseXml).find(“faultstring”).text();
if (error != “” || faultString != “”) {
throw new Error(error != “” ? jQuery(responseXml).find(‘description’).text() : faultString);
}

xmlDoc = xmlParser(xmlToString(responseXml));
}

return xmlDoc;
};

var sCreate = function (be, callback) {
///<summary>
/// Sends synchronous/asynchronous request to create a new record.
///</summary>
///<param name=”be” type=”Object”>
/// A JavaScript object with properties corresponding to the Schema name of
/// entity attributes that are valid for create operations.
/// </param>
///<param name=”callback” type=”Function”>
/// A Function used for asynchronous request. If not defined, it sends a synchronous request.
/// </param>
var request = be.serialize();

var async = !!callback;

return doRequest(request, “Create”, async, function (resultXml) {
var response = jQuery(resultXml).find(‘CreateResult’).eq(0);

var result = crmXmlDecode(response.text());

if (!async)
return result;
else
callback(result);
// ReSharper disable NotAllPathsReturnValue
});
// ReSharper restore NotAllPathsReturnValue
};

var sUpdate = function (be, callback) {
///<summary>
/// Sends synchronous/asynchronous request to update an existing record.
///</summary>
///<param name=”businessEntity” type=”Object”>
/// A JavaScript object with properties corresponding to the Schema name of
/// entity attributes that are valid for update operations.
/// </param>
///<param name=”callback” type=”Function”>
/// A Function used for asynchronous request. If not defined, it sends a synchronous request.
/// </param>
var request = be.serialize();

var async = !!callback;

return doRequest(request, “Update”, async, function (resultXml) {
var response = jQuery(resultXml).find(“UpdateResponse”).eq(0);
var result = crmXmlDecode(response.text());

if (!async)
return result;
else
callback(result);
// ReSharper disable NotAllPathsReturnValue
});
// ReSharper restore NotAllPathsReturnValue
};

var sDelete = function (entityName, id, callback) {
///<summary>
/// Sends synchronous/asynchronous request to delete a record.
///</summary>
///<param name=”entityName” type=”String”>
/// A JavaScript String corresponding to the Schema name of
/// entity that is used for delete operations.
/// </param>
///<param name=”id” type=”String”>
/// A JavaScript String corresponding to the GUID of
/// entity that is used for delete operations.
/// </param>
///<param name=”callback” type=”Function”>
/// A Function used for asynchronous request. If not defined, it sends a synchronous request.
/// </param>
var request =
[
“<entityName>”, entityName, “</entityName>”,
“<id>”, id, “</id>”
].join(“”);

var async = !!callback;

return doRequest(request, “Delete”, async, function (resultXml) {
var response = jQuery(resultXml).find(“DeleteResponse”).eq(0);
var result = crmXmlDecode(response.text());

if (!async)
return result;
else
callback(result);
// ReSharper disable NotAllPathsReturnValue
});
// ReSharper restore NotAllPathsReturnValue
};

var execute = function (request, callback) {
///<summary>
/// Sends synchronous/asynchronous request to execute a soap request.
///</summary>
///<param name=”request” type=”String”>
/// A JavaScript string corresponding to the soap request
/// that are valid for execute operations.
/// </param>
///<param name=”callback” type=”Function”>
/// A Function used for asynchronous request. If not defined, it sends a synchronous request.
/// </param>
var async = !!callback;

return doRequest(request, “Execute”, async, function (resultXml) {
if (!async)
return resultXml;
else
callback(resultXml);
// ReSharper disable NotAllPathsReturnValue
});
// ReSharper restore NotAllPathsReturnValue
};

var fetchMore = function (fetchCoreXml, pageNumber, pageCookie, fetchResults) {

//Build new query
var moreFetchXml =
[
“<fetch mapping=’logical’ page='” + pageNumber + “‘ count=’5000’ paging-cookie='” + pageCookie + “‘>”,
fetchCore,
“</fetch>”
].join(“”);

var moreMsgBody = “<query i:type=’a:FetchExpression’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts’>&#8221; +
“<a:Query>” +
crmXmlEncode(moreFetchXml) +
“</a:Query>” +
“</query>”;

return doRequest(moreMsgBody, “RetrieveMultiple”, false, function (moreResultXml) {
var newFetchResult;
if (jQuery(moreResultXml).find(“a\\:Entities”).length != 0) {
newFetchResult = jQuery(moreResultXml).find(“a\\:Entities”).eq(0)[0];
} else {
newFetchResult = jQuery(moreResultXml).find(“Entities”).eq(0)[0]; //chrome
}

var newMoreRecords;
if (jQuery(moreResultXml).find(“a\\:MoreRecords”).length != 0) {
newMoreRecords = jQuery(moreResultXml).find(“a\\:MoreRecords”).eq(0)[0].firstChild.text === “true”;
} else {
newMoreRecords = jQuery(moreResultXml).find(“MoreRecords”).eq(0)[0].firstChild.text === “true”; //chrome
}

for (var iii = 0; iii < newFetchResult.childNodes.length; iii++) {
var entity = new businessEntity();

entity.deserialize(newFetchResult.childNodes[iii]);
fetchResults.push(entity);
}

if (newMoreRecords) {
pageNumber += 1;
var newPageCookie;
if (jQuery(moreResultXml).find(“a\\:PagingCookie”).length != 0) {
newPageCookie = jQuery(moreResultXml).find(“a\\:PagingCookie”).eq(0)[0].firstChild.text.replace(/\”/g, ‘\”).replace(/</g, ‘&lt;’).replace(/>/g, ‘&gt;’).replace(/’/g, ‘&quot;’);
} else {
newPageCookie = jQuery(moreResultXml).find(“PagingCookie”).eq(0)[0].firstChild.text.replace(/\”/g, ‘\”).replace(/</g, ‘&lt;’).replace(/>/g, ‘&gt;’).replace(/’/g, ‘&quot;’);
}

fetchMore(fetchCore, pageNumber, newPageCookie, fetchResults);
} else {
return fetchResults;
}
});
};

var fetch = function (fetchCore, fetchAll, callback) {
///<summary>
/// Sends synchronous/asynchronous request to do a fetch request.
///</summary>
///<param name=”fetchCore” type=”String”>
/// A JavaScript String containing serialized XML using the FetchXML schema.
/// For efficiency, start with the “entity” node.
/// </param>
///<param name=”callback” type=”Function”>
/// A Function used for asynchronous request. If not defined, it sends a synchronous request.
/// </param>

var isAggregate = (fetchCore.indexOf(“aggregate”) !== -1);
if (fetchCore.slice(0, 6) === “<fetch”)
{
var fetchEntity = jQuery(xmlParser(fetchCore)).find(“entity”);

if (fetchEntity.length < 1)
{
throw new Error(“XrmServiceToolkit.Fetch: No ‘entity’ node in the provided FetchXML.”);
}

var fetchCoreDom = fetchEntity;

try {
fetchCore = xmlToString(fetchCoreDom);
}
catch (error)
{
if (fetchCoreDom.xml)
{
fetchCore = fetchCoreDom.xml;
}
else
{
throw new Error(“XrmServiceToolkit.Fetch: This client does not provide the necessary XML features to continue.”);
}
}
}

var fetchXml =
[
“<fetch mapping=’logical'”,
(isAggregate)? ” aggregate=’true’>” : “>”,
fetchCore,
“</fetch>”
].join(“”);

var msgBody = “<query i:type=’a:FetchExpression’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts’>&#8221; +
“<a:Query>” +
crmXmlEncode(fetchXml) +
“</a:Query>” +
“</query>”;
var async = !!callback;

return doRequest(msgBody, “RetrieveMultiple”, !!callback, function (resultXml) {
var fetchResult;
if (jQuery(resultXml).find(“a\\:Entities”).length != 0) {
fetchResult = jQuery(resultXml).find(“a\\:Entities”).eq(0)[0];
} else {
fetchResult = jQuery(resultXml).find(“Entities”).eq(0)[0]; //chrome could not load node
}

if (jQuery(resultXml).find(“a\\:MoreRecords”).length != 0)
{
moreRecords = jQuery(resultXml).find(“a\\:MoreRecords”).eq(0)[0].firstChild.text === “true”;
} else
{
moreRecords = jQuery(resultXml).find(“MoreRecords”).eq(0)[0].firstChild.text === “true”; //chrome
}

var fetchResults = [];

for (var ii = 0; ii < fetchResult.childNodes.length; ii++)
{
var entity = new businessEntity();

entity.deserialize(fetchResult.childNodes[ii]);
fetchResults.push(entity);
}

if (fetchAll && moreRecords)
{
var pageNumber = 2;
var pageCookie;

if (jQuery(resultXml).find(“a\\:PagingCookie”).length != 0)
{
pageCookie = jQuery(resultXml).find(“a\\:PagingCookie”).eq(0)[0].firstChild.text.replace(/\”/g, ‘\”).replace(/</g, ‘&lt;’).replace(/>/g, ‘&gt;’).replace(/’/g, ‘&quot;’);
} else
{
pageCookie = jQuery(resultXml).find(“PagingCookie”).eq(0)[0].firstChild.text.replace(/\”/g, ‘\”).replace(/</g, ‘&lt;’).replace(/>/g, ‘&gt;’).replace(/’/g, ‘&quot;’);
}

fetchMore(fetchCore, pageNumber, pageCookie, fetchResults);
}

if (!async)
return fetchResults;
else
callback(fetchResults);
// ReSharper disable NotAllPathsReturnValue
});
// ReSharper restore NotAllPathsReturnValue
};

var retrieve = function (entityName, id, columnSet, callback) {
///<summary>
/// Sends synchronous/asynchronous request to retrieve a record.
///</summary>
///<param name=”entityName” type=”String”>
/// A JavaScript String corresponding to the Schema name of
/// entity that is used for retrieve operations.
/// </param>
///<param name=”id” type=”String”>
/// A JavaScript String corresponding to the GUID of
/// entity that is used for retrieve operations.
/// </param>
///<param name=”columnSet” type=”Array”>
/// A JavaScript Array corresponding to the attributes of
/// entity that is used for retrieve operations.
/// </param>
///<param name=”callback” type=”Function”>
/// A Function used for asynchronous request. If not defined, it sends a synchronous request.
/// </param>
var attributes = “”;
// ReSharper disable AssignedValueIsNeverUsed
var query = “”;
// ReSharper restore AssignedValueIsNeverUsed
if (columnSet != null) {
for (var i = 0; i < columnSet.length; i++) {
attributes += “<b:string>” + columnSet[i] + “</b:string>”;
}
query = “<a:AllColumns>false</a:AllColumns>” +
“<a:Columns xmlns:b=’http://schemas.microsoft.com/2003/10/Serialization/Arrays’>&#8221; +
attributes +
“</a:Columns>”;
}
else {
query = “<a:AllColumns>true</a:AllColumns><a:Columns xmlns:b=’http://schemas.microsoft.com/2003/10/Serialization/Arrays&#8217; />”;
}

var msgBody =
[
“<entityName>”, entityName, “</entityName>”,
“<id>”, id, “</id>”,
“<columnSet xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts’>&#8221;,
query,
“</columnSet>”
].join(“”);

var async = !!callback;

return doRequest(msgBody, “Retrieve”, !!callback, function (resultXml) {
var retrieveResult = jQuery(resultXml).find(“RetrieveResult”).eq(0)[0];
var entity = new businessEntity();
entity.deserialize(retrieveResult);

if (!async)
return entity;
else
callback(entity);
// ReSharper disable NotAllPathsReturnValue
});
// ReSharper restore NotAllPathsReturnValue
};

var retrieveMultiple = function (query, callback) {
///<summary>
/// Sends synchronous/asynchronous request to do a retrieveMultiple request.
///</summary>
///<param name=”query” type=”String”>
/// A JavaScript String with properties corresponding to the retrievemultiple request
/// that are valid for retrievemultiple operations.
/// </param>
///<param name=”callback” type=”Function”>
/// A Function used for asynchronous request. If not defined, it sends a synchronous request.
/// </param>
var msgBody =
[
“<query i:type=’a:QueryExpression’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts’>&#8221;, query, “</query>”
].join(“”);

var async = !!callback;

return doRequest(msgBody, “RetrieveMultiple”, async, function (resultXml) {
var resultNodes;

if (jQuery(resultXml).find(“a\\:Entities”).length != 0) {
resultNodes = jQuery(resultXml).find(“a\\:Entities”).eq(0)[0];
} else {
resultNodes = jQuery(resultXml).find(“Entities”).eq(0)[0]; //chrome could not load node properly
}
var retriveMultipleResults = [];

for (var i = 0; i < resultNodes.childNodes.length; i++) {
var entity = new businessEntity();

entity.deserialize(resultNodes.childNodes[i]);
retriveMultipleResults[i] = entity;
}

if (!async)
return retriveMultipleResults;
else
callback(retriveMultipleResults);
// ReSharper disable NotAllPathsReturnValue
});
// ReSharper restore NotAllPathsReturnValue
};

var joinArray = function (prefix, array, suffix) {
var output = [];
for (var i = 0; i < array.length; i++) {
if (array[i] != ” && array[i] != undefined) {
output.push(prefix, array[i], suffix);
}
}
return output.join(“”);
};

var joinConditionPair = function (attributes, values) {
var output = [];
for (var i = 0; i < attributes.length; i++) {
if (attributes[i] != ”) {
if (typeof values[i] == typeof [])
{
output.push(“<condition attribute='”, attributes[i], “‘ operator=’in’ >”);

for (var valueIndex in values[i])
{
var value = encodeValue(values[i][valueIndex]);
output.push(“<value>” + value + “</value>”);
}

output.push(“</condition>”);
}
else if (typeof values[i] == typeof “”)
{
output.push(“<condition attribute='”, attributes[i], “‘ operator=’eq’ value='”, encodeValue(values[i]), “‘ />”);
}
}
}
return output.join(“”);
};

var isArray = function (input) {
return input.constructor.toString().indexOf(“Array”) != -1;
};

var queryByAttribute = function (queryOptions, callback) {
///<summary>
/// Sends synchronous/asynchronous request to do a queryByAttribute request.
///</summary>
///<param name=”queryOptions” type=”Object”>
/// A JavaScript Object with properties corresponding to the queryByAttribute Criteria
/// that are valid for queryByAttribute operations.
/// queryOptions.entityName is a string represents the name of the entity
/// queryOptions.attributes is a array represents the attributes of the entity to query
/// queryOptions.values is a array represents the values of the attributes to query
/// queryOptions.columnSet is a array represents the attributes of the entity to return
/// queryOptions.orderBy is a array represents the order conditions of the results
/// </param>
///<param name=”callback” type=”Function”>
/// A Function used for asynchronous request. If not defined, it sends a synchronous request.
/// </param>
var entityName = queryOptions.entityName;
var attributes = queryOptions.attributes;
var values = queryOptions.values;
var columnSet = queryOptions.columnSet;
var orderBy = queryOptions.orderBy || ”;

attributes = isArray(attributes) ? attributes : [attributes];
values = isArray(values) ? values : [values];
orderBy = (!!orderBy && isArray(orderBy)) ? orderBy : [orderBy];
columnSet = (!!columnSet && isArray(columnSet)) ? columnSet : [columnSet];

var xml =
[
” <entity name='”, entityName, “‘>”,
joinArray(“<attribute name='”, columnSet, “‘ />”),
joinArray(“<order attribute='”, orderBy, “‘ />”),
” <filter>”,
joinConditionPair(attributes, values),
” </filter>”,
” </entity>”
].join(“”);

return fetch(xml, false, callback);
};

var queryAll = function (queryOptions, callback) {
///<summary>
/// Sends synchronous/asynchronous request to do a queryAll request. This is to return all records (>5k+).
/// Consider Performance impact when using this method.
///</summary>
///<param name=”queryOptions” type=”Object”>
/// A JavaScript Object with properties corresponding to the queryByAttribute Criteria
/// that are valid for queryByAttribute operations.
/// queryOptions.entityName is a string represents the name of the entity
/// queryOptions.attributes is a array represents the attributes of the entity to query
/// queryOptions.values is a array represents the values of the attributes to query
/// queryOptions.columnSet is a array represents the attributes of the entity to return
/// queryOptions.orderBy is a array represents the order conditions of the results
/// </param>
///<param name=”callback” type=”Function”>
/// A Function used for asynchronous request. If not defined, it sends a synchronous request.
/// </param>
var entityName = queryOptions.entityName;
var attributes = queryOptions.attributes;
var values = queryOptions.values;
var columnSet = queryOptions.columnSet;
var orderBy = queryOptions.orderBy || ”;

attributes = isArray(attributes) ? attributes : [attributes];
values = isArray(values) ? values : [values];
orderBy = (!!orderBy && isArray(orderBy)) ? orderBy : [orderBy];
columnSet = (!!columnSet && isArray(columnSet)) ? columnSet : [columnSet];

var fetchCore = [
” <entity name='”, entityName, “‘>”,
joinArray(“<attribute name='”, columnSet, “‘ />”),
joinArray(“<order attribute='”, orderBy, “‘ />”),
” <filter>”,
joinConditionPair(attributes, values),
” </filter>”,
” </entity>”
].join(“”);

var async = !!callback;

return fetch(fetchCore, true, async);
};

var setState = function (entityName, id, stateCode, statusCode, callback) {
///<summary>
/// Sends synchronous/asynchronous request to setState of a record.
///</summary>
///<param name=”entityName” type=”String”>
/// A JavaScript String corresponding to the Schema name of
/// entity that is used for setState operations.
/// </param>
///<param name=”id” type=”String”>
/// A JavaScript String corresponding to the GUID of
/// entity that is used for setState operations.
/// </param>
///<param name=”stateCode” type=”Int”>
/// A JavaScript Integer corresponding to the value of
/// entity state that is used for setState operations.
/// </param>
///<param name=”statusCode” type=”Int”>
/// A JavaScript Integer corresponding to the value of
/// entity status that is used for setState operations.
/// </param>
///<param name=”callback” type=”Function”>
/// A Function used for asynchronous request. If not defined, it sends a synchronous request.
/// </param>
var request = [
“<request i:type=’b:SetStateRequest’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts&#8217; xmlns:b=’http://schemas.microsoft.com/crm/2011/Contracts’>&#8221;,
“<a:Parameters xmlns:c=’http://schemas.datacontract.org/2004/07/System.Collections.Generic’>&#8221;,
“<a:KeyValuePairOfstringanyType>”,
“<c:key>EntityMoniker</c:key>”,
“<c:value i:type=’a:EntityReference’>”,
“<a:Id>”, id, “</a:Id>”,
“<a:LogicalName>”, entityName, “</a:LogicalName>”,
“<a:Name i:nil=’true’ />”,
“</c:value>”,
“</a:KeyValuePairOfstringanyType>”,
“<a:KeyValuePairOfstringanyType>”,
“<c:key>State</c:key>”,
“<c:value i:type=’a:OptionSetValue’>”,
“<a:Value>”, stateCode.toString(), “</a:Value>”,
“</c:value>”,
“</a:KeyValuePairOfstringanyType>”,
“<a:KeyValuePairOfstringanyType>”,
“<c:key>Status</c:key>”,
“<c:value i:type=’a:OptionSetValue’>”,
“<a:Value>”, statusCode.toString(), “</a:Value>”,
“</c:value>”,
“</a:KeyValuePairOfstringanyType>”,
“</a:Parameters>”,
“<a:RequestId i:nil=’true’ />”,
“<a:RequestName>SetState</a:RequestName>”,
“</request>”
].join(“”);

var async = !!callback;

return doRequest(request, “Execute”, async, function (resultXml) {
var response = jQuery(resultXml).find(‘ExecuteResult’).eq(0);
var result = crmXmlDecode(response.text());
if (!async)
return result;
else
callback(result);
// ReSharper disable NotAllPathsReturnValue
});
// ReSharper restore NotAllPathsReturnValue
};

var associate = function (relationshipName, targetEntityName, targetId, relatedEntityName, relatedBusinessEntities, callback) {
///<summary>
/// Sends synchronous/asynchronous request to associate records.
///</summary>
///<param name=”relationshipName” type=”String”>
/// A JavaScript String corresponding to the relationship name
/// that is used for associate operations.
/// </param>
///<param name=”targetEntityName” type=”String”>
/// A JavaScript String corresponding to the schema name of the target entity
/// that is used for associate operations.
/// </param>
///<param name=”targetId” type=”String”>
/// A JavaScript String corresponding to the GUID of the target entity
/// that is used for associate operations.
/// </param>
///<param name=”relatedEntityName” type=”String”>
/// A JavaScript String corresponding to the schema name of the related entity
/// that is used for associate operations.
/// </param>
///<param name=”relationshipBusinessEntities” type=”Array”>
/// A JavaScript Array corresponding to the collection of the related entities as BusinessEntity
/// that is used for associate operations.
/// </param>
///<param name=”callback” type=”Function”>
/// A Function used for asynchronous request. If not defined, it sends a synchronous request.
/// </param>
var relatedEntities = relatedBusinessEntities;

relatedEntities = isArray(relatedEntities) ? relatedEntities : [relatedEntities];

var output = [];
for (var i = 0; i < relatedEntities.length; i++) {
if (relatedEntities[i].id != ”) {
output.push(“<a:EntityReference>”,
“<a:Id>”, relatedEntities[i].id, “</a:Id>”,
“<a:LogicalName>”, relatedEntityName, “</a:LogicalName>”,
“<a:Name i:nil=’true’ />”,
“</a:EntityReference>”);
}
}

var relatedXml = output.join(“”);

var request = [
“<request i:type=’a:AssociateRequest’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts’>&#8221;,
“<a:Parameters xmlns:b=’http://schemas.datacontract.org/2004/07/System.Collections.Generic’>&#8221;,
“<a:KeyValuePairOfstringanyType>”,
“<b:key>Target</b:key>”,
“<b:value i:type=’a:EntityReference’>”,
“<a:Id>”, targetId, “</a:Id>”,
“<a:LogicalName>”, targetEntityName, “</a:LogicalName>”,
“<a:Name i:nil=’true’ />”,
“</b:value>”,
“</a:KeyValuePairOfstringanyType>”,
“<a:KeyValuePairOfstringanyType>”,
“<b:key>Relationship</b:key>”,
“<b:value i:type=’a:Relationship’>”,
“<a:PrimaryEntityRole i:nil=’true’ />”,
“<a:SchemaName>”, relationshipName, “</a:SchemaName>”,
“</b:value>”,
“</a:KeyValuePairOfstringanyType>”,
“<a:KeyValuePairOfstringanyType>”,
“<b:key>RelatedEntities</b:key>”,
“<b:value i:type=’a:EntityReferenceCollection’>”,
relatedXml,
“</b:value>”,
“</a:KeyValuePairOfstringanyType>”,
“</a:Parameters>”,
“<a:RequestId i:nil=’true’ />”,
“<a:RequestName>Associate</a:RequestName>”,
“</request>”
].join(“”);

var async = !!callback;

return doRequest(request, “Execute”, async, function (resultXml) {
var response = jQuery(resultXml).find(‘ExecuteResult’).eq(0);
var result = crmXmlDecode(response.text());
if (!async)
return result;
else
callback(result);
// ReSharper disable NotAllPathsReturnValue
});
// ReSharper restore NotAllPathsReturnValue
};

var disassociate = function (relationshipName, targetEntityName, targetId, relatedEntityName, relatedBusinessEntities, callback) {
///<summary>
/// Sends synchronous/asynchronous request to disassociate records.
///</summary>
///<param name=”relationshipName” type=”String”>
/// A JavaScript String corresponding to the relationship name
/// that is used for disassociate operations.
/// </param>
///<param name=”targetEntityName” type=”String”>
/// A JavaScript String corresponding to the schema name of the target entity
/// that is used for disassociate operations.
/// </param>
///<param name=”targetId” type=”String”>
/// A JavaScript String corresponding to the GUID of the target entity
/// that is used for disassociate operations.
/// </param>
///<param name=”relatedEntityName” type=”String”>
/// A JavaScript String corresponding to the schema name of the related entity
/// that is used for disassociate operations.
/// </param>
///<param name=”relationshipBusinessEntities” type=”Array”>
/// A JavaScript Array corresponding to the collection of the related entities as BusinessEntity
/// that is used for disassociate operations.
/// </param>
///<param name=”callback” type=”Function”>
/// A Function used for asynchronous request. If not defined, it sends a synchronous request.
/// </param>
var relatedEntities = relatedBusinessEntities;

relatedEntities = isArray(relatedEntities) ? relatedEntities : [relatedEntities];

var output = [];
for (var i = 0; i < relatedEntities.length; i++) {
if (relatedEntities[i].id != ”) {
output.push(“<a:EntityReference>”,
“<a:Id>”, relatedEntities[i].id, “</a:Id>”,
“<a:LogicalName>”, relatedEntityName, “</a:LogicalName>”,
“<a:Name i:nil=’true’ />”,
“</a:EntityReference>”);
}
}

var relatedXml = output.join(“”);

var request = [
“<request i:type=’a:DisassociateRequest’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts’>&#8221;,
“<a:Parameters xmlns:b=’http://schemas.datacontract.org/2004/07/System.Collections.Generic’>&#8221;,
“<a:KeyValuePairOfstringanyType>”,
“<b:key>Target</b:key>”,
“<b:value i:type=’a:EntityReference’>”,
“<a:Id>”, targetId, “</a:Id>”,
“<a:LogicalName>”, targetEntityName, “</a:LogicalName>”,
“<a:Name i:nil=’true’ />”,
“</b:value>”,
“</a:KeyValuePairOfstringanyType>”,
“<a:KeyValuePairOfstringanyType>”,
“<b:key>Relationship</b:key>”,
“<b:value i:type=’a:Relationship’>”,
“<a:PrimaryEntityRole i:nil=’true’ />”,
“<a:SchemaName>”, relationshipName, “</a:SchemaName>”,
“</b:value>”,
“</a:KeyValuePairOfstringanyType>”,
“<a:KeyValuePairOfstringanyType>”,
“<b:key>RelatedEntities</b:key>”,
“<b:value i:type=’a:EntityReferenceCollection’>”,
relatedXml,
“</b:value>”,
“</a:KeyValuePairOfstringanyType>”,
“</a:Parameters>”,
“<a:RequestId i:nil=’true’ />”,
“<a:RequestName>Disassociate</a:RequestName>”,
“</request>”
].join(“”);

var async = !!callback;

return doRequest(request, “Execute”, async, function (resultXml) {
var response = jQuery(resultXml).find(‘ExecuteResult’).eq(0);
var result = crmXmlDecode(response.text());
if (!async)
return result;
else
callback(result);
// ReSharper disable NotAllPathsReturnValue
});
// ReSharper restore NotAllPathsReturnValue
};

var getCurrentUserId = function () {
///<summary>
/// Sends synchronous request to retrieve the GUID of the current user.
///</summary>
var request = “<request i:type=’b:WhoAmIRequest’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts&#8217; xmlns:b=’http://schemas.microsoft.com/crm/2011/Contracts’>&#8221; +
“<a:Parameters xmlns:c=’http://schemas.datacontract.org/2004/07/System.Collections.Generic&#8217; />” +
“<a:RequestId i:nil=’true’ />” +
“<a:RequestName>WhoAmI</a:RequestName>” +
“</request>”;
var xmlDoc = doRequest(request, “Execute”);
if (jQuery(xmlDoc).find(‘a\\:Results’).length != 0) {
return jQuery(xmlDoc).find(‘a\\:Results’).children().eq(0).children().eq(1).text();
} else {
return jQuery(xmlDoc).find(‘Results’).children().eq(0).children().eq(1).text(); //Chrome 24.0.1312.52 could not find node by the previous code
}

};

var getCurrentUserBusinessUnitId = function () {
///<summary>
/// Sends synchronous request to retrieve the GUID of the current user’s business unit.
///</summary>
var request = “<request i:type=’b:WhoAmIRequest’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts&#8217; xmlns:b=’http://schemas.microsoft.com/crm/2011/Contracts’>&#8221; +
“<a:Parameters xmlns:c=’http://schemas.datacontract.org/2004/07/System.Collections.Generic&#8217; />” +
“<a:RequestId i:nil=’true’ />” +
“<a:RequestName>WhoAmI</a:RequestName>” +
“</request>”;
var xmlDoc = doRequest(request, “Execute”);

if (jQuery(xmlDoc).find(‘a\\:Results’).length != 0) {
return jQuery(xmlDoc).find(‘a\\:Results’).children().eq(1).children().eq(1).text();
} else {
return jQuery(xmlDoc).find(‘Results’).children().eq(1).children().eq(1).text(); //Chrome 24.0.1312.52 could not find node by the previous code
}
};

var getCurrentUserRoles = function () {
///<summary>
/// Sends synchronous request to retrieve the list of the current user’s roles.
///</summary>
var xml =
[
“<fetch version=’1.0′ output-format=’xml-platform’ mapping=’logical’ distinct=’true’>” +
“<entity name=’role’>” +
“<attribute name=’name’ />” +
“<attribute name=’businessunitid’ />” +
“<attribute name=’roleid’ />” +
“<order attribute=’name’ descending=’false’ />” +
“<link-entity name=’systemuserroles’ from=’roleid’ to=’roleid’ visible=’false’ intersect=’true’>” +
“<link-entity name=’systemuser’ from=’systemuserid’ to=’systemuserid’ alias=’aa’>” +
“<filter type=’and’>” +
“<condition attribute=’systemuserid’ operator=’eq-userid’ />” +
“</filter>” +
“</link-entity>” +
“</link-entity>” +
“</entity>” +
“</fetch>”
].join(“”);

var fetchResult = fetch(xml);
var roles = [];

if (fetchResult !== null && typeof fetchResult != ‘undefined’) {
for (var i = 0; i < fetchResult.length; i++) {
roles[i] = fetchResult[i].attributes[“name”].value;
}
}

return roles;
};

var isCurrentUserInRole = function () {
///<summary>
/// Sends synchronous request to check if the current user has certain roles
/// Passes name of role as arguments. For example, IsCurrentUserInRole(‘System Administrator’)
/// Returns true or false.
///</summary>
var roles = getCurrentUserRoles();
for (var i = 0; i < roles.length; i++) {
for (var j = 0; j < arguments.length; j++) {
if (roles[i] === arguments[j]) {
return true;
}
}
}

return false;
};

var assign = function (targetEntityName, targetId, assigneeEntityName, assigneeId, callback) {
///<summary>
/// Sends synchronous/asynchronous request to assign an existing record to a user / a team.
///</summary>
///<param name=”targetEntityName” type=”String”>
/// A JavaScript String corresponding to the schema name of the target entity
/// that is used for assign operations.
/// </param>
///<param name=”targetId” type=”String”>
/// A JavaScript String corresponding to the GUID of the target entity
/// that is used for assign operations.
/// </param>
///<param name=”assigneeEntityName” type=”String”>
/// A JavaScript String corresponding to the schema name of the assignee entity
/// that is used for assign operations.
/// </param>
///<param name=”assigneeId” type=”String”>
/// A JavaScript String corresponding to the GUID of the assignee entity
/// that is used for assign operations.
/// </param>
///<param name=”callback” type=”Function”>
/// A Function used for asynchronous request. If not defined, it sends a synchronous request.
/// </param>

var request = “<request i:type=’b:AssignRequest’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts&#8217; xmlns:b=’http://schemas.microsoft.com/crm/2011/Contracts’>&#8221; +
“<a:Parameters xmlns:c=’http://schemas.datacontract.org/2004/07/System.Collections.Generic’>&#8221; +
“<a:KeyValuePairOfstringanyType>” +
“<c:key>Target</c:key>” +
“<c:value i:type=’a:EntityReference’>” +
“<a:Id>” + targetId + “</a:Id>” +
“<a:LogicalName>” + targetEntityName + “</a:LogicalName>” +
“<a:Name i:nil=’true’ />” +
“</c:value>” +
“</a:KeyValuePairOfstringanyType>” +
“<a:KeyValuePairOfstringanyType>” +
“<c:key>Assignee</c:key>” +
“<c:value i:type=’a:EntityReference’>” +
“<a:Id>” + assigneeId + “</a:Id>” +
“<a:LogicalName>” + assigneeEntityName + “</a:LogicalName>” +
“<a:Name i:nil=’true’ />” +
“</c:value>” +
“</a:KeyValuePairOfstringanyType>” +
“</a:Parameters>” +
“<a:RequestId i:nil=’true’ />” +
“<a:RequestName>Assign</a:RequestName>” +
“</request>”;
var async = !!callback;

return doRequest(request, “Execute”, async, function (resultXml) {
var response = jQuery(resultXml).find(‘ExecuteResult’).eq(0);
var result = crmXmlDecode(response.text());
if (!async)
return result;
else
callback(result);
// ReSharper disable NotAllPathsReturnValue
});
// ReSharper restore NotAllPathsReturnValue
};

var grantAccess = function (accessOptions, callback) {
///<summary>
/// Sends synchronous/asynchronous request to do a grantAccess request.
/// Levels of Access Options are: AppendAccess, AppendToAccess, AssignAccess, CreateAccess, DeleteAccess, None, ReadAccess, ShareAccess, and WriteAccess
///</summary>
///<param name=”accessOptions” type=”Object”>
/// A JavaScript Object with properties corresponding to the grantAccess Criteria
/// that are valid for grantAccess operations.
/// accessOptions.targetEntityName is a string represents the name of the target entity
/// accessOptions.targetEntityId is a string represents the GUID of the target entity
/// accessOptions.principalEntityName is a string represents the name of the principal entity
/// accessOptions.principalEntityId is a string represents the GUID of the principal entity
/// accessOptions.accessRights is a array represents the access conditions of the results
/// </param>
///<param name=”callback” type=”Function”>
/// A Function used for asynchronous request. If not defined, it sends a synchronous request.
/// </param>

var targetEntityName = accessOptions.targetEntityName;
var targetEntityId = accessOptions.targetEntityId;
var principalEntityName = accessOptions.principalEntityName;
var principalEntityId = accessOptions.principalEntityId;
var accessRights = accessOptions.accessRights;

accessRights = isArray(accessRights) ? accessRights : [accessRights];

var accessRightString = “”;
for (var i = 0; i < accessRights.length; i++) {
accessRightString += encodeValue(accessRights[i]) + ” “;
}

var request = “<request i:type=’b:GrantAccessRequest’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts&#8217; xmlns:b=’http://schemas.microsoft.com/crm/2011/Contracts’>&#8221; +
“<a:Parameters xmlns:c=’http://schemas.datacontract.org/2004/07/System.Collections.Generic’>&#8221; +
“<a:KeyValuePairOfstringanyType>” +
“<c:key>Target</c:key>” +
“<c:value i:type=’a:EntityReference’>” +
“<a:Id>” + targetEntityId + “</a:Id>” +
“<a:LogicalName>” + targetEntityName + “</a:LogicalName>” +
“<a:Name i:nil=’true’ />” +
“</c:value>” +
“</a:KeyValuePairOfstringanyType>” +
“<a:KeyValuePairOfstringanyType>” +
“<c:key>PrincipalAccess</c:key>” +
“<c:value i:type=’b:PrincipalAccess’>” +
“<b:AccessMask>” + accessRightString + “</b:AccessMask>” +
“<b:Principal>” +
“<a:Id>” + principalEntityId + “</a:Id>” +
“<a:LogicalName>” + principalEntityName + “</a:LogicalName>” +
“<a:Name i:nil=’true’ />” +
“</b:Principal>” +
“</c:value>” +
“</a:KeyValuePairOfstringanyType>” +
“</a:Parameters>” +
“<a:RequestId i:nil=’true’ />” +
“<a:RequestName>GrantAccess</a:RequestName>” +
“</request>”;
var async = !!callback;

return doRequest(request, “Execute”, async, function (resultXml) {
var response = jQuery(resultXml).find(‘ExecuteResult’).eq(0);
var result = crmXmlDecode(response.text());
if (!async)
return result;
else
callback(result);
// ReSharper disable NotAllPathsReturnValue
});
// ReSharper restore NotAllPathsReturnValue
};

var modifyAccess = function (accessOptions, callback) {
///<summary>
/// Sends synchronous/asynchronous request to do a modifyAccess request.
/// Levels of Access Options are: AppendAccess, AppendToAccess, AssignAccess, CreateAccess, DeleteAccess, None, ReadAccess, ShareAccess, and WriteAccess
///</summary>
///<param name=”accessOptions” type=”Object”>
/// A JavaScript Object with properties corresponding to the modifyAccess Criteria
/// that are valid for modifyAccess operations.
/// accessOptions.targetEntityName is a string represents the name of the target entity
/// accessOptions.targetEntityId is a string represents the GUID of the target entity
/// accessOptions.principalEntityName is a string represents the name of the principal entity
/// accessOptions.principalEntityId is a string represents the GUID of the principal entity
/// accessOptions.accessRights is a array represents the access conditions of the results
/// </param>
///<param name=”callback” type=”Function”>
/// A Function used for asynchronous request. If not defined, it sends a synchronous request.
/// </param>

var targetEntityName = accessOptions.targetEntityName;
var targetEntityId = accessOptions.targetEntityId;
var principalEntityName = accessOptions.principalEntityName;
var principalEntityId = accessOptions.principalEntityId;
var accessRights = accessOptions.accessRights;

accessRights = isArray(accessRights) ? accessRights : [accessRights];

var accessRightString = “”;
for (var i = 0; i < accessRights.length; i++) {
accessRightString += encodeValue(accessRights[i]) + ” “;
}

var request = “<request i:type=’b:ModifyAccessRequest’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts&#8217; xmlns:b=’http://schemas.microsoft.com/crm/2011/Contracts’>&#8221; +
“<a:Parameters xmlns:c=’http://schemas.datacontract.org/2004/07/System.Collections.Generic’>&#8221; +
“<a:KeyValuePairOfstringanyType>” +
“<c:key>Target</c:key>” +
“<c:value i:type=’a:EntityReference’>” +
“<a:Id>” + targetEntityId + “</a:Id>” +
“<a:LogicalName>” + targetEntityName + “</a:LogicalName>” +
“<a:Name i:nil=’true’ />” +
“</c:value>” +
“</a:KeyValuePairOfstringanyType>” +
“<a:KeyValuePairOfstringanyType>” +
“<c:key>PrincipalAccess</c:key>” +
“<c:value i:type=’b:PrincipalAccess’>” +
“<b:AccessMask>” + accessRightString + “</b:AccessMask>” +
“<b:Principal>” +
“<a:Id>” + principalEntityId + “</a:Id>” +
“<a:LogicalName>” + principalEntityName + “</a:LogicalName>” +
“<a:Name i:nil=’true’ />” +
“</b:Principal>” +
“</c:value>” +
“</a:KeyValuePairOfstringanyType>” +
“</a:Parameters>” +
“<a:RequestId i:nil=’true’ />” +
“<a:RequestName>ModifyAccess</a:RequestName>” +
“</request>”;
var async = !!callback;

return doRequest(request, “Execute”, async, function (resultXml) {
var response = jQuery(resultXml).find(‘ExecuteResult’).eq(0);
var result = crmXmlDecode(response.text());
if (!async)
return result;
else
callback(result);
// ReSharper disable NotAllPathsReturnValue
});
// ReSharper restore NotAllPathsReturnValue
};

var revokeAccess = function (accessOptions, callback) {
///<summary>
/// Sends synchronous/asynchronous request to do a revokeAccess request.
///</summary>
///<param name=”accessOptions” type=”Object”>
/// A JavaScript Object with properties corresponding to the revokeAccess Criteria
/// that are valid for revokeAccess operations.
/// accessOptions.targetEntityName is a string represents the name of the target entity
/// accessOptions.targetEntityId is a string represents the GUID of the target entity
/// accessOptions.revokeeEntityName is a string represents the name of the revokee entity
/// accessOptions.revokeeEntityId is a string represents the GUID of the revokee entity
/// </param>
///<param name=”callback” type=”Function”>
/// A Function used for asynchronous request. If not defined, it sends a synchronous request.
/// </param>

var targetEntityName = accessOptions.targetEntityName;
var targetEntityId = accessOptions.targetEntityId;
var revokeeEntityName = accessOptions.revokeeEntityName;
var revokeeEntityId = accessOptions.revokeeEntityId;

var request = “<request i:type=’b:RevokeAccessRequest’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts&#8217; xmlns:b=’http://schemas.microsoft.com/crm/2011/Contracts’>&#8221; +
“<a:Parameters xmlns:c=’http://schemas.datacontract.org/2004/07/System.Collections.Generic’>&#8221; +
“<a:KeyValuePairOfstringanyType>” +
“<c:key>Target</c:key>” +
“<c:value i:type=’a:EntityReference’>” +
“<a:Id>” + targetEntityId + “</a:Id>” +
“<a:LogicalName>” + targetEntityName + “</a:LogicalName>” +
“<a:Name i:nil=’true’ />” +
“</c:value>” +
“</a:KeyValuePairOfstringanyType>” +
“<a:KeyValuePairOfstringanyType>” +
“<c:key>Revokee</c:key>” +
“<c:value i:type=’a:EntityReference’>” +
“<a:Id>” + revokeeEntityId + “</a:Id>” +
“<a:LogicalName>” + revokeeEntityName + “</a:LogicalName>” +
“<a:Name i:nil=’true’ />” +
“</c:value>” +
“</a:KeyValuePairOfstringanyType>” +
“</a:Parameters>” +
“<a:RequestId i:nil=’true’ />” +
“<a:RequestName>RevokeAccess</a:RequestName>” +
“</request>”;
var async = !!callback;

return doRequest(request, “Execute”, async, function (resultXml) {
var response = jQuery(resultXml).find(‘ExecuteResult’).eq(0);
var result = crmXmlDecode(response.text());
if (!async)
return result;
else
callback(result);
// ReSharper disable NotAllPathsReturnValue
});
// ReSharper restore NotAllPathsReturnValue
};

var retrievePrincipalAccess = function (accessOptions, callback) {
///<summary>
/// Sends synchronous/asynchronous request to do a retrievePrincipalAccess request.
///</summary>
///<param name=”accessOptions” type=”Object”>
/// A JavaScript Object with properties corresponding to the retrievePrincipalAccess Criteria
/// that are valid for retrievePrincipalAccess operations.
/// accessOptions.targetEntityName is a string represents the name of the target entity
/// accessOptions.targetEntityId is a string represents the GUID of the target entity
/// accessOptions.principalEntityName is a string represents the name of the principal entity
/// accessOptions.principalEntityId is a string represents the GUID of the principal entity
/// </param>
///<param name=”callback” type=”Function”>
/// A Function used for asynchronous request. If not defined, it sends a synchronous request.
/// </param>

var targetEntityName = accessOptions.targetEntityName;
var targetEntityId = accessOptions.targetEntityId;
var principalEntityName = accessOptions.principalEntityName;
var principalEntityId = accessOptions.principalEntityId;

var request = “<request i:type=’b:RetrievePrincipalAccessRequest’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts&#8217; xmlns:b=’http://schemas.microsoft.com/crm/2011/Contracts’>&#8221; +
“<a:Parameters xmlns:c=’http://schemas.datacontract.org/2004/07/System.Collections.Generic’>&#8221; +
“<a:KeyValuePairOfstringanyType>” +
“<c:key>Target</c:key>” +
“<c:value i:type=’a:EntityReference’>” +
“<a:Id>” + targetEntityId + “</a:Id>” +
“<a:LogicalName>” + targetEntityName + “</a:LogicalName>” +
“<a:Name i:nil=’true’ />” +
“</c:value>” +
“</a:KeyValuePairOfstringanyType>” +
“<a:KeyValuePairOfstringanyType>” +
“<c:key>Principal</c:key>” +
“<c:value i:type=’a:EntityReference’>” +
“<a:Id>” + principalEntityId + “</a:Id>” +
“<a:LogicalName>” + principalEntityName + “</a:LogicalName>” +
“<a:Name i:nil=’true’ />” +
“</c:value>” +
“</a:KeyValuePairOfstringanyType>” +
“</a:Parameters>” +
“<a:RequestId i:nil=’true’ />” +
“<a:RequestName>RetrievePrincipalAccess</a:RequestName>” +
“</request>”;
var async = !!callback;

return doRequest(request, “Execute”, async, function (resultXml) {
var response;
if (jQuery(resultXml).find(‘c\\:value’).length != 0) {
response = jQuery(resultXml).find(‘c\\:value’).eq(0);
} else {
response = jQuery(resultXml).find(‘value’).eq(0);; //Chrome 24.0.1312.52 could not find node by the previous code
}
var result = crmXmlDecode(response.text());
if (!async)
return result;
else
callback(result);
// ReSharper disable NotAllPathsReturnValue
});
// ReSharper restore NotAllPathsReturnValue
};

// Added in 1.4.1 for metadata retrieval
// Inspired From Microsoft SDK code to retrieve Metadata using JavaScript
// Copyright (C) Microsoft Corporation. All rights reserved.
var arrayElements = [“Attributes”,
“ManyToManyRelationships”,
“ManyToOneRelationships”,
“OneToManyRelationships”,
“Privileges”,
“LocalizedLabels”,
“Options”,
“Targets”];

var isMetadataArray = function (elementName) {
for (var i = 0; i < arrayElements.length; i++) {
if (elementName === arrayElements[i]) {
return true;
}
}
return false;
};

var getNodeName = function (node) {
if (typeof (node.baseName) != “undefined”) {
return node.baseName;
}
else {
return node.localName;
}
};

var objectifyNode = function (node) {
//Check for null
if (node.attributes != null && node.attributes.length == 1) {
if (node.attributes.getNamedItem(“i:nil”) != null && node.attributes.getNamedItem(“i:nil”).nodeValue == “true”) {
return null;
}
}

//Check if it is a value
if ((node.firstChild != null) && (node.firstChild.nodeType == 3)) {
var nodeName = getNodeName(node);

switch (nodeName) {
//Integer Values
case “ActivityTypeMask”:
case “ObjectTypeCode”:
case “ColumnNumber”:
case “DefaultFormValue”:
case “MaxValue”:
case “MinValue”:
case “MaxLength”:
case “Order”:
case “Precision”:
case “PrecisionSource”:
case “LanguageCode”:
return parseInt(node.firstChild.nodeValue, 10);
// Boolean values
case “AutoRouteToOwnerQueue”:
case “CanBeChanged”:
case “CanTriggerWorkflow”:
case “IsActivity”:
case “IsActivityParty”:
case “IsAvailableOffline”:
case “IsChildEntity”:
case “IsCustomEntity”:
case “IsCustomOptionSet”:
case “IsDocumentManagementEnabled”:
case “IsEnabledForCharts”:
case “IsGlobal”:
case “IsImportable”:
case “IsIntersect”:
case “IsManaged”:
case “IsReadingPaneEnabled”:
case “IsValidForAdvancedFind”:
case “CanBeSecuredForCreate”:
case “CanBeSecuredForRead”:
case “CanBeSecuredForUpdate”:
case “IsCustomAttribute”:
case “IsPrimaryId”:
case “IsPrimaryName”:
case “IsSecured”:
case “IsValidForCreate”:
case “IsValidForRead”:
case “IsValidForUpdate”:
case “IsCustomRelationship”:
case “CanBeBasic”:
case “CanBeDeep”:
case “CanBeGlobal”:
case “CanBeLocal”:
return (node.firstChild.nodeValue === “true”) ? true : false;
//OptionMetadata.Value and BooleanManagedProperty.Value and AttributeRequiredLevelManagedProperty.Value
case “Value”:
//BooleanManagedProperty.Value
if ((node.firstChild.nodeValue === “true”) || (node.firstChild.nodeValue == “false”)) {
return (node.firstChild.nodeValue == “true”) ? true : false;
}
//AttributeRequiredLevelManagedProperty.Value
if (
(node.firstChild.nodeValue == “ApplicationRequired”) ||
(node.firstChild.nodeValue == “None”) ||
(node.firstChild.nodeValue == “Recommended”) ||
(node.firstChild.nodeValue == “SystemRequired”)
) {
return node.firstChild.nodeValue;
}
else {
//OptionMetadata.Value
return parseInt(node.firstChild.nodeValue, 10);
}
// ReSharper disable JsUnreachableCode
break;
// ReSharper restore JsUnreachableCode
//String values
default:
return node.firstChild.nodeValue;
}

}

//Check if it is a known array
if (isMetadataArray(getNodeName(node))) {
var arrayValue = [];
for (var iii = 0; iii < node.childNodes.length; iii++) {
var objectTypeName;
if ((node.childNodes[iii].attributes != null) && (node.childNodes[iii].attributes.getNamedItem(“i:type”) != null)) {
objectTypeName = node.childNodes[iii].attributes.getNamedItem(“i:type”).nodeValue.split(“:”)[1];
}
else {

objectTypeName = getNodeName(node.childNodes[iii]);
}

var b = objectifyNode(node.childNodes[iii]);
b._type = objectTypeName;
arrayValue.push(b);

}

return arrayValue;
}

//Null entity description labels are returned as <label/> – not using i:nil = true;
if (node.childNodes.length == 0) {
return null;
}

//Otherwise return an object
var c = {};
if (node.attributes.getNamedItem(“i:type”) != null) {
c._type = node.attributes.getNamedItem(“i:type”).nodeValue.split(“:”)[1];
}
for (var i = 0; i < node.childNodes.length; i++) {
if (node.childNodes[i].nodeType == 3) {
c[getNodeName(node.childNodes[i])] = node.childNodes[i].nodeValue;
}
else {
c[getNodeName(node.childNodes[i])] = objectifyNode(node.childNodes[i]);
}

}
return c;
};

var retrieveAllEntitiesMetadata = function (entityFilters, retrieveIfPublished, callback) {
///<summary>
/// Sends an synchronous/asynchronous RetrieveAllEntitieMetadata Request to retrieve all entities metadata in the system
///</summary>
///<returns>Entity Metadata Collection</returns>
///<param name=”entityFilters” type=”Array”>
/// The filter array available to filter which data is retrieved. Case Sensitive filters [Entity,Attributes,Privileges,Relationships]
/// Include only those elements of the entity you want to retrieve in the array. Retrieving all parts of all entities may take significant time.
///</param>
///<param name=”retrieveIfPublished” type=”Boolean”>
/// Sets whether to retrieve the metadata that has not been published.
///</param>
///<param name=”callBack” type=”Function”>
/// The function that will be passed through and be called by a successful response.
/// This function also used as an indicator if the function is synchronous/asynchronous
///</param>

entityFilters = isArray(entityFilters) ? entityFilters : [entityFilters];
var entityFiltersString = “”;
for (var iii = 0; iii < entityFilters.length; iii++) {
entityFiltersString += encodeValue(entityFilters[iii]) + ” “;
}

var request = [
“<request i:type=\”a:RetrieveAllEntitiesRequest\” xmlns:a=\”http://schemas.microsoft.com/xrm/2011/Contracts\”>”,
“<a:Parameters xmlns:b=\”http://schemas.datacontract.org/2004/07/System.Collections.Generic\”>”,
“<a:KeyValuePairOfstringanyType>”,
“<b:key>EntityFilters</b:key>”,
“<b:value i:type=\”c:EntityFilters\” xmlns:c=\”http://schemas.microsoft.com/xrm/2011/Metadata\”>” + encodeValue(entityFiltersString) + “</b:value>”,
“</a:KeyValuePairOfstringanyType>”,
“<a:KeyValuePairOfstringanyType>”,
“<b:key>RetrieveAsIfPublished</b:key>”,
“<b:value i:type=\”c:boolean\” xmlns:c=\”http://www.w3.org/2001/XMLSchema\”>” + encodeValue(retrieveIfPublished.toString()) + “</b:value>”,
“</a:KeyValuePairOfstringanyType>”,
“</a:Parameters>”,
“<a:RequestId i:nil=\”true\” />”,
“<a:RequestName>RetrieveAllEntities</a:RequestName>”,
“</request>”].join(“”);

var async = !!callback;
return doRequest(request, “Execute”, async, function (resultXml) {
var response;
if (jQuery(resultXml).find(‘c\\:EntityMetadata’).length != 0) {
response = jQuery(resultXml).find(‘c\\:EntityMetadata’);
} else {
response = jQuery(resultXml).find(‘EntityMetadata’); //Chrome 24.0.1312.52 could not find node by the previous code
}

var results = [];
for (var i = 0; i < response.length; i++) {
var a = objectifyNode(response[i]);
a._type = “EntityMetadata”;
results.push(a);
}

if (!async)
return results;
else
callback(results);
// ReSharper disable NotAllPathsReturnValue
});
// ReSharper restore NotAllPathsReturnValue
};

var retrieveEntityMetadata = function (entityFilters, logicalName, retrieveIfPublished, callback) {
///<summary>
/// Sends an synchronous/asynchronous RetreiveEntityMetadata Request to retrieve a particular entity metadata in the system
///</summary>
///<returns>Entity Metadata</returns>
///<param name=”entityFilters” type=”String”>
/// The filter string available to filter which data is retrieved. Case Sensitive filters [Entity,Attributes,Privileges,Relationships]
/// Include only those elements of the entity you want to retrieve in the array. Retrieving all parts of all entities may take significant time.
///</param>
///<param name=”logicalName” type=”String”>
/// The string of the entity logical name
///</param>
///<param name=”retrieveIfPublished” type=”Boolean”>
/// Sets whether to retrieve the metadata that has not been published.
///</param>
///<param name=”callBack” type=”Function”>
/// The function that will be passed through and be called by a successful response.
/// This function also used as an indicator if the function is synchronous/asynchronous
///</param>

entityFilters = isArray(entityFilters) ? entityFilters : [entityFilters];
var entityFiltersString = “”;
for (var iii = 0; iii < entityFilters.length; iii++) {
entityFiltersString += encodeValue(entityFilters[iii]) + ” “;
}

var request = [
“<request i:type=\”a:RetrieveEntityRequest\” xmlns:a=\”http://schemas.microsoft.com/xrm/2011/Contracts\”>”,
“<a:Parameters xmlns:b=\”http://schemas.datacontract.org/2004/07/System.Collections.Generic\”>”,
“<a:KeyValuePairOfstringanyType>”,
“<b:key>EntityFilters</b:key>”,
“<b:value i:type=\”c:EntityFilters\” xmlns:c=\”http://schemas.microsoft.com/xrm/2011/Metadata\”>” + encodeValue(entityFiltersString) + “</b:value>”,
“</a:KeyValuePairOfstringanyType>”,
“<a:KeyValuePairOfstringanyType>”,
“<b:key>MetadataId</b:key>”,
“<b:value i:type=\”c:guid\” xmlns:c=\”http://schemas.microsoft.com/2003/10/Serialization/\”>” + encodeValue(“00000000-0000-0000-0000-000000000000”) + “</b:value>”,
“</a:KeyValuePairOfstringanyType>”,
“<a:KeyValuePairOfstringanyType>”,
“<b:key>RetrieveAsIfPublished</b:key>”,
“<b:value i:type=\”c:boolean\” xmlns:c=\”http://www.w3.org/2001/XMLSchema\”>” + encodeValue(retrieveIfPublished.toString()) + “</b:value>”,
“</a:KeyValuePairOfstringanyType>”,
“<a:KeyValuePairOfstringanyType>”,
“<b:key>LogicalName</b:key>”,
“<b:value i:type=\”c:string\” xmlns:c=\”http://www.w3.org/2001/XMLSchema\”>” + encodeValue(logicalName) + “</b:value>”,
“</a:KeyValuePairOfstringanyType>”,
“</a:Parameters>”,
“<a:RequestId i:nil=\”true\” />”,
“<a:RequestName>RetrieveEntity</a:RequestName>”,
“</request>”].join(“”);

var async = !!callback;

return doRequest(request, “Execute”, async, function (resultXml) {
var response;
if (jQuery(resultXml).find(‘b\\:value’).length != 0) {
response = jQuery(resultXml).find(‘b\\:value’);
} else {
response = jQuery(resultXml).find(‘value’); //Chrome 24.0.1312.52 could not find node by the previous code
}
var results = [];
for (var i = 0; i < response.length; i++) {
var a = objectifyNode(response[i]);
a._type = “EntityMetadata”;
results.push(a);
}

if (!async)
return results;
else
callback(results);
// ReSharper disable NotAllPathsReturnValue
});
// ReSharper restore NotAllPathsReturnValue
};

var retrieveAttributeMetadata = function (entityLogicalName, attributeLogicalName, retrieveIfPublished, callback) {
///<summary>
/// Sends an synchronous/asynchronous RetrieveAttributeMetadata Request to retrieve a particular entity’s attribute metadata in the system
///</summary>
///<returns>Entity Metadata</returns>
///<param name=”entityLogicalName” type=”String”>
/// The string of the entity logical name
///</param>
///<param name=”attributeLogicalName” type=”String”>
/// The string of the entity’s attribute logical name
///</param>
///<param name=”retrieveIfPublished” type=”Boolean”>
/// Sets whether to retrieve the metadata that has not been published.
///</param>
///<param name=”callBack” type=”Function”>
/// The function that will be passed through and be called by a successful response.
/// This function also used as an indicator if the function is synchronous/asynchronous
///</param>

var request = [
“<request i:type=\”a:RetrieveAttributeRequest\” xmlns:a=\”http://schemas.microsoft.com/xrm/2011/Contracts\”>”,
“<a:Parameters xmlns:b=\”http://schemas.datacontract.org/2004/07/System.Collections.Generic\”>”,
“<a:KeyValuePairOfstringanyType>”,
“<b:key>EntityLogicalName</b:key>”,
“<b:value i:type=\”c:string\” xmlns:c=\”http://www.w3.org/2001/XMLSchema\”>” + encodeValue(entityLogicalName) + “</b:value>”,
“</a:KeyValuePairOfstringanyType>”,
“<a:KeyValuePairOfstringanyType>”,
“<b:key>MetadataId</b:key>”,
“<b:value i:type=\”ser:guid\” xmlns:ser=\”http://schemas.microsoft.com/2003/10/Serialization/\”>” + encodeValue(“00000000-0000-0000-0000-000000000000”) + “</b:value>”,
“</a:KeyValuePairOfstringanyType>”,
“<a:KeyValuePairOfstringanyType>”,
“<b:key>RetrieveAsIfPublished</b:key>”,
“<b:value i:type=\”c:boolean\” xmlns:c=\”http://www.w3.org/2001/XMLSchema\”>” + encodeValue(retrieveIfPublished.toString()) + “</b:value>”,
“</a:KeyValuePairOfstringanyType>”,
“<a:KeyValuePairOfstringanyType>”,
“<b:key>LogicalName</b:key>”,
“<b:value i:type=\”c:string\” xmlns:c=\”http://www.w3.org/2001/XMLSchema\”>” + encodeValue(attributeLogicalName) + “</b:value>”,
“</a:KeyValuePairOfstringanyType>”,
“</a:Parameters>”,
“<a:RequestId i:nil=\”true\” />”,
“<a:RequestName>RetrieveAttribute</a:RequestName>”,
“</request>”].join(“”);

var async = !!callback;

return doRequest(request, “Execute”, async, function (resultXml) {
var response;
if (jQuery(resultXml).find(‘b\\:value’).length != 0) {
response = jQuery(resultXml).find(‘b\\:value’);
} else {
response = jQuery(resultXml).find(‘value’); //Chrome 24.0.1312.52 could not find node by the previous code
}
var results = [];
for (var i = 0; i < response.length; i++) {
var a = objectifyNode(response[i]);
results.push(a);
}

if (!async)
return results;
else
callback(results);
// ReSharper disable NotAllPathsReturnValue
});
// ReSharper restore NotAllPathsReturnValue
};

//Toolkit’s Return Static Methods
return {
BusinessEntity: businessEntity,
Execute: execute,
Fetch: fetch,
Retrieve: retrieve,
RetrieveMultiple: retrieveMultiple,
Create: sCreate,
Update: sUpdate,
Delete: sDelete,
QueryByAttribute: queryByAttribute,
QueryAll: queryAll,
SetState: setState,
Associate: associate,
Disassociate: disassociate,
Assign: assign,
RetrievePrincipalAccess: retrievePrincipalAccess,
GrantAccess: grantAccess,
ModifyAccess: modifyAccess,
RevokeAccess: revokeAccess,
GetCurrentUserId: getCurrentUserId,
GetCurrentUserBusinessUnitId: getCurrentUserBusinessUnitId,
GetCurrentUserRoles: getCurrentUserRoles,
IsCurrentUserRole: isCurrentUserInRole,
RetrieveAllEntitiesMetadata: retrieveAllEntitiesMetadata,
RetrieveEntityMetadata: retrieveEntityMetadata,
RetrieveAttributeMetadata: retrieveAttributeMetadata
};
} ();

XrmServiceToolkit.Extension = function () {
// jQuery Load Help function to add tooltip for attribute in CRM 2011. Unsupported because of the usage of DOM object edit.
//****************************************************
var jQueryXrmFieldTooltip = function (filename, bDisplayImg) {
///<summary>
/// A generic configurable method to add tooltip to crm 2011 field.
///</summary>
///<param name=”filename” type=”String”>
/// A JavaScript String corresponding the name of the configuration web resource name in CRM 2011 instance
/// </param>
///<param name=”bDisplayImg” type=”boolean”>
/// A JavaScript boolean corresponding if display a help image for the tooltip
/// </param>

/*
This function is used add tooltips to any field in CRM2011.

This function requires the following parameters:
filename : name of the XML web resource
bDisplayImg: boolean to show/hide the help image (true/false)
Returns: nothing
Example: jQueryLoadHelp(‘cm_xmlhelpfile’, true);
Designed by: http://lambrite.com/?p=221
Adapted by Geron Profet (www.crmxpg.nl), Jaimie Ji
Modified by Jaimie Ji with jQuery and cross browser
*/

if (Xrm.Page.ui.setFormNotification !== undefined) {
alert(‘XrmServiceToolkit.Extension.JQueryXrmFieldTooltip is not supported in CRM2013.\nPlease use the out of box functionality’);
return;
}

if (typeof jQuery === ‘undefined’) {
alert(‘jQuery is not loaded.\nPlease ensure that jQuery is included\n as web resource in the form load.’);
return;
}

jQuery.support.cors = true;

jQuery.ajax({
type: “GET”,
url: “../WebResources/” + filename,
dataType: “xml”,
success: parseHelpXml,
// ReSharper disable UnusedParameter
error: function (xmlHttpRequest, textStatus, errorThrown) {
// ReSharper restore UnusedParameter
alert(‘Something is wrong to setup the tooltip for the fields. Please contact your administrator’);
}
}); //end Ajax

//****************************************************
function parseHelpXml(data) {
var entity = Xrm.Page.data.entity.getEntityName().toString().toLowerCase();
var entXml = jQuery(“entity[name=” + entity + “]”, data);
jQuery(entXml).children().each(function () {
var attr = jQuery(this).attr(‘name’);
var txt = jQuery(this).find(‘shorthelp’).text();
registerHelp(entity, attr, txt);
});
}
//****************************************************
function registerHelp(entity, attr, txt) {
var obj = jQuery(‘#’ + attr + ‘_c’).children(‘:first’);
if (obj != null) {
var html = ‘<img id=”img_’ + attr + ‘” src=”/_imgs/ico/16_help.gif” alt=”‘ + txt + ‘” width=”16″ height=”16″ /><div id=”help_’ + attr + ‘” style=”visibility: hidden; position: absolute;”>: ‘ + txt + ‘</div>’;
jQuery(obj).append(html);
//20110909 GP: added line to hide/show help image
jQuery(‘#img_’ + attr).css(‘display’, (bDisplayImg) ? ‘inline’ : ‘none’);
}
}
};

// Generic Dependent Option Set Function. Changed from CRM 2011 SDK example
var jQueryXrmDependentOptionSet = function (filename) {
///<summary>
/// A generic configurable method to configure dependent optionset for CRM 2011 instance
///</summary>
///<param name=”filename” type=”String”>
/// A JavaScript String corresponding the name of the configuration web resource name in CRM 2011 instance
/// </param>
if (typeof jQuery === ‘undefined’) {
alert(‘jQuery is not loaded.\nPlease ensure that jQuery is included\n as web resource in the form load.’);
return;
}

jQuery.support.cors = true;

jQuery.ajax({
type: “GET”,
url: “../WebResources/” + filename,
dataType: “xml”,
success: init,
// ReSharper disable UnusedParameter
error: function (xmlHttpRequest, textStatus, errorThrown) {
// ReSharper restore UnusedParameter
alert(‘Something is wrong to setup the dependent picklist. Please contact your administrator’);
}
}); //end Ajax

function init(data) {
var entity = Xrm.Page.data.entity.getEntityName().toString().toLowerCase();
var configWr = jQuery(“entity[name=” + entity + “]”, data);

//Convert the XML Data into a JScript object.
var parentFields = configWr.children(“ParentField”);
var jsConfig = [];
for (var i = 0; i < parentFields.length; i++) {
var node = parentFields[i];
var mapping = {};
mapping.parent = jQuery(node).attr(“id”);
mapping.dependent = jQuery(node).children(“DependentField:first”).attr(“id”);
mapping.options = [];
var options = jQuery(node).children(“Option”);
for (var a = 0; a < options.length; a++) {
var option = {};
option.value = jQuery(options[a]).attr(“value”);
option.showOptions = [];
var optionsToShow = jQuery(options[a]).children(“ShowOption”);
for (var b = 0; b < optionsToShow.length; b++) {
var optionToShow = {};
optionToShow.value = jQuery(optionsToShow[b]).attr(“value”);
optionToShow.text = jQuery(optionsToShow[b]).attr(“label”); // Label is not used in the code.

option.showOptions.push(optionToShow);
}
mapping.options.push(option);
}
jsConfig.push(mapping);
}
// Attach the configuration object to jQueryXrmDependentOptionSet
// so it will be available for the OnChange events.
jQueryXrmDependentOptionSet.config = jsConfig;

//Fire the OnChange event for the mapped optionset fields
// so that the dependent fields are filtered for the current values.
for (var depOptionSet in jQueryXrmDependentOptionSet.config) {
var parent = jQueryXrmDependentOptionSet.config[depOptionSet].parent;
var child = jQueryXrmDependentOptionSet.config[depOptionSet].dependent;
filterDependentField(parent, child, jQueryXrmDependentOptionSet);
}
}

// This is the function set on the OnChange event for
// parent fields.
// ReSharper disable DuplicatingLocalDeclaration
function filterDependentField(parentField, childField, jQueryXrmDependentOptionSet) {
// ReSharper restore DuplicatingLocalDeclaration
for (var depOptionSet in jQueryXrmDependentOptionSet.config) {
var dependentOptionSet = jQueryXrmDependentOptionSet.config[depOptionSet];
/* Match the parameters to the correct dependent optionset mapping*/
if ((dependentOptionSet.parent === parentField) && (dependentOptionSet.dependent === childField)) {
/* Get references to the related fields*/
var parent = Xrm.Page.data.entity.attributes.get(parentField);
var child = Xrm.Page.data.entity.attributes.get(childField);

var parentControl = Xrm.Page.getControl(parentField);
var childControl = Xrm.Page.getControl(childField);
/* Capture the current value of the child field*/
var currentChildFieldValue = child.getValue();

/* If the parent field is null the Child field can be set to null */
var controls;
var ctrl;
if (parent.getValue() === null) {
child.setValue(null);
child.setSubmitMode(“always”);
child.fireOnChange();

// Any attribute may have any number of controls,
// so disable each instance.
controls = child.controls.get();
for (ctrl in controls) {
controls[ctrl].setDisabled(true);
}
return;
}

for (var os in dependentOptionSet.options) {
var options = dependentOptionSet.options[os];
var optionsToShow = options.showOptions;
/* Find the Options that corresponds to the value of the parent field. */
if (parent.getValue() === options.value) {
controls = child.controls.get(); /*Enable the field and set the options*/
for (ctrl in controls) {
controls[ctrl].setDisabled(false);
controls[ctrl].clearOptions();

for (var option in optionsToShow) {
controls[ctrl].addOption(optionsToShow[option]);
}
}
/*Check whether the current value is valid*/
var bCurrentValueIsValid = false;
var childFieldOptions = optionsToShow;

for (var validOptionIndex in childFieldOptions) {
var optionDataValue = childFieldOptions[validOptionIndex].value;

if (currentChildFieldValue === optionDataValue) {
bCurrentValueIsValid = true;
break;
}
}
/*
If the value is valid, set it.
If not, set the child field to null
*/
if (bCurrentValueIsValid) {
child.setValue(currentChildFieldValue);
}
else {
child.setValue(null);
}
child.setSubmitMode(“always”);
child.fireOnChange();

if (parentControl.getDisabled() === true) {
childControl.setDisabled(true);
}
break;
}
}
}
}
}
};

var jQueryXrmCustomFilterView = function (filename) {
///<summary>
/// A generic configurable method to add custom filter view to lookup field in crm 2011 instance
///</summary>
///<param name=”filename” type=”String”>
/// A JavaScript String corresponding the name of the configuration web resource name in CRM 2011 instance
/// </param>
if (typeof jQuery === ‘undefined’) {
alert(‘jQuery is not loaded.\nPlease ensure that jQuery is included\n as web resource in the form load.’);
return;
}

jQuery.support.cors = true;

jQuery.ajax({
type: “GET”,
url: “../WebResources/” + filename,
dataType: “xml”,
success: init,
// ReSharper disable UnusedParameter
error: function (xmlHttpRequest, textStatus, errorThrown) {
// ReSharper restore UnusedParameter
alert(‘Something is wrong to setup the custom filter view. Please contact your administrator’);
}
}); //end Ajax

function init(data) {
var entity = Xrm.Page.data.entity.getEntityName().toString().toLowerCase();
var configWr = jQuery(“entity[name=” + entity + “]”, data);

//Convert the XML Data into a JScript object.
var targetFields = configWr.children(“TargetField”);
var jsConfig = [];
for (var i = 0; i < targetFields.length; i++) {
var node = targetFields[i];
var mapping = {};
mapping.target = jQuery(node).attr(“id”);
mapping.entityName = jQuery(node).attr(“viewentity”);
mapping.viewName = jQuery(node).attr(“viewname”);
mapping.dynamic = jQuery(node).children(“dynamic”).children();
mapping.fetchXml = xmlToString(jQuery(node).children(“fetch”));
mapping.layoutXml = xmlToString(jQuery(node).children(“grid”));

jsConfig.push(mapping);
}
// Attach the configuration object to JQueryCustomFilterView
// so it will be available for the OnChange events.
jQueryXrmCustomFilterView.config = jsConfig;

//Fire the OnChange event for the mapped fields
// so that the lookup dialog are changed with the filtered view for the current values.
for (var customFilterView in jQueryXrmCustomFilterView.config) {
var target = jQueryXrmCustomFilterView.config[customFilterView].target;
var entityName = jQueryXrmCustomFilterView.config[customFilterView].entityName;
var viewName = jQueryXrmCustomFilterView.config[customFilterView].viewName;
var dynamic = jQueryXrmCustomFilterView.config[customFilterView].dynamic;
var fetchXml = jQueryXrmCustomFilterView.config[customFilterView].fetchXml;
var layoutXml = jQueryXrmCustomFilterView.config[customFilterView].layoutXml;

//TODO: Adding logics for various field and conditions. More tests required.
if (dynamic != null) {
for (var a = 0; a < dynamic.length; a++) {
var dynamicControlType = Xrm.Page.getControl(jQuery(dynamic).attr(‘name’)).getControlType();
var fieldValueType = jQuery(dynamic).attr(‘fieldvaluetype’); //for optionset, name might be used to filter
if (Xrm.Page.getAttribute(jQuery(dynamic).attr(‘name’)).getValue() === null) {
alert(jQuery(dynamic).attr(‘name’) + ‘ does not have a value. Please put validation logic on the field change to call this function. Only use XrmServiceToolkit.Extension.JQueryXrmCustomFilterView when the field has a value.’);
return;
}
var dynamicValue = null;
switch (dynamicControlType) {
case ‘standard’:
dynamicValue = Xrm.Page.getAttribute(jQuery(dynamic).attr(‘name’)).getValue();
break;
case ‘optionset’:
dynamicValue = (fieldValueType != null && fieldValueType === ‘label’) ? Xrm.Page.getAttribute(jQuery(dynamic).attr(‘name’)).getSelectionOption().text : Xrm.Page.getAttribute(jQuery(dynamic).attr(‘name’)).getValue();
break;
case ‘lookup’:
dynamicValue = (fieldValueType != null && fieldValueType === ‘name’) ? Xrm.Page.getAttribute(jQuery(dynamic).attr(‘name’)).getValue()[0].name : Xrm.Page.getAttribute(jQuery(dynamic).attr(‘name’)).getValue()[0].id;
break;
default:
alert(jQuery(dynamic).attr(‘name’) + ” is not supported for filter lookup view. Please change the configuration.”);
break;
}

var operator = jQuery(dynamic).attr(‘operator’);
if (operator === null) {
alert(‘operator is missing in the configuration file. Please fix the issue’);
return;
}
var dynamicString = jQuery(dynamic).attr(‘fetchnote’);
switch (operator.toLowerCase()) {
case ‘contains’:
case ‘does not contain’:
dynamicValue = ‘%’ + dynamicValue + ‘%’;
break;
case ‘begins with’:
case ‘does not begin with’:
dynamicValue = dynamicValue + ‘%’;
break;
case ‘ends with’:
case ‘does not end with’:
dynamicValue = ‘%’ + dynamicValue;
break;
default:
dynamicValue = dynamicValue;
break;
}

fetchXml = fetchXml.replace(dynamicString, dynamicValue);
}
}

//replace the values if required
setCustomFilterView(target, entityName, viewName, fetchXml, layoutXml);
}
}

function setCustomFilterView(target, entityName, viewName, fetchXml, layoutXml) {
// use randomly generated GUID Id for our new view
var viewId = “{1DFB2B35-B07C-44D1-868D-258DEEAB88E2}”;

// add the Custom View to the indicated [lookupFieldName] Control
Xrm.Page.getControl(target).addCustomView(viewId, entityName, viewName, fetchXml, layoutXml, true);
}

function xmlToString(xmlData) {
var xmlString = ”;
try {
if (xmlData != null && xmlData.length > 0) {
//IE
if (window.ActiveXObject) {
xmlString = xmlData[0].xml;
}
// code for Mozilla, Firefox, Opera, etc.
else {
// ReSharper disable InconsistentNaming
xmlString = (new XMLSerializer()).serializeToString(xmlData[0]);
// ReSharper restore InconsistentNaming
}
return xmlString;
}
} catch (e) {
alert(“Cannot convert the XML to a string.”);
}
return xmlString;
}
};

// Disable or Enable to insert/edit note for entity. Unsupported because of DOM object edit
var jQueryXrmFormatNotesControl = function (allowInsert, allowEdit) {
///<summary>
/// A generic configurable method to format the note control in crm 2011 instance
///</summary>
///<param name=”allowInsert” type=”Boolean”>
/// A JavaScript boolean to format if the note control allow insert
/// </param>
///<param name=”allowEdit” type=”Boolean”>
/// A JavaScript boolean to format if the note control allow edit
/// </param>

if (Xrm.Page.ui.setFormNotification !== undefined) {
alert(‘XrmServiceToolkit.Extension.JQueryXrmFormatNotesControl is not supported in CRM2013’);
return;
}

if (typeof jQuery === ‘undefined’) {
alert(‘jQuery is not loaded.\nPlease ensure that jQuery is included\n as web resource in the form load.’);
return;
}

jQuery.support.cors = true;

var notescontrol = jQuery(‘#notescontrol’);
if (notescontrol === null || notescontrol === undefined) return;
var url = notescontrol.attr(‘url’);
//if (url === null) return;
if (url != null) {
if (!allowInsert) {
url = url.replace(“EnableInsert=true”, “EnableInsert=false”);
}
else if (!allowEdit) {
url = url.replace(“EnableInlineEdit=true”, “EnableInlineEdit=false”);
}
notescontrol.attr(‘url’, url);
} else {
var src = notescontrol.attr(‘src’);
if (src != null) {
if (!allowInsert) {
src = src.replace(“EnableInsert=true”, “EnableInsert=false”);
}
else if (!allowEdit) {
src = src.replace(“EnableInlineEdit=true”, “EnableInlineEdit=false”);
}
notescontrol.attr(‘src’, src);
}
}
};

// Toolkit’s public static members
return {
JQueryXrmFieldTooltip: jQueryXrmFieldTooltip,
JQueryXrmDependentOptionSet: jQueryXrmDependentOptionSet,
JQueryXrmCustomFilterView: jQueryXrmCustomFilterView,
JQueryXrmFormatNotesControl: jQueryXrmFormatNotesControl
};
} ();

Image

1) When you select Account it will fetch the account related opporuntiy in opportuity lookup.

2) Same way when you select oppotunity it will fetch the Account data which are related to opporunity.

3)In Subgrid opportunity related sub opportuinities will be displayed..

 

 

/// <reference path=”XrmPageTemplate.js” />/// <reference path=”json2.js” />/// <reference path=”jquery.js” />
/**
* MSCRM 2011 Web Service Toolkit for JavaScript* @author Jaimie Ji* @author David Berry* @current version : 2.0.0 (beta)
* Credits:*   The idea of this library was inspired by Daniel Cai’s CrmWebServiceToolkit.*   The idea of BusinessEntity was inspired by Daniel Cai && Ascentium CrmService JavaScript Library.*   The REST Endpoint functions were inspired by MSCRM 2011 SDK JavaScript code and various resources from CRM websites and forums. Some of them were just copies with minor modification.*   The Soap functions were inspired by Daniel Cai && Jamie Miley && Paul Way && Customer Effective.*   Additional thanks to all contributors of MSCRM and i have learned a lot from you all.* Date: February, 2012** Special Thanks:*   JetBrains ReSharper Open License* Date: July, 2012** What’s new:***********************************************************************************************************   Version: 1.1*   Date: April, 2012*       Dependency: JSON2*       New Function – XrmServiceToolkit.Soap.Assign*       New Function – XrmServiceToolkit.Soap.GrantAccess*       New Function – XrmServiceToolkit.Soap.ModifyAccess*       New Function – XrmServiceToolkit.Soap.GrantAccess*       New Function – XrmServiceToolkit.Soap.RetrievePrincipalAccess***********************************************************************************************************   Version: 1.2*   Date: April, 2012*       Dependency: JSON2*       New Fix – Fix soaps functions to create/update/retrieve activities with Party List fields.***********************************************************************************************************   Version: 1.3*   Date: July, 2012*       Dependency: JSON2, jQuery (latest or 1.7.2 above)*       New Feature: cross browser support. jQuery Integration.*       New Extension: A new category of functions to extend some functions:*          1. JQueryXrmDependentOptionSet: Create Configurable Dependent Option Set to utilize CRM 2011 web resource.*          2. JQueryXrmFieldTooltip: Create configurable tooltip for fields on CRM 2011 form*          3. JQueryXrmCustomFilterView: Create configurable ability to add custom filter view to crm 2011 lookup field on the form*          4. JQueryXrmFormatNotesControl: Format the notes control to allow insert, allow edit***********************************************************************************************************   Version: 1.3.1*   Date: November, 2012*       Dependency: JSON2, jQuery (latest or 1.7.2 above)*       New Feature – A change of logic to increase performance when returning large number of records*       New Function – XrmServiceToolkit.Soap.QueryAll: Return all available records by query options (>5k+)*       New Fix – XrmServiceToolkit.Rest.RetrieveMultiple not returning records more than 50*       New Fix – XrmServiceToolkit.Soap.Business error when referring number fields like (int, double, float)     *       New Fix – XrmServiceToolkit.Soap not handling error message properly***********************************************************************************************************   Version: 1.3.2*   Date: January, 2013*       Dependency: JSON2, jQuery (latest or 1.7.2 above)  *       New Fix – XrmServiceToolkit.Soap cross browser support to initialize soap service***********************************************************************************************************   Version: 1.4.0 *   Date: January, 2013*       Dependency: JSON2, jQuery (latest or 1.7.2 above)  *       Feature: Add Cross Browser Support for RU12*       Tested Platform: IE9, IE10, Chrome Version 24.0.1312.56 m, Firefox 18.0.1***********************************************************************************************************   Version: 1.4.1*   Date: April, 2013*       Dependency: JSON2, jQuery (latest or 1.7.2 above)  *       Tested Platform: IE9, IE10, Chrome Version 26.0.1410.64 m, Firefox 20.0.1*       Feature: Add Cross Browser Support for RU12, RU13*       New Fix – XrmServiceToolkit.Common.AddNotification method updated for RU12, RU13, still compatible for RU11 below*       New Fix – XrmServiceToolkit.Soap.Fetch method did not format linked record correctly*       New Fix – XrmServiceToolkit.Soap.Retrieve method did not return partylist data for activity*       New Fix – Added manual conversion from String to Date conversion for cross browser*       New Fix – getServerUrl method is updated as getClientUrl to align with RU12 SDK method getClientUrl(), still compatible to support RU11 below*       New Function – getServerUrl private method is updated as getClientUrl to align with RU12 SDK method getClientUrl(), still compatible to support RU11 below*       New Function – XrmServiceToolkit.Soap.RetrieveAllEntitiesMetadata method is a method to return all metadata for all entities by the specified entity filters*       New Function – XrmServiceToolkit.Soap.RetrieveEntityMetadata method is a method to return the metadata for a certain entity by the specified entity filters*       New Function – XrmServiceToolkit.Soap.RetrieveAttributeMetadata method is a method to return the metadata for a certain entity’s attribute***********************************************************************************************************   Version: 1.4.2 (beta)*   Date: May, 2013*       Dependency: JSON2, jQuery (latest or 1.7.2 above)*       Tested Platform: IE10*       New Fix – XrmServiceToolkit.Soap.Fetch now takes an additional parameter, ‘fetchAll’, that when set to true will retrieve all pages of results*       New Behavior – XrmServiceToolkit.Soap.Fetch works best when providing a FetchXML string starting with the “entity” node, because of the way paging works;*           It will still function with the traditional “fetch” node to start, but then the XML has to be parsed to select just the “entity” node, which adds some overhead.*       New Behavior – XrmServiceToolkit fetch and queryall methods use a unified model, and some redundant code has been removed.  This allows better paging operations.************************************************************************************************************   Version: 2.0.0 (beta)*   Date: October, 2013*       Dependency: JSON2, jQuery (latest or 1.7.2 above)*       —NOTE—Due to the changes for CRM 2013, please use the attached version of JSON2 and jQuery*       Tested Platform: IE10, latest Chrome, latest FireFox*    Changes:*       New Behavior – XrmServiceTookit.Soap.Fetch parameters change to work with asynchronous callback compared to 1.4.2 beta: XrmServiceToolkit.Soap.Fetch(fetchXml, fetchAll, callback)*       New Behavior – XrmServiceTookit.Soap.AddNotification is working with CRM 2013 using the out-of-box functionality. Still support CRM 2011*       New Fix – XrmServiceToolkit.Comon.GetObjectCodeType is now using metadata retrieval as a supported method*       New Fix – The included jQuery has a line changed at the bottom <window.jQuery = jQuery;> $ is removed to work with CRM 2013 form*   Beta Release for CRM 2013***********************************************************************************************************/
XrmServiceToolkit = function () {    /// <summary>    /// XrmServiceToolkit.Common for common functions.    /// XrmServiceToolkit.Rest for all REST endpoints functions.    /// XrmServiceToolkit.Soap for all Soap functions.    /// XrmServiceToolkit.Extension for all Extension functions.    /// </summary>};
XrmServiceToolkit.Common = function () {    var guidsAreEqual = function (guid1, guid2) {        /// <summary>        /// Check if two guids are equal        /// </summary>        /// <param name=”guid1″ type=”string”>        /// A string represents a guid        /// </param>        /// <param name=”guid2″ type=”string”>        /// A string represents a guid        /// </param>        /// <returns type=”boolean” />        var isEqual;        if (guid1 === null || guid2 === null || guid1 === undefined || guid2 === undefined) {            isEqual = false;        }        else {            isEqual = guid1.replace(/[{}]/g, “”).toLowerCase() === guid2.replace(/[{}]/g, “”).toLowerCase();        }
        return isEqual;    };
    var enableField = function (fieldName) {        /// <summary>        /// Enable a field by the name        /// </summary>        /// <param name=”fieldName” type=”string”>        /// The name of the field to be enabled        /// </param>        /// <returns type=”void” />        Xrm.Page.getControl(fieldName).setDisabled(false);    };
    var disableField = function (fieldName) {        /// <summary>        /// Disable a field by the name        /// </summary>        /// <param name=”fieldName” type=”string”>        /// The name of the field to be disabled        /// </param>        /// <returns type=”void” />        Xrm.Page.getControl(fieldName).setDisabled(true);    };
    var showField = function (fieldName) {        /// <summary>        /// Show a field by the name        /// </summary>        /// <param name=”fieldName” type=”string”>        /// The name of the field to be shown        /// </param>        /// <returns type=”void” />        Xrm.Page.getControl(fieldName).setVisible(true);    };
    var hideField = function (fieldName) {        /// <summary>        /// Hide a field by the name        /// </summary>        /// <param name=”fieldName” type=”string”>        /// The name of the field to be hidden        /// </param>        /// <returns type=”void” />        Xrm.Page.getControl(fieldName).setVisible(false);    };
    var updateRequirementLevel = function (fieldName, levelName) {        /// <summary>        /// Updates the requirement level of a field        /// </summary>        /// <param name=”fieldName” type=”string”>        /// Name of the field        /// </param>        /// <param name=”levelName” type=”string”>        /// Name of the requirement level. [none, recommended, required] (Case Sensitive)        /// </param>        /// <returns type=”void” />        Xrm.Page.getAttribute(fieldName).setRequiredLevel(levelName);    };
    var showError = function (error) {        /// <summary>        /// Alert the error message if occurred        /// </summary>        /// <param name=”error” type=”error”>        /// Object of the JavaScript error        /// </param>        /// <returns type=”void” />        alert(error.message);    };
    var getObjectTypeCode = function (entityName) {        /// <summary>        /// Gets the EntityTypeCode / ObjectTypeCode of a entity        /// </summary>        /// <param name=”entityName” type=”string”>        /// Name of entity to return object type code of        /// </param>        /// <returns type=”int” />        try {            var entityMetaData = XrmServiceToolkit.Soap.RetrieveEntityMetadata(“Entity”, entityName, false);            if (entityMetaData && entityMetaData.length === 1) {                return entityMetaData[0].ObjectTypeCode;            } else {                return null;            }        } catch (e) {            showError(e.message);            return null;        }    };
    var addNotification = function (message, level, uniqueId) {        /// <summary>        /// Add a notification bar message with CRM 2011 style        /// </summary>        /// <param name=”message” type=”string”>        /// Details of the message        /// </param>        /// <param name=”level” type=”int”>        /// The warning level of the message: [1 critical, 2 information, 3 warning]        /// </param>        /// <param name=”uniqueId” type=”string”>        /// A unique identifier for the message used with clearFormNotification to remove the notification.        /// </param>        /// <returns type=”void” />        if (Xrm.Page.ui.setFormNotification !== undefined) {            // CRM 2013            if (!!uniqueId) {                Xrm.Page.ui.clearFormNotification(uniqueId);                if (level === 1) {                    //Error                    Xrm.Page.ui.setFormNotification(message, “ERROR”, uniqueId);                }                if (level === 2) {                    //Info                    Xrm.Page.ui.setFormNotification(message, “INFO”, uniqueId);                }                if (level === 3) {                    //Warning                    Xrm.Page.ui.setFormNotification(message, “WARNING”, uniqueId);                }            } else {                var tempUniqueId = “formNotification00”;                Xrm.Page.ui.clearFormNotification(tempUniqueId);                if (level === 1) {                    //Error                    Xrm.Page.ui.setFormNotification(message, “ERROR”, tempUniqueId);                }                if (level === 2) {                    //Info                    Xrm.Page.ui.setFormNotification(message, “INFO”, tempUniqueId);                }                if (level === 3) {                    //Warning                    Xrm.Page.ui.setFormNotification(message, “WARNING”, tempUniqueId);                }            }               }        else {            var notificationsArea = document.getElementById(‘crmNotifications’);            if (notificationsArea === null || notificationsArea === undefined) {                alert(‘Cannot find the notification area’); return;            }            if (typeof notificationsArea.AddNotification !== “undefined” && typeof notificationsArea.control.AddNotification !== “undefined”) {                alert(‘Add Notification is no longer supported’); return;            }            if (level === 1) {                //critical                if (typeof notificationsArea.AddNotification !== “undefined”) {                    notificationsArea.AddNotification(‘mep1’, 1, ‘source’, message);                } else if (typeof notificationsArea.control.AddNotification !== “undefined”) {                    notificationsArea.control.AddNotification(‘mep1’, 1, ‘source’, message);                }            }
            if (level === 2) {                //Info                if (typeof notificationsArea.AddNotification !== “undefined”) {                    notificationsArea.AddNotification(‘mep3’, 3, ‘source’, message);                } else if (typeof notificationsArea.control.AddNotification !== “undefined”) {                    notificationsArea.control.AddNotification(‘mep3’, 3, ‘source’, message);                }            }            if (level === 3) {                //Warning                if (typeof notificationsArea.AddNotification !== “undefined”) {                    notificationsArea.AddNotification(‘mep2’, 2, ‘source’, message);                } else if (typeof notificationsArea.control.AddNotification !== “undefined”) {                    notificationsArea.control.AddNotification(‘mep2’, 2, ‘source’, message);                }            }            if (message === “”) {                if (typeof notificationsArea.SetNotifications !== “undefined”) {                    notificationsArea.SetNotifications(null, null);                } else if (typeof notificationsArea.control.SetNotifications !== “undefined”) {                    notificationsArea.control.SetNotifications(null, null);                } else {                    alert(‘Set Notification is no longer supported’);                }            }        }         };
    var addControlNotification = function(attributeName, message) {        if (Xrm.Page.getControl(attributeName).setNotification !== undefined) {            Xrm.Page.getControl(attributeName).setNotification(message);        }    };
    var calculateDaysBetween = function (datetime1, datetime2) {        /// <summary>        /// Calculate the days between two dates        /// </summary>        /// <param name=”datetime1″ type=”DateTime”>        /// The first / early date to be calculated        /// </param>        /// <param name=”datetime2″ type=”DateTime”>        /// The second / later date to e calculated        /// </param>        /// <returns type=”int” />
        // The number of milliseconds in one day        var oneDay = 1000 * 60 * 60 * 24;
        // Convert both dates to milliseconds        var date1Ms = datetime1.getTime();        var date2Ms = datetime2.getTime();
        // Calculate the difference in milliseconds        var differenceMs = Math.abs(date1Ms – date2Ms); // Convert back to days and return        return Math.round(differenceMs / oneDay);    };
    var disableAllControlsInTab = function (tabControlNo) {        /// <summary>        /// Disable all controls in a tab by tab number.        /// </summary>        /// <param name=”tabControlNo” type=”int”>        /// The number of the tab        /// </param>        /// <returns type=”void” />        var tabControl = Xrm.Page.ui.tabs.get(tabControlNo);        if (tabControl != null) {            Xrm.Page.ui.controls.forEach(             function (control) {                 if (control.getParent().getParent() === tabControl && control.getControlType() != “subgrid”) {                     control.setDisabled(true);                 }             });        }    };
    var disableAllControlsInSection = function (sectionLabel) {        /// <summary>        /// Disable all controls in a section by section label.        /// </summary>        /// <param name=”sectionLabel” type=”string”>        /// The label of the section        /// </param>        /// <returns type=”void” />        var tabs = Xrm.Page.ui.tabs;        for (var i = 0; i < tabs.getLength(); i++) {            var tab = tabs.get(i);            var sections = tab.sections;            for (var j = 0; j < sections.getLength(); j++) {                var section = sections.get(j);                if (section.getLabel().toLowerCase() === sectionLabel.toLowerCase()) {                    Xrm.Page.ui.controls.forEach(                        function (control) {                            if (control.getParent().getLabel() === sectionLabel && control.getControlType() != “subgrid”) {                                control.setDisabled(true);                            }                        });                    break;                }            }        }    };
    // Toolkit’s public static members    return {        EnableField: enableField,        DisableField: disableField,        ShowField: showField,        HideField: hideField,        UpdateRequiredLevel: updateRequirementLevel,        GetObjectTypeCode: getObjectTypeCode,        CalculateDaysBetween: calculateDaysBetween,        AddNotification: addNotification,        AddControlNotification: addControlNotification,        ShowError: showError,        GuidsAreEqual: guidsAreEqual,        DisableAllControlsInTab: disableAllControlsInTab,        DisableAllControlsInSection: disableAllControlsInSection    };} ();
XrmServiceToolkit.Rest = function () {    // Private members    var htmlEncode = function (s) {        if (s === null || s === “” || s === undefined) return s;        for (var count = 0, buffer = “”, hEncode = “”, cnt = 0; cnt < s.length; cnt++) {            var c = s.charCodeAt(cnt);            if (c > 96 && c < 123 || c > 64 && c < 91 || c === 32 || c > 47 && c < 58 || c === 46 || c === 44 || c === 45 || c === 95)                buffer += String.fromCharCode(c);            else buffer += “&#” + c + “;”;            if (++count === 500) {                hEncode += buffer; buffer = “”; count = 0;            }        }        if (buffer.length) hEncode += buffer;        return hEncode;    };
    var innerSurrogateAmpersandWorkaround = function (s) {        var buffer = ”;        var c0;        for (var cnt = 0; cnt < s.length; cnt++) {            c0 = s.charCodeAt(cnt);            if (c0 >= 55296 && c0 <= 57343)                if (cnt + 1 < s.length) {                    var c1 = s.charCodeAt(cnt + 1);                    if (c1 >= 56320 && c1 <= 57343) {                        buffer += “CRMEntityReferenceOpen” + ((c0 – 55296) * 1024 + (c1 & 1023) + 65536).toString(16) + “CRMEntityReferenceClose”; cnt++;                    }                    else                        buffer += String.fromCharCode(c0);                }                else buffer += String.fromCharCode(c0);            else buffer += String.fromCharCode(c0);        }        s = buffer;        buffer = “”;        for (cnt = 0; cnt < s.length; cnt++) {            c0 = s.charCodeAt(cnt);            if (c0 >= 55296 && c0 <= 57343)                buffer += String.fromCharCode(65533);            else buffer += String.fromCharCode(c0);        }        s = buffer;        s = htmlEncode(s);        s = s.replace(/CRMEntityReferenceOpen/g, “&#x”);        s = s.replace(/CRMEntityReferenceClose/g, “;”);        return s;    };
    // ReSharper disable UnusedLocals    var crmXmlEncode = function (s) {        // ReSharper restore UnusedLocals        // ReSharper disable UsageOfPossiblyUnassignedValue        // ReSharper disable ExpressionIsAlwaysConst        if (‘undefined’ === typeof s || ‘unknown’ === typeof s || null === s) return s;        // ReSharper restore ExpressionIsAlwaysConst        // ReSharper restore UsageOfPossiblyUnassignedValue        else if (typeof s != “string”) s = s.toString();        return innerSurrogateAmpersandWorkaround(s);    };
    // ReSharper disable UnusedLocals    var crmXmlDecode = function (s) {        // ReSharper restore UnusedLocals        if (typeof s != “string”) s = s.toString();        return s;    };
    var context = function () {        ///<summary>        /// Private function to the context object.        ///</summary>        ///<returns>Context</returns>        var oContext;        if (typeof window.GetGlobalContext != “undefined”) {            oContext = window.GetGlobalContext();        }        else {            if (typeof Xrm != “undefined”) {                oContext = Xrm.Page.context;            }            else if (typeof window.parent.Xrm != “undefined”) {                oContext = window.parent.Xrm.Page.context;            }            else {                throw new Error(“Context is not available.”);            }        }        return oContext;    };
    var getClientUrl = function () {        ///<summary>        /// Private function to return the server URL from the context        ///</summary>        ///<returns>String</returns>        var serverUrl = typeof context().getClientUrl !== “undefined” ? context().getClientUrl() : context().getServerUrl();        if (serverUrl.match(/\/$/)) {            serverUrl = serverUrl.substring(0, serverUrl.length – 1);        }        return serverUrl;    };
    var oDataPath = function () {        ///<summary>        /// Private function to return the path to the REST endpoint.        ///</summary>        ///<returns>String</returns>        return getClientUrl() + “/XRMServices/2011/OrganizationData.svc/”;    };
    var errorHandler = function (req) {        ///<summary>        /// Private function return an Error object to the errorCallback        ///</summary>        ///<param name=”req” type=”XMLHttpRequest”>        /// The XMLHttpRequest response that returned an error.        ///</param>        ///<returns>Error</returns>        return new Error(“Error : ” +        req.status + “: ” +        req.statusText + “: ” +        JSON.parse(req.responseText).error.message.value);    };
    var dateReviver = function (key, value) {        ///<summary>        /// Private function to convert matching string values to Date objects.        ///</summary>        ///<param name=”key” type=”String”>        /// The key used to identify the object property        ///</param>        ///<param name=”value” type=”String”>        /// The string value representing a date        ///</param>        var a;        if (typeof value === ‘string’) {            a = /Date\(([-+]?\d+)\)/.exec(value);            if (a) {                return new Date(parseInt(value.replace(“/Date(“, “”).replace(“)/”, “”), 10));            }        }        return value;    };
    var parameterCheck = function (parameter, message) {        ///<summary>        /// Private function used to check whether required parameters are null or undefined        ///</summary>        ///<param name=”parameter” type=”Object”>        /// The parameter to check;        ///</param>        ///<param name=”message” type=”String”>        /// The error message text to include when the error is thrown.        ///</param>        if ((typeof parameter === “undefined”) || parameter === null) {            throw new Error(message);        }    };
    var stringParameterCheck = function (parameter, message) {        ///<summary>        /// Private function used to check whether required parameters are null or undefined        ///</summary>        ///<param name=”parameter” type=”String”>        /// The string parameter to check;        ///</param>        ///<param name=”message” type=”String”>        /// The error message text to include when the error is thrown.        ///</param>        if (typeof parameter != “string”) {            throw new Error(message);        }    };
    var callbackParameterCheck = function (callbackParameter, message) {        ///<summary>        /// Private function used to check whether required callback parameters are functions        ///</summary>        ///<param name=”callbackParameter” type=”Function”>        /// The callback parameter to check;        ///</param>        ///<param name=”message” type=”String”>        /// The error message text to include when the error is thrown.        ///</param>        if (typeof callbackParameter != “function”) {            throw new Error(message);        }    };
    var booleanParameterCheck = function (parameter, message) {        ///<summary>        /// Private function used to check whether required parameters are null or undefined        ///</summary>        ///<param name=”parameter” type=”String”>        /// The string parameter to check;        ///</param>        ///<param name=”message” type=”String”>        /// The error message text to include when the error is thrown.        ///</param>        if (typeof parameter != “boolean”) {            throw new Error(message);        }    };
    var getXhr = function () {        ///<summary>        /// Get an instance of XMLHttpRequest for all browsers        ///</summary>        if (XMLHttpRequest) {            // Chrome, Firefox, IE7+, Opera, Safari            // ReSharper disable InconsistentNaming            return new XMLHttpRequest();            // ReSharper restore InconsistentNaming        }        // IE6        try {            // The latest stable version. It has the best security, performance,            // reliability, and W3C conformance. Ships with Vista, and available            // with other OS’s via downloads and updates.            return new ActiveXObject(‘MSXML2.XMLHTTP.6.0’);        } catch (e) {            try {                // The fallback.                return new ActiveXObject(‘MSXML2.XMLHTTP.3.0’);            } catch (e) {                alert(‘This browser is not AJAX enabled.’);                return null;            }        }    };
    var createRecord = function (object, type, successCallback, errorCallback, async) {        ///<summary>        /// Sends synchronous/asynchronous request to create a new record.        ///</summary>        ///<param name=”object” type=”Object”>        /// A JavaScript object with properties corresponding to the Schema name of        /// entity attributes that are valid for create operations.        ///</param>        parameterCheck(object, “XrmServiceToolkit.REST.createRecord requires the object parameter.”);        ///<param name=”type” type=”string”>        /// A String representing the name of the entity        ///</param>        stringParameterCheck(type, “XrmServiceToolkit.REST.createRecord requires the type parameter is a string.”);        ///<param name=”successCallback” type=”Function”>        /// The function that will be passed through and be called by a successful response.        /// This function can accept the returned record as a parameter.        /// </param>        callbackParameterCheck(successCallback, “XrmServiceToolkit.REST.createRecord requires the successCallback is a function.”);        ///<param name=”errorCallback” type=”Function”>        /// The function that will be passed through and be called by a failed response.        /// This function must accept an Error object as a parameter.        /// </param>        callbackParameterCheck(errorCallback, “XrmServiceToolkit.REST.createRecord requires the errorCallback is a function.”);        ///<param name=”async” type=”Boolean”>        /// A Boolean representing if the method should run asynchronously or synchronously        /// true means asynchronously. false means synchronously        /// </param>        booleanParameterCheck(async, “XrmServiceToolkit.REST.createRecord requires the async is a boolean.”);
        var req = getXhr();        req.open(“POST”, oDataPath() + type, async);        req.setRequestHeader(“Accept”, “application/json”);        req.setRequestHeader(“Content-Type”, “application/json; charset=utf-8”);        req.onreadystatechange = function () {            if (this.readyState === 4 /* complete */) {                req.onreadystatechange = null;                if (this.status === 201) {                    successCallback(JSON.parse(this.responseText, dateReviver).d);                }                else {                    errorCallback(errorHandler(this));                }            }        };        req.send(JSON.stringify(object));    };
    var retrieveRecord = function (id, type, select, expand, successCallback, errorCallback, async) {        ///<summary>        /// Sends synchronous/asynchronous request to retrieve a record.        ///</summary>        ///<param name=”id” type=”String”>        /// A String representing the GUID value for the record to retrieve.        ///</param>        stringParameterCheck(id, “XrmServiceToolkit.REST.retrieveRecord requires the id parameter is a string.”);        ///<param name=”type” type=”string”>        /// A String representing the name of the entity        ///</param>        stringParameterCheck(type, “XrmServiceToolkit.REST.retrieveRecord requires the type parameter is a string.”);        ///<param name=”select” type=”String”>        /// A String representing the $select OData System Query Option to control which        /// attributes will be returned. This is a comma separated list of Attribute names that are valid for retrieve.        /// If null all properties for the record will be returned        ///</param>        if (select != null)            stringParameterCheck(select, “XrmServiceToolkit.REST.retrieveRecord requires the select parameter is a string.”);        ///<param name=”expand” type=”String”>        /// A String representing the $expand OData System Query Option value to control which        /// related records are also returned. This is a comma separated list of of up to 6 entity relationship names        /// If null no expanded related records will be returned.        ///</param>        if (expand != null)            stringParameterCheck(expand, “XrmServiceToolkit.REST.retrieveRecord requires the expand parameter is a string.”);        ///<param name=”successCallback” type=”Function”>        /// The function that will be passed through and be called by a successful response.        /// This function must accept the returned record as a parameter.        /// </param>        callbackParameterCheck(successCallback, “XrmServiceToolkit.REST.retrieveRecord requires the successCallback parameter is a function.”);        ///<param name=”errorCallback” type=”Function”>        /// The function that will be passed through and be called by a failed response.        /// This function must accept an Error object as a parameter.        /// </param>        callbackParameterCheck(errorCallback, “XrmServiceToolkit.REST.retrieveRecord requires the errorCallback parameter is a function.”);        ///<param name=”async” type=”Boolean”>        /// A Boolean representing if the method should run asynchronously or synchronously        /// true means asynchronously. false means synchronously        /// </param>        booleanParameterCheck(async, “XrmServiceToolkit.REST.retrieveRecord requires the async parameter is a boolean.”);
        var systemQueryOptions = “”;
        if (select != null || expand != null) {            systemQueryOptions = “?”;            if (select != null) {                var selectString = “$select=” + select;                if (expand != null) {                    selectString = selectString + “,” + expand;                }                systemQueryOptions = systemQueryOptions + selectString;            }            if (expand != null) {                systemQueryOptions = systemQueryOptions + “&$expand=” + expand;            }        }
        var req = getXhr();        req.open(“GET”, oDataPath() + type + “(guid'” + id + “‘)” + systemQueryOptions, async);        req.setRequestHeader(“Accept”, “application/json”);        req.setRequestHeader(“Content-Type”, “application/json; charset=utf-8”);        req.onreadystatechange = function () {            if (this.readyState === 4 /* complete */) {                if (this.status === 200) {                    successCallback(JSON.parse(this.responseText, dateReviver).d);                }                else {                    errorCallback(errorHandler(this));                }            }        };        req.send();    };
    var updateRecord = function (id, object, type, successCallback, errorCallback, async) {        ///<summary>        /// Sends synchronous/asynchronous request to update a record.        ///</summary>        ///<param name=”id” type=”String”>        /// A String representing the GUID value for the record to update.        ///</param>        stringParameterCheck(id, “XrmServiceToolkit.REST.updateRecord requires the id parameter.”);        ///<param name=”object” type=”Object”>        /// A JavaScript object with properties corresponding to the Schema name of        /// entity attributes that are valid for create operations.        ///</param>        parameterCheck(object, “XrmServiceToolkit.REST.updateRecord requires the object parameter.”);        ///<param name=”type” type=”string”>        /// A String representing the name of the entity        ///</param>        stringParameterCheck(type, “XrmServiceToolkit.REST.updateRecord requires the type parameter.”);        ///<param name=”successCallback” type=”Function”>        /// The function that will be passed through and be called by a successful response.        /// Nothing will be returned to this function.        /// </param>        callbackParameterCheck(successCallback, “XrmServiceToolkit.REST.updateRecord requires the successCallback is a function.”);        ///<param name=”errorCallback” type=”Function”>        /// The function that will be passed through and be called by a failed response.        /// This function must accept an Error object as a parameter.        /// </param>        callbackParameterCheck(errorCallback, “XrmServiceToolkit.REST.updateRecord requires the errorCallback is a function.”);        ///<param name=”async” type=”Boolean”>        /// A Boolean representing if the method should run asynchronously or synchronously        /// true means asynchronously. false means synchronously        /// </param>        booleanParameterCheck(async, “XrmServiceToolkit.REST.updateRecord requires the async parameter is a boolean.”);
        var req = getXhr();
        req.open(“POST”, oDataPath() + type + “(guid'” + id + “‘)”, async);        req.setRequestHeader(“Accept”, “application/json”);        req.setRequestHeader(“Content-Type”, “application/json; charset=utf-8”);        req.setRequestHeader(“X-HTTP-Method”, “MERGE”);
        req.onreadystatechange = function () {            if (this.readyState === 4 /* complete */) {                if (this.status === 204 || this.status === 1223) {                    successCallback();                }                else {                    errorCallback(errorHandler(this));                }            }        };        req.send(JSON.stringify(object));    };
    var deleteRecord = function (id, type, successCallback, errorCallback, async) {        ///<summary>        /// Sends synchronous/asynchronous request to delete a record.        ///</summary>        ///<param name=”id” type=”String”>        /// A String representing the GUID value for the record to delete.        ///</param>        stringParameterCheck(id, “XrmServiceToolkit.REST.deleteRecord requires the id parameter.”);        ///<param name=”type” type=”string”>        /// A String representing the name of the entity        ///</param>        stringParameterCheck(type, “XrmServiceToolkit.REST.deleteRecord requires the type parameter.”);        ///<param name=”successCallback” type=”Function”>        /// The function that will be passed through and be called by a successful response.        /// Nothing will be returned to this function.        /// </param>        callbackParameterCheck(successCallback, “XrmServiceToolkit.REST.deleteRecord requires the successCallback is a function.”);        ///<param name=”errorCallback” type=”Function”>        /// The function that will be passed through and be called by a failed response.        /// This function must accept an Error object as a parameter.        /// </param>        callbackParameterCheck(errorCallback, “XrmServiceToolkit.REST.deleteRecord requires the errorCallback is a function.”);        ///<param name=”async” type=”Boolean”>        /// A Boolean representing if the method should run asynchronously or synchronously        /// true means asynchronously. false means synchronously        /// </param>        booleanParameterCheck(async, “XrmServiceToolkit.REST.deleteRecord requires the async parameter is a boolean.”);
        var req = getXhr();        req.open(“POST”, oDataPath() + type + “(guid'” + id + “‘)”, async);        req.setRequestHeader(“Accept”, “application/json”);        req.setRequestHeader(“Content-Type”, “application/json; charset=utf-8”);        req.setRequestHeader(“X-HTTP-Method”, “DELETE”);        req.onreadystatechange = function () {            if (this.readyState === 4 /* complete */) {                if (this.status === 204 || this.status === 1223) {                    successCallback();                }                else {                    errorCallback(errorHandler(this));                }            }        };        req.send();    };
    var retrieveMultipleRecords = function (type, options, successCallback, errorCallback, onComplete, async) {        ///<summary>        /// Sends synchronous/asynchronous request to retrieve records.        ///</summary>        ///<param name=”type” type=”String”>        /// The Schema Name of the Entity type record to retrieve.        /// For an Account record, use “Account”        ///</param>        stringParameterCheck(type, “XrmServiceToolkit.REST.retrieveMultipleRecords requires the type parameter is a string.”);        ///<param name=”options” type=”String”>        /// A String representing the OData System Query Options to control the data returned        ///</param>        if (options != null)            stringParameterCheck(options, “XrmServiceToolkit.REST.retrieveMultipleRecords requires the options parameter is a string.”);        ///<param name=”successCallback” type=”Function”>        /// The function that will be passed through and be called for each page of records returned.        /// Each page is 50 records. If you expect that more than one page of records will be returned,        /// this function should loop through the results and push the records into an array outside of the function.        /// Use the OnComplete event handler to know when all the records have been processed.        /// </param>        callbackParameterCheck(successCallback, “XrmServiceToolkit.REST.retrieveMultipleRecords requires the successCallback parameter is a function.”);        ///<param name=”errorCallback” type=”Function”>        /// The function that will be passed through and be called by a failed response.        /// This function must accept an Error object as a parameter.        /// </param>        callbackParameterCheck(errorCallback, “XrmServiceToolkit.REST.retrieveMultipleRecords requires the errorCallback parameter is a function.”);        ///<param name=”OnComplete” type=”Function”>        /// The function that will be called when all the requested records have been returned.        /// No parameters are passed to this function.        /// </param>        callbackParameterCheck(onComplete, “XrmServiceToolkit.REST.retrieveMultipleRecords requires the OnComplete parameter is a function.”);        ///<param name=”async” type=”Boolean”>        /// A Boolean representing if the method should run asynchronously or synchronously        /// true means asynchronously. false means synchronously        /// </param>        booleanParameterCheck(async, “XrmServiceToolkit.REST.retrieveMultipleRecords requires the async parameter is a boolean.”);
        var optionsString = ”;        if (options != null) {            if (options.charAt(0) != “?”) {                optionsString = “?” + options;            }            else {                optionsString = options;            }        }
        var req = getXhr();        req.open(“GET”, oDataPath() + type + optionsString, async);        req.setRequestHeader(“Accept”, “application/json”);        req.setRequestHeader(“Content-Type”, “application/json; charset=utf-8”);        req.onreadystatechange = function () {            if (this.readyState === 4 /* complete */) {                if (this.status === 200) {                    var returned = JSON.parse(this.responseText, dateReviver).d;                    successCallback(returned.results);                    if (returned.__next != null) {                        var queryOptions = returned.__next.substring((oDataPath() + type).length);                        retrieveMultipleRecords(type, queryOptions, successCallback, errorCallback, onComplete, async);                    }                    else {                        onComplete();                    }                }                else {                    errorCallback(errorHandler(this));                }            }        };        req.send();    };
    var performRequest = function (settings) {        parameterCheck(settings, “The value passed to the performRequest function settings parameter is null or undefined.”);        var request = getXhr();        request.open(settings.type, settings.url, settings.async);        request.setRequestHeader(“Accept”, “application/json”);        if (settings.action != null) {            request.setRequestHeader(“X-HTTP-Method”, settings.action);        }        request.setRequestHeader(“Content-Type”, “application/json; charset=utf-8”);        request.onreadystatechange = function () {            if (this.readyState === 4 /*Complete*/) {                // Status 201 is for create, status 204/1223 for link and delete.                // There appears to be an issue where IE maps the 204 status to 1223                // when no content is returned.                if (this.status === 204 || this.status === 1223 || this.status === 201) {                    settings.success(this);                }                else {                    // Failure                    if (settings.error) {                        settings.error(errorHandler(this));                    }                    else {                        errorHandler(this);                    }                }            }        };
        if (typeof settings.data === “undefined”) {            request.send();        }        else {            request.send(settings.data);        }    };
    var associateRecord = function (entityid1, odataSetName1, entityid2, odataSetName2, relationship, successCallback, errorCallback, async) {        ///<summary>        /// Sends synchronous/asynchronous request to associate a record.        ///</summary>        ///<param name=”entityid1″ type=”string”>        /// A String representing the GUID value for the record to associate.        ///</param>        parameterCheck(entityid1, “XrmServiceToolkit.REST.associateRecord requires the entityid1 parameter.”);        ///<param name=”odataSetName1″ type=”string”>        /// A String representing the odataset name for entityid1        ///</param>        parameterCheck(odataSetName1, “XrmServiceToolkit.REST.associateRecord requires the odataSetName1 parameter.”);        ///<param name=”entityid2″ type=”string”>        /// A String representing the GUID value for the record to be associated.        ///</param>        parameterCheck(entityid2, “XrmServiceToolkit.REST.associateRecord requires the entityid2 parameter.”);        ///<param name=”odataSetName2″ type=”string”>        /// A String representing the odataset name for entityid2        ///</param>        parameterCheck(odataSetName2, “XrmServiceToolkit.REST.associateRecord requires the odataSetName2 parameter.”);        ///<param name=”relationship” type=”string”>        /// A String representing the name of the relationship for association        ///</param>        parameterCheck(relationship, “XrmServiceToolkit.REST.associateRecord requires the relationship parameter.”);        ///<param name=”successCallback” type=”Function”>        /// The function that will be passed through and be called by a successful response.        /// Nothing will be returned to this function.        /// </param>        callbackParameterCheck(successCallback, “XrmServiceToolkit.REST.associateRecord requires the successCallback is a function.”);        ///<param name=”errorCallback” type=”Function”>        /// The function that will be passed through and be called by a failed response.        /// This function must accept an Error object as a parameter.        /// </param>        callbackParameterCheck(errorCallback, “XrmServiceToolkit.REST.associateRecord requires the errorCallback is a function.”);        ///<param name=”async” type=”Boolean”>        /// A Boolean representing if the method should run asynchronously or synchronously        /// true means asynchronously. false means synchronously        /// </param>        booleanParameterCheck(async, “XrmServiceToolkit.REST.associateRecord requires the async parameter is a boolean”);
        var entity2 = {};        entity2.uri = oDataPath() + “/” + odataSetName2 + “(guid'” + entityid2 + “‘)”;        var jsonEntity = window.JSON.stringify(entity2);
        performRequest({            type: “POST”,            url: oDataPath() + “/” + odataSetName1 + “(guid'” + entityid1 + “‘)/$links/” + relationship,            data: jsonEntity,            success: successCallback,            error: errorCallback,            async: async        });    };
    var disassociateRecord = function (entityid1, odataSetName, entityid2, relationship, successCallback, errorCallback, async) {        ///<summary>        /// Sends synchronous/asynchronous request to disassociate a record.        ///</summary>        ///<param name=”entityid1″ type=”string”>        /// A String representing the GUID value for the record to disassociate.        ///</param>        parameterCheck(entityid1, “XrmServiceToolkit.REST.disassociateRecord requires the entityid1 parameter.”);        ///<param name=”odataSetName” type=”string”>        /// A String representing the odataset name for entityid1        ///</param>        parameterCheck(odataSetName, “XrmServiceToolkit.REST.disassociateRecord requires the odataSetName parameter.”);        ///<param name=”entityid2″ type=”string”>        /// A String representing the GUID value for the record to be disassociated.        ///</param>        parameterCheck(entityid2, “XrmServiceToolkit.REST.disassociateRecord requires the entityid2 parameter.”);        ///<param name=”relationship” type=”string”>        /// A String representing the name of the relationship for disassociation        ///</param>        parameterCheck(relationship, “XrmServiceToolkit.REST.disassociateRecord requires the relationship parameter.”);        ///<param name=”successCallback” type=”Function”>        /// The function that will be passed through and be called by a successful response.        /// Nothing will be returned to this function.        /// </param>        callbackParameterCheck(successCallback, “XrmServiceToolkit.REST.disassociateRecord requires the successCallback is a function.”);        ///<param name=”errorCallback” type=”Function”>        /// The function that will be passed through and be called by a failed response.        /// This function must accept an Error object as a parameter.        /// </param>        callbackParameterCheck(errorCallback, “XrmServiceToolkit.REST.disassociateRecord requires the errorCallback is a function.”);        ///<param name=”async” type=”Boolean”>        /// A Boolean representing if the method should run asynchronously or synchronously        /// true means asynchronously. false means synchronously        /// </param>        booleanParameterCheck(async, “XrmServiceToolkit.REST.disassociateRecord requires the async parameter is a boolean.”);
        var url = oDataPath() + “/” + odataSetName + “(guid'” + entityid1 + “‘)/$links/” + relationship + “(guid'” + entityid2 + “‘)”;        performRequest({            url: url,            type: “POST”,            action: “DELETE”,            error: errorCallback,            success: successCallback,            async: async        });    };
    // Toolkit’s public static members    return {        Create: createRecord,        Retrieve: retrieveRecord,        Update: updateRecord,        Delete: deleteRecord,        RetrieveMultiple: retrieveMultipleRecords,        Associate: associateRecord,        Disassociate: disassociateRecord    };} ();
XrmServiceToolkit.Soap = function () {
    var htmlEncode = function (s) {        if (s === null || s === “” || s === undefined) return s;        for (var count = 0, buffer = “”, hEncode = “”, cnt = 0; cnt < s.length; cnt++) {            var c = s.charCodeAt(cnt);            if (c > 96 && c < 123 || c > 64 && c < 91 || c === 32 || c > 47 && c < 58 || c === 46 || c === 44 || c === 45 || c === 95)                buffer += String.fromCharCode(c);            else buffer += “&#” + c + “;”;            if (++count === 500) {                hEncode += buffer; buffer = “”; count = 0;            }        }        if (buffer.length) hEncode += buffer;        return hEncode;    };
    var innerSurrogateAmpersandWorkaround = function (s) {        var buffer = ”;        var c0;        for (var cnt = 0; cnt < s.length; cnt++) {            c0 = s.charCodeAt(cnt);            if (c0 >= 55296 && c0 <= 57343)                if (cnt + 1 < s.length) {                    var c1 = s.charCodeAt(cnt + 1);                    if (c1 >= 56320 && c1 <= 57343) {                        buffer += “CRMEntityReferenceOpen” + ((c0 – 55296) * 1024 + (c1 & 1023) + 65536).toString(16) + “CRMEntityReferenceClose”; cnt++;                    }                    else                        buffer += String.fromCharCode(c0);                }                else buffer += String.fromCharCode(c0);            else buffer += String.fromCharCode(c0);        }        s = buffer;        buffer = “”;        for (cnt = 0; cnt < s.length; cnt++) {            c0 = s.charCodeAt(cnt);            if (c0 >= 55296 && c0 <= 57343)                buffer += String.fromCharCode(65533);            else buffer += String.fromCharCode(c0);        }        s = buffer;        s = htmlEncode(s);        s = s.replace(/CRMEntityReferenceOpen/g, “&#x”);        s = s.replace(/CRMEntityReferenceClose/g, “;”);        return s;    };
    var crmXmlEncode = function (s) {        // ReSharper disable UsageOfPossiblyUnassignedValue        // ReSharper disable ExpressionIsAlwaysConst        if (‘undefined’ === typeof s || ‘unknown’ === typeof s || null === s) return s;        // ReSharper restore ExpressionIsAlwaysConst        // ReSharper restore UsageOfPossiblyUnassignedValue        else if (typeof s != “string”) s = s.toString();        return innerSurrogateAmpersandWorkaround(s);    };
    var crmXmlDecode = function (s) {        if (typeof s != “string”) s = s.toString();        return s;    };
    var padNumber = function (s, len) {        len = len || 2;
        s = ” + s;        while (s.length < len) {            s = “0” + s;        }        return s;    };
    var encodeDate = function (dateTime) {        return dateTime.getFullYear() + “-” +               padNumber(dateTime.getMonth() + 1) + “-” +               padNumber(dateTime.getDate()) + “T” +               padNumber(dateTime.getHours()) + “:” +               padNumber(dateTime.getMinutes()) + “:” +               padNumber(dateTime.getSeconds());    };
    var encodeValue = function (value) {        // Handle GUIDs wrapped in braces        if (typeof value == typeof “” && value.slice(0, 1) == “{” && value.slice(-1) == “}”)        {            value = value.slice(1, -1);        }
        // ReSharper disable QualifiedExpressionMaybeNull        return (typeof value === “object” && value.getTime)        // ReSharper restore QualifiedExpressionMaybeNull               ? encodeDate(value)               : crmXmlEncode(value);    };
    var context = function () {        ///<summary>        /// Private function to the context object.        ///</summary>        ///<returns>Context</returns>        var oContext;        if (typeof window.GetGlobalContext != “undefined”) {            oContext = window.GetGlobalContext();        }        else {            if (typeof Xrm != “undefined”) {                oContext = Xrm.Page.context;            }            else if (typeof window.parent.Xrm != “undefined”) {                oContext = window.parent.Xrm.Page.context;            }            else {                throw new Error(“Context is not available.”);            }        }        return oContext;    };
    var getClientUrl = function () {        ///<summary>        /// Private function to return the server URL from the context        ///</summary>        ///<returns>String</returns>        var serverUrl = typeof context().getClientUrl != ‘undefined’ ? context().getClientUrl() : context().getServerUrl();        if (serverUrl.match(/\/$/)) {            serverUrl = serverUrl.substring(0, serverUrl.length – 1);        }        return serverUrl;    };
    var orgServicePath = function () {        ///<summary>        /// Private function to return the path to the organization service.        ///</summary>        ///<returns>String</returns>        return getClientUrl() + “/XRMServices/2011/Organization.svc/web”;    };
    // ReSharper disable UnusedLocals    var dateReviver = function (key, value) {        // ReSharper restore UnusedLocals        ///<summary>        /// Private function to convert matching string values to Date objects.        ///</summary>        ///<param name=”key” type=”String”>        /// The key used to identify the object property        ///</param>        ///<param name=”value” type=”String”>        /// The string value representing a date        ///</param>        var a;        if (typeof value === ‘string’) {            a = /Date\(([-+]?\d+)\)/.exec(value);            if (a) {                return new Date(parseInt(value.replace(“/Date(“, “”).replace(“)/”, “”), 10));            }        }        return value;    };
    var xrmValue = function (sType, sValue) {        this.type = sType;        this.value = sValue;    };
    var xrmEntityReference = function (gId, sLogicalName, sName) {        this.id = gId;        this.logicalName = sLogicalName;        this.name = sName;        this.type = ‘EntityReference’;    };
    var xrmEntityCollection = function (items) {        this.value = items;        this.type = ‘EntityCollection’;    };
    var xrmOptionSetValue = function (iValue, sFormattedValue) {        this.value = iValue;        this.formattedValue = sFormattedValue;        this.type = ‘OptionSetValue’;    };
    var businessEntity = function (logicalName, id) {        ///<summary>        /// A object represents a business entity for CRM 2011.        ///</summary>        ///<param name=”logicalName” type=”String”>        /// A String represents the name of the entity.        /// For example, “contact” means the business entity will be a contact entity        /// </param>        ///<param name=”id” type=”String”>        /// A String represents the id of the entity. If not passed, it will be auto populated as a empty guid string        /// </param>        this.id = (!id) ? “00000000-0000-0000-0000-000000000000” : id;        this.logicalName = logicalName;        this.attributes = new Object();    };
    var getXhr = function () {        ///<summary>        /// Get an instance of XMLHttpRequest for all browsers        ///</summary>        if (XMLHttpRequest) {            // Chrome, Firefox, IE7+, Opera, Safari            // ReSharper disable InconsistentNaming            return new XMLHttpRequest();            // ReSharper restore InconsistentNaming        }        // IE6        try {            // The latest stable version. It has the best security, performance,            // reliability, and W3C conformance. Ships with Vista, and available            // with other OS’s via downloads and updates.            return new ActiveXObject(‘MSXML2.XMLHTTP.6.0’);        } catch (e) {            try {                // The fallback.                return new ActiveXObject(‘MSXML2.XMLHTTP.3.0’);            } catch (e) {                alert(‘This browser is not AJAX enabled.’);                return null;            }        }    };
    var stringToDate = function (s) {        var b = s.split(/\D/);        return new Date(Date.UTC(b[0], –b[1], b[2], b[3], b[4], b[5]));    };
    businessEntity.prototype = {        /**        * Serialize a CRM Business Entity object to XML string in order to be passed to CRM Web Services.        * @return {String} The serialized XML string of CRM entity.        */        serialize: function () {            var xml = [‘<entity xmlns:a=”http://schemas.microsoft.com/xrm/2011/Contracts”>’%5D;            xml.push(‘<a:Attributes xmlns:b=”http://schemas.datacontract.org/2004/07/System.Collections.Generic”>&#8217;);
            for (var attributeName in this.attributes) {                var attribute = this.attributes[attributeName];
                xml.push(‘<a:KeyValuePairOfstringanyType>’);                xml.push(‘<b:key>’, attributeName, ‘</b:key>’);
                if (attribute === null || attribute.value === null) {                    xml.push(‘<b:value i:nil=”true” />’);                }                else {                    var sType = (!attribute.type)                            ? typeof attribute                            : crmXmlEncode(attribute.type);                    var value;                    var encodedValue;                    var id;                    var encodedId;                    var logicalName;                    var encodedLogicalName;                    switch (sType) {                        case “OptionSetValue”:                            value = (attribute.hasOwnProperty(“value”)) ? attribute[“value”] : attribute;                            encodedValue = encodeValue(value);                            xml.push(‘<b:value i:type=”a:OptionSetValue”>’);                            xml.push(‘<a:Value>’, encodedValue, ‘</a:Value>’, ‘</b:value>’);                            break;
                        case “EntityCollection”:                            xml.push(‘<b:value i:type=”a:EntityCollection”>’);                            xml.push(‘<a:Entities>’);                            value = (attribute.hasOwnProperty(“value”)) ? attribute[“value”] : attribute;                            var collections = isArray(value) ? value : [value];
                            for (var i = 0; i < collections.length; i++) {                                var item = collections[i];                                id = (item.hasOwnProperty(“id”)) ? item[“id”] : item;                                encodedId = encodeValue(id);                                logicalName = (item.hasOwnProperty(“logicalName”)) ? item[“logicalName”] : item;                                encodedLogicalName = encodeValue(logicalName);                                xml.push(‘<a:Entity>’);                                xml.push(‘<a:Attributes>’);                                xml.push(‘<a:KeyValuePairOfstringanyType>’);                                xml.push(‘<b:key>partyid</b:key>’);                                xml.push(‘<b:value i:type=”a:EntityReference”>’);                                xml.push(‘<a:Id>’, encodedId, ‘</a:Id>’);                                xml.push(‘<a:LogicalName>’, encodedLogicalName, ‘</a:LogicalName>’);                                xml.push(‘<a:Name i:nil=”true” />’);                                xml.push(‘</b:value>’);                                xml.push(‘</a:KeyValuePairOfstringanyType>’);                                xml.push(‘</a:Attributes>’);                                xml.push(‘<a:EntityState i:nil=”true” />’);                                xml.push(‘<a:FormattedValues />’);                                xml.push(‘<a:Id>00000000-0000-0000-0000-000000000000</a:Id>’);                                xml.push(‘<a:LogicalName>activityparty</a:LogicalName>’);                                xml.push(‘<a:RelatedEntities />’);                                xml.push(‘</a:Entity>’);                            }                            xml.push(‘</a:Entities>’);                            xml.push(‘<a:EntityName i:nil=”true” />’);                            xml.push(‘<a:MinActiveRowVersion i:nil=”true” />’);                            xml.push(‘<a:MoreRecords>false</a:MoreRecords>’);                            xml.push(‘<a:PagingCookie i:nil=”true” />’);                            xml.push(‘<a:TotalRecordCount>0</a:TotalRecordCount>’);                            xml.push(‘<a:TotalRecordCountLimitExceeded>false</a:TotalRecordCountLimitExceeded>’);                            xml.push(‘</b:value>’);                            break;
                        case “EntityReference”:                            id = (attribute.hasOwnProperty(“id”)) ? attribute[“id”] : attribute;                            encodedId = encodeValue(id);                            logicalName = (attribute.hasOwnProperty(“logicalName”)) ? attribute[“logicalName”] : attribute;                            encodedLogicalName = encodeValue(logicalName);                            xml.push(‘<b:value i:type=”a:EntityReference”>’);                            xml.push(‘<a:Id>’, encodedId, ‘</a:Id>’);                            xml.push(‘<a:LogicalName>’, encodedLogicalName, ‘</a:LogicalName>’);                            xml.push(‘<a:Name i:nil=”true” />’, ‘</b:value>’);                            break;
                        case “Money”:                            value = (attribute.hasOwnProperty(“value”)) ? attribute[“value”] : attribute;                            encodedValue = encodeValue(value);                            xml.push(‘<b:value i:type=”a:Money”>’);                            xml.push(‘<a:Value>’, encodedValue, ‘</a:Value>’, ‘</b:value>’);                            break;
                        case “guid”:                            value = (attribute.hasOwnProperty(“value”)) ? attribute[“value”] : attribute;                            encodedValue = encodeValue(value);                            xml.push(‘<b:value i:type=”c:guid” xmlns:c=”http://schemas.microsoft.com/2003/10/Serialization/”>&#8217;);                            xml.push(encodedValue, ‘</b:value>’);                            break;
                        case “number”:                            value = (attribute.hasOwnProperty(“value”)) ? attribute[“value”] : attribute;                            encodedValue = encodeValue(value);                            var oType = (parseInt(encodedValue) === encodedValue) ? “c:int” : “c:decimal”;                            xml.push(‘<b:value i:type=”‘, oType, ‘” xmlns:c=”http://www.w3.org/2001/XMLSchema”>&#8217;);                            xml.push(encodedValue, ‘</b:value>’);                            break;
                        default:                            value = (attribute.hasOwnProperty(“value”)) ? attribute[“value”] : attribute;                            encodedValue = encodeValue(value);                            sType = (typeof value === “object” && value.getTime) ? “dateTime” : sType;                            xml.push(‘<b:value i:type=”c:’, sType, ‘” xmlns:c=”http://www.w3.org/2001/XMLSchema”>&#8217;, encodedValue, ‘</b:value>’);                            break;                    }                }                xml.push(‘</a:KeyValuePairOfstringanyType>’);            }
            xml.push(‘</a:Attributes><a:EntityState i:nil=”true” />’);            xml.push(‘<a:FormattedValues xmlns:b=”http://schemas.datacontract.org/2004/07/System.Collections.Generic&#8221; />’);            xml.push(‘<a:Id>’, encodeValue(this.id), ‘</a:Id>’);            xml.push(‘<a:LogicalName>’, this.logicalName, ‘</a:LogicalName>’);            xml.push(‘<a:RelatedEntities xmlns:b=”http://schemas.datacontract.org/2004/07/System.Collections.Generic&#8221; />’);            xml.push(‘</entity>’);            return xml.join(“”);        },
        /**        * Deserialize an XML node into a CRM Business Entity object. The XML node comes from CRM Web Service’s response.        * @param {object} resultNode The XML node returned from CRM Web Service’s Fetch, Retrieve, RetrieveMultiple messages.        */        deserialize: function (resultNode) {            var obj = new Object();            var resultNodes = resultNode.childNodes;
            for (var j = 0; j < resultNodes.length; j++) {                var k;                var sKey;                switch (resultNodes[j].nodeName) {                    case “a:Attributes”:                        var attr = resultNodes[j];                        for (k = 0; k < attr.childNodes.length; k++) {
                            // Establish the Key for the Attribute                            sKey = jQuery(attr.childNodes[k].firstChild).text();                            var sType = ”;
                            // Determine the Type of Attribute value we should expect                            for (var l = 0; l < attr.childNodes[k].childNodes[1].attributes.length; l++) {                                if (attr.childNodes[k].childNodes[1].attributes[l].nodeName === ‘i:type’) {                                    sType = jQuery(attr.childNodes[k].childNodes[1].attributes[l]).val();                                }                            }                            var entRef;                            var entCv;                            switch (sType) {                                case “a:OptionSetValue”:                                    var entOsv = new xrmOptionSetValue();                                    entOsv.type = sType.replace(‘a:’, ”);                                    entOsv.value = parseInt(jQuery(attr.childNodes[k].childNodes[1]).text());                                    obj[sKey] = entOsv;                                    break;
                                case “a:EntityReference”:                                    entRef = new xrmEntityReference();                                    entRef.type = sType.replace(‘a:’, ”);                                    entRef.id = jQuery(attr.childNodes[k].childNodes[1].childNodes[0]).text();                                    entRef.logicalName = jQuery(attr.childNodes[k].childNodes[1].childNodes[1]).text();                                    entRef.name = jQuery(attr.childNodes[k].childNodes[1].childNodes[2]).text();                                    obj[sKey] = entRef;                                    break;
                                case “a:EntityCollection”:                                    entRef = new xrmEntityCollection();                                    entRef.type = sType.replace(‘a:’, ”);
                                    //get all party items….                                    var items = [];                                    for (var y = 0; y < attr.childNodes[k].childNodes[1].childNodes[0].childNodes.length; y++) {                                        var itemNodes = attr.childNodes[k].childNodes[1].childNodes[0].childNodes[y].childNodes[0].childNodes;                                        for (var z = 0; z < itemNodes.length; z++) {                                            if (jQuery(itemNodes[z].childNodes[0]).text() === “partyid”) {                                                var itemRef = new xrmEntityReference();                                                itemRef.id = jQuery(itemNodes[z].childNodes[1].childNodes[0]).text();                                                itemRef.logicalName = jQuery(itemNodes[z].childNodes[1].childNodes[1]).text();                                                itemRef.name = jQuery(itemNodes[z].childNodes[1].childNodes[2]).text();                                                items[y] = itemRef;                                            }                                        }                                    }                                    entRef.value = items;                                    obj[sKey] = entRef;                                    break;
                                case “a:Money”:                                    entCv = new xrmValue();                                    entCv.type = sType.replace(‘a:’, ”);                                    entCv.value = parseFloat(jQuery(attr.childNodes[k].childNodes[1]).text());                                    obj[sKey] = entCv;                                    break;
                                default:                                    entCv = new xrmValue();                                    entCv.type = sType.replace(‘c:’, ”).replace(‘a:’, ”);                                    if (entCv.type === “int”) {                                        entCv.value = parseInt(jQuery(attr.childNodes[k].childNodes[1]).text());                                    }                                    else if (entCv.type === “decimal” || entCv.type === “double”) {                                        entCv.value = parseFloat(jQuery(attr.childNodes[k].childNodes[1]).text());                                    }                                    else if (entCv.type === “dateTime”) {                                        entCv.value = stringToDate(jQuery(attr.childNodes[k].childNodes[1]).text());                                    }                                    else if (entCv.type === “boolean”) {                                        entCv.value = (jQuery(attr.childNodes[k].childNodes[1]).text() === ‘false’) ? false : true;                                    }                                    //@Credit: Thanks for Tanguy92’s code from CodePlex                                    else if (entCv.type === “AliasedValue”) {                                        entCv.value = jQuery(attr).children().eq(k).children().eq(1).children().eq(2).text();                                        if (jQuery(attr).children().eq(k).children().eq(1).children().eq(2).attr(“i:type”) === “a:EntityReference”) {                                            entCv = new xrmEntityReference();                                            entCv.type = “EntityReference”;                                            entCv.id = jQuery(attr).children().eq(k).children().eq(1).children().eq(2).children().eq(0).text();                                            entCv.logicalName = jQuery(attr).children().eq(k).children().eq(1).children().eq(2).children().eq(1).text();                                            entCv.name = jQuery(attr).children().eq(k).children().eq(1).children().eq(2).children().eq(2).text();                                    }                                    }                                    else {                                        entCv.value = jQuery(attr.childNodes[k].childNodes[1]).text();                                    }                                    obj[sKey] = entCv;                                    break;                            }                        }                        this.attributes = obj;                        break;
                    case “a:Id”:                        this.id = jQuery(resultNodes[j]).text();                        break;
                    case “a:LogicalName”:                        this.logicalName = jQuery(resultNodes[j]).text();                        break;
                    case “a:FormattedValues”:                        var foVal = resultNodes[j];
                        for (k = 0; k < foVal.childNodes.length; k++) {                            // Establish the Key, we are going to fill in the formatted value of the already found attribute                            sKey = jQuery(foVal.childNodes[k].firstChild).text();                            this.attributes[sKey].formattedValue = jQuery(foVal.childNodes[k].childNodes[1]).text();                            if (isNaN(this.attributes[sKey].value) && this.attributes[sKey].type === “dateTime”) {                                this.attributes[sKey].value = new Date(this.attributes[sKey].formattedValue);                            }                        }                        break;                }            }        }    };
    var xmlParser = function (txt) {        ///<summary>        /// cross browser responseXml to return a XML object        ///</summary>        var xmlDoc = null;        try {            // code for Mozilla, Firefox, Opera, etc.            if (window.DOMParser) {                // ReSharper disable InconsistentNaming                var parser = new DOMParser();                // ReSharper restore InconsistentNaming                xmlDoc = parser.parseFromString(txt, “text/xml”);            }            else // Internet Explorer            {                xmlDoc = new ActiveXObject(“Microsoft.XMLDOM”);                xmlDoc.async = false;                xmlDoc.loadXML(txt);            }        } catch (e) {            alert(“Cannot convert the XML string to a cross-browser XML object.”);        }
        return xmlDoc;    };
    var xmlToString = function (responseXml) {        var xmlString = ”;        try {            if (responseXml != null) {                if (typeof XMLSerializer !== “undefined” && typeof responseXml.xml === “undefined”) {                    // ReSharper disable InconsistentNaming                    xmlString = (new XMLSerializer()).serializeToString(responseXml[0]);                    // ReSharper restore InconsistentNaming                } else {                    if (typeof responseXml.xml !== “undefined”) {                        xmlString = responseXml.xml;                    }                    else if (typeof responseXml[0].xml !== “undefined”) {                        xmlString = responseXml[0].xml;                    }
                }            }        } catch (e) {            alert(“Cannot convert the XML to a string.”);        }        return xmlString;    };
    var doRequest = function (soapBody, requestType, async, internalCallback) {        async = async || false;
        // Wrap the Soap Body in a soap:Envelope.        var soapXml =        [“<soap:Envelope xmlns:soap=’http://schemas.xmlsoap.org/soap/envelope/’>&#8221;,            “<soap:Body>”,                “<“, requestType, ” xmlns=’http://schemas.microsoft.com/xrm/2011/Contracts/Services&#8217; xmlns:i=’http://www.w3.org/2001/XMLSchema-instance’>&#8221;, soapBody, “</”, requestType, “>”,            “</soap:Body>”,            “</soap:Envelope>”        ].join(“”);
        var req = getXhr();        req.open(“POST”, orgServicePath(), async);        req.setRequestHeader(“Accept”, “application/xml, text/xml, */*”);        req.setRequestHeader(“Content-Type”, “text/xml; charset=utf-8”);        req.setRequestHeader(“SOAPAction”, “http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/&#8221; + requestType);
        req.send(soapXml);
        if (async) {            req.onreadystatechange = function () {                if (req.readyState === 4) { // “complete”                    req.onreadystatechange = null; //Addresses potential memory leak issue with IE                    if (req.status === 200) { // “OK”                        internalCallback(processResponse(req.responseXML, req.responseText));                    }                    else {                        processResponse(req.responseXML, req.responseText);                    }                }            };        }        else {            var result = processResponse(req.responseXML, req.responseText);            return !!internalCallback ? internalCallback(result) : result;        }        // ReSharper disable NotAllPathsReturnValue    };    // ReSharper restore NotAllPathsReturnValue
    var processResponse = function (responseXml, responseText) {        var error;        var faultString;        var xmlDoc;        if (responseXml === null || typeof responseXml === ‘undefined’ || responseXml.xml === null || responseXml.xml === “”) {            if (responseText !== null && responseText !== “”) {                throw new Error(responseText);            }            else                throw new Error(“No response received from the server. “);        }
        // Report the error if occurred        // Load responseXML and return as an XML object        if (typeof responseXml.xml === ‘undefined’) {            error = jQuery(responseText).find(“error”).text();            faultString = jQuery(responseText).find(“faultstring”).text();            if (error != ” || faultString != ”) {                throw new Error(error !== ” ? jQuery(responseText).find(‘description’).text() : faultString);            }
            xmlDoc = xmlParser(responseText);        } else {            error = jQuery(responseXml).find(“error”).text();            faultString = jQuery(responseXml).find(“faultstring”).text();            if (error != “” || faultString != “”) {                throw new Error(error != “” ? jQuery(responseXml).find(‘description’).text() : faultString);            }
            xmlDoc = xmlParser(xmlToString(responseXml));        }
        return xmlDoc;    };
    var sCreate = function (be, callback) {        ///<summary>        /// Sends synchronous/asynchronous request to create a new record.        ///</summary>        ///<param name=”be” type=”Object”>        /// A JavaScript object with properties corresponding to the Schema name of        /// entity attributes that are valid for create operations.        /// </param>        ///<param name=”callback” type=”Function”>        /// A Function used for asynchronous request. If not defined, it sends a synchronous request.        /// </param>        var request = be.serialize();
        var async = !!callback;
        return doRequest(request, “Create”, async, function (resultXml) {            var response = jQuery(resultXml).find(‘CreateResult’).eq(0);
            var result = crmXmlDecode(response.text());
            if (!async)                return result;            else                callback(result);            // ReSharper disable NotAllPathsReturnValue        });        // ReSharper restore NotAllPathsReturnValue    };
    var sUpdate = function (be, callback) {        ///<summary>        /// Sends synchronous/asynchronous request to update an existing record.        ///</summary>        ///<param name=”businessEntity” type=”Object”>        /// A JavaScript object with properties corresponding to the Schema name of        /// entity attributes that are valid for update operations.        /// </param>        ///<param name=”callback” type=”Function”>        /// A Function used for asynchronous request. If not defined, it sends a synchronous request.        /// </param>        var request = be.serialize();
        var async = !!callback;
        return doRequest(request, “Update”, async, function (resultXml) {            var response = jQuery(resultXml).find(“UpdateResponse”).eq(0);            var result = crmXmlDecode(response.text());
            if (!async)                return result;            else                callback(result);            // ReSharper disable NotAllPathsReturnValue        });        // ReSharper restore NotAllPathsReturnValue    };
    var sDelete = function (entityName, id, callback) {        ///<summary>        /// Sends synchronous/asynchronous request to delete a record.        ///</summary>        ///<param name=”entityName” type=”String”>        /// A JavaScript String corresponding to the Schema name of        /// entity that is used for delete operations.        /// </param>        ///<param name=”id” type=”String”>        /// A JavaScript String corresponding to the GUID of        /// entity that is used for delete operations.        /// </param>        ///<param name=”callback” type=”Function”>        /// A Function used for asynchronous request. If not defined, it sends a synchronous request.        /// </param>        var request =                [                    “<entityName>”, entityName, “</entityName>”,                    “<id>”, id, “</id>”                ].join(“”);
        var async = !!callback;
        return doRequest(request, “Delete”, async, function (resultXml) {            var response = jQuery(resultXml).find(“DeleteResponse”).eq(0);            var result = crmXmlDecode(response.text());
            if (!async)                return result;            else                callback(result);            // ReSharper disable NotAllPathsReturnValue        });        // ReSharper restore NotAllPathsReturnValue    };
    var execute = function (request, callback) {        ///<summary>        /// Sends synchronous/asynchronous request to execute a soap request.        ///</summary>        ///<param name=”request” type=”String”>        /// A JavaScript string corresponding to the soap request        /// that are valid for execute operations.        /// </param>        ///<param name=”callback” type=”Function”>        /// A Function used for asynchronous request. If not defined, it sends a synchronous request.        /// </param>        var async = !!callback;
        return doRequest(request, “Execute”, async, function (resultXml) {            if (!async)                return resultXml;            else                callback(resultXml);            // ReSharper disable NotAllPathsReturnValue        });        // ReSharper restore NotAllPathsReturnValue    };

    var fetchMore = function (fetchCoreXml, pageNumber, pageCookie, fetchResults) {
        //Build new query        var moreFetchXml =                [                    “<fetch mapping=’logical’ page='” + pageNumber + “‘ count=’5000’ paging-cookie='” + pageCookie + “‘>”,                    fetchCore,                    “</fetch>”                ].join(“”);
        var moreMsgBody = “<query i:type=’a:FetchExpression’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts’>&#8221; +                            “<a:Query>” +                                crmXmlEncode(moreFetchXml) +                            “</a:Query>” +                        “</query>”;

        return doRequest(moreMsgBody, “RetrieveMultiple”, false, function (moreResultXml) {            var newFetchResult;            if (jQuery(moreResultXml).find(“a\\:Entities”).length != 0) {                newFetchResult = jQuery(moreResultXml).find(“a\\:Entities”).eq(0)[0];            } else {                newFetchResult = jQuery(moreResultXml).find(“Entities”).eq(0)[0]; //chrome            }
            var newMoreRecords;            if (jQuery(moreResultXml).find(“a\\:MoreRecords”).length != 0) {                newMoreRecords = jQuery(moreResultXml).find(“a\\:MoreRecords”).eq(0)[0].firstChild.text === “true”;            } else {                newMoreRecords = jQuery(moreResultXml).find(“MoreRecords”).eq(0)[0].firstChild.text === “true”; //chrome            }
            for (var iii = 0; iii < newFetchResult.childNodes.length; iii++) {                var entity = new businessEntity();
                entity.deserialize(newFetchResult.childNodes[iii]);                fetchResults.push(entity);            }
            if (newMoreRecords) {                pageNumber += 1;                var newPageCookie;                if (jQuery(moreResultXml).find(“a\\:PagingCookie”).length != 0) {                    newPageCookie = jQuery(moreResultXml).find(“a\\:PagingCookie”).eq(0)[0].firstChild.text.replace(/\”/g, ‘\”).replace(/</g, ‘&lt;’).replace(/>/g, ‘&gt;’).replace(/’/g, ‘&quot;’);                } else {                    newPageCookie = jQuery(moreResultXml).find(“PagingCookie”).eq(0)[0].firstChild.text.replace(/\”/g, ‘\”).replace(/</g, ‘&lt;’).replace(/>/g, ‘&gt;’).replace(/’/g, ‘&quot;’);                }
                fetchMore(fetchCore, pageNumber, newPageCookie, fetchResults);            } else {                return fetchResults;            }        });    };

    var fetch = function (fetchCore, fetchAll, callback) {        ///<summary>        /// Sends synchronous/asynchronous request to do a fetch request.        ///</summary>        ///<param name=”fetchCore” type=”String”>        /// A JavaScript String containing serialized XML using the FetchXML schema.        /// For efficiency, start with the “entity” node.        /// </param>        ///<param name=”callback” type=”Function”>        /// A Function used for asynchronous request. If not defined, it sends a synchronous request.        /// </param>
        var isAggregate = (fetchCore.indexOf(“aggregate”) !== -1);        if (fetchCore.slice(0, 6) === “<fetch”)        {            var fetchEntity = jQuery(xmlParser(fetchCore)).find(“entity”);
            if (fetchEntity.length < 1)            {                throw new Error(“XrmServiceToolkit.Fetch: No ‘entity’ node in the provided FetchXML.”);            }
            var fetchCoreDom = fetchEntity;
            try {                fetchCore = xmlToString(fetchCoreDom);            }            catch (error)            {                if (fetchCoreDom.xml)                {                    fetchCore = fetchCoreDom.xml;                }                else                {                    throw new Error(“XrmServiceToolkit.Fetch: This client does not provide the necessary XML features to continue.”);                }            }        }
        var fetchXml =                [                    “<fetch mapping=’logical'”,                    (isAggregate)? ” aggregate=’true’>” : “>”,                    fetchCore,                    “</fetch>”                ].join(“”);
        var msgBody = “<query i:type=’a:FetchExpression’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts’>&#8221; +                            “<a:Query>” +                                crmXmlEncode(fetchXml) +                            “</a:Query>” +                        “</query>”;        var async = !!callback;
        return doRequest(msgBody, “RetrieveMultiple”, !!callback, function (resultXml) {            var fetchResult;            if (jQuery(resultXml).find(“a\\:Entities”).length != 0) {                fetchResult = jQuery(resultXml).find(“a\\:Entities”).eq(0)[0];            } else {                fetchResult = jQuery(resultXml).find(“Entities”).eq(0)[0]; //chrome could not load node            }
            if (jQuery(resultXml).find(“a\\:MoreRecords”).length != 0)            {                moreRecords = jQuery(resultXml).find(“a\\:MoreRecords”).eq(0)[0].firstChild.text === “true”;            } else            {                moreRecords = jQuery(resultXml).find(“MoreRecords”).eq(0)[0].firstChild.text === “true”; //chrome            }
            var fetchResults = [];
            for (var ii = 0; ii < fetchResult.childNodes.length; ii++)            {                var entity = new businessEntity();
                entity.deserialize(fetchResult.childNodes[ii]);                fetchResults.push(entity);            }
            if (fetchAll && moreRecords)            {                var pageNumber = 2;                var pageCookie;
                if (jQuery(resultXml).find(“a\\:PagingCookie”).length != 0)                {                    pageCookie = jQuery(resultXml).find(“a\\:PagingCookie”).eq(0)[0].firstChild.text.replace(/\”/g, ‘\”).replace(/</g, ‘&lt;’).replace(/>/g, ‘&gt;’).replace(/’/g, ‘&quot;’);                } else                {                    pageCookie = jQuery(resultXml).find(“PagingCookie”).eq(0)[0].firstChild.text.replace(/\”/g, ‘\”).replace(/</g, ‘&lt;’).replace(/>/g, ‘&gt;’).replace(/’/g, ‘&quot;’);                }
                fetchMore(fetchCore, pageNumber, pageCookie, fetchResults);            }
            if (!async)                return fetchResults;            else                callback(fetchResults);            // ReSharper disable NotAllPathsReturnValue        });        // ReSharper restore NotAllPathsReturnValue    };
    var retrieve = function (entityName, id, columnSet, callback) {        ///<summary>        /// Sends synchronous/asynchronous request to retrieve a record.        ///</summary>        ///<param name=”entityName” type=”String”>        /// A JavaScript String corresponding to the Schema name of        /// entity that is used for retrieve operations.        /// </param>        ///<param name=”id” type=”String”>        /// A JavaScript String corresponding to the GUID of        /// entity that is used for retrieve operations.        /// </param>        ///<param name=”columnSet” type=”Array”>        /// A JavaScript Array corresponding to the attributes of        /// entity that is used for retrieve operations.        /// </param>        ///<param name=”callback” type=”Function”>        /// A Function used for asynchronous request. If not defined, it sends a synchronous request.        /// </param>        var attributes = “”;        // ReSharper disable AssignedValueIsNeverUsed        var query = “”;        // ReSharper restore AssignedValueIsNeverUsed        if (columnSet != null) {            for (var i = 0; i < columnSet.length; i++) {                attributes += “<b:string>” + columnSet[i] + “</b:string>”;            }            query = “<a:AllColumns>false</a:AllColumns>” +                    “<a:Columns xmlns:b=’http://schemas.microsoft.com/2003/10/Serialization/Arrays’>&#8221; +                        attributes +                    “</a:Columns>”;        }        else {            query = “<a:AllColumns>true</a:AllColumns><a:Columns xmlns:b=’http://schemas.microsoft.com/2003/10/Serialization/Arrays&#8217; />”;        }
        var msgBody =            [                “<entityName>”, entityName, “</entityName>”,                “<id>”, id, “</id>”,                “<columnSet xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts’>&#8221;,                    query,                “</columnSet>”            ].join(“”);
        var async = !!callback;
        return doRequest(msgBody, “Retrieve”, !!callback, function (resultXml) {            var retrieveResult = jQuery(resultXml).find(“RetrieveResult”).eq(0)[0];            var entity = new businessEntity();            entity.deserialize(retrieveResult);
            if (!async)                return entity;            else                callback(entity);            // ReSharper disable NotAllPathsReturnValue        });        // ReSharper restore NotAllPathsReturnValue    };
    var retrieveMultiple = function (query, callback) {        ///<summary>        /// Sends synchronous/asynchronous request to do a retrieveMultiple request.        ///</summary>        ///<param name=”query” type=”String”>        /// A JavaScript String with properties corresponding to the retrievemultiple request        /// that are valid for retrievemultiple operations.        /// </param>        ///<param name=”callback” type=”Function”>        /// A Function used for asynchronous request. If not defined, it sends a synchronous request.        /// </param>        var msgBody =                [                    “<query i:type=’a:QueryExpression’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts’>&#8221;, query, “</query>”                ].join(“”);
        var async = !!callback;
        return doRequest(msgBody, “RetrieveMultiple”, async, function (resultXml) {            var resultNodes;
            if (jQuery(resultXml).find(“a\\:Entities”).length != 0) {                resultNodes = jQuery(resultXml).find(“a\\:Entities”).eq(0)[0];            } else {                resultNodes = jQuery(resultXml).find(“Entities”).eq(0)[0]; //chrome could not load node properly            }            var retriveMultipleResults = [];
            for (var i = 0; i < resultNodes.childNodes.length; i++) {                var entity = new businessEntity();
                entity.deserialize(resultNodes.childNodes[i]);                retriveMultipleResults[i] = entity;            }
            if (!async)                return retriveMultipleResults;            else                callback(retriveMultipleResults);            // ReSharper disable NotAllPathsReturnValue        });        // ReSharper restore NotAllPathsReturnValue    };
    var joinArray = function (prefix, array, suffix) {        var output = [];        for (var i = 0; i < array.length; i++) {            if (array[i] != ” && array[i] != undefined) {                output.push(prefix, array[i], suffix);            }        }        return output.join(“”);    };
    var joinConditionPair = function (attributes, values) {        var output = [];        for (var i = 0; i < attributes.length; i++) {            if (attributes[i] != ”) {                if (typeof values[i] == typeof [])                {                    output.push(“<condition attribute='”, attributes[i], “‘ operator=’in’ >”);
                    for (var valueIndex in values[i])                    {                        var value = encodeValue(values[i][valueIndex]);                        output.push(“<value>” + value + “</value>”);                    }
                    output.push(“</condition>”);                }                else if (typeof values[i] == typeof “”)                {                    output.push(“<condition attribute='”, attributes[i], “‘ operator=’eq’ value='”, encodeValue(values[i]), “‘ />”);                }            }        }        return output.join(“”);    };
    var isArray = function (input) {        return input.constructor.toString().indexOf(“Array”) != -1;    };
    var queryByAttribute = function (queryOptions, callback) {        ///<summary>        /// Sends synchronous/asynchronous request to do a queryByAttribute request.        ///</summary>        ///<param name=”queryOptions” type=”Object”>        /// A JavaScript Object with properties corresponding to the queryByAttribute Criteria        /// that are valid for queryByAttribute operations.        /// queryOptions.entityName is a string represents the name of the entity        /// queryOptions.attributes is a array represents the attributes of the entity to query        /// queryOptions.values is a array represents the values of the attributes to query        /// queryOptions.columnSet is a array represents the attributes of the entity to return        /// queryOptions.orderBy is a array represents the order conditions of the results        /// </param>        ///<param name=”callback” type=”Function”>        /// A Function used for asynchronous request. If not defined, it sends a synchronous request.        /// </param>        var entityName = queryOptions.entityName;        var attributes = queryOptions.attributes;        var values = queryOptions.values;        var columnSet = queryOptions.columnSet;        var orderBy = queryOptions.orderBy || ”;
        attributes = isArray(attributes) ? attributes : [attributes];        values = isArray(values) ? values : [values];        orderBy = (!!orderBy && isArray(orderBy)) ? orderBy : [orderBy];        columnSet = (!!columnSet && isArray(columnSet)) ? columnSet : [columnSet];
        var xml =                [                    ”   <entity name='”, entityName, “‘>”,                           joinArray(“<attribute name='”, columnSet, “‘ />”),                           joinArray(“<order attribute='”, orderBy, “‘ />”),                    ”      <filter>”,                              joinConditionPair(attributes, values),                    ”      </filter>”,                    ”   </entity>”                ].join(“”);
        return fetch(xml, false, callback);    };
    var queryAll = function (queryOptions, callback) {        ///<summary>        /// Sends synchronous/asynchronous request to do a queryAll request. This is to return all records (>5k+).        /// Consider Performance impact when using this method.        ///</summary>        ///<param name=”queryOptions” type=”Object”>        /// A JavaScript Object with properties corresponding to the queryByAttribute Criteria        /// that are valid for queryByAttribute operations.        /// queryOptions.entityName is a string represents the name of the entity        /// queryOptions.attributes is a array represents the attributes of the entity to query        /// queryOptions.values is a array represents the values of the attributes to query        /// queryOptions.columnSet is a array represents the attributes of the entity to return        /// queryOptions.orderBy is a array represents the order conditions of the results        /// </param>        ///<param name=”callback” type=”Function”>        /// A Function used for asynchronous request. If not defined, it sends a synchronous request.        /// </param>        var entityName = queryOptions.entityName;        var attributes = queryOptions.attributes;        var values = queryOptions.values;        var columnSet = queryOptions.columnSet;        var orderBy = queryOptions.orderBy || ”;
        attributes = isArray(attributes) ? attributes : [attributes];        values = isArray(values) ? values : [values];        orderBy = (!!orderBy && isArray(orderBy)) ? orderBy : [orderBy];        columnSet = (!!columnSet && isArray(columnSet)) ? columnSet : [columnSet];
        var fetchCore = [                    ”   <entity name='”, entityName, “‘>”,                           joinArray(“<attribute name='”, columnSet, “‘ />”),                           joinArray(“<order attribute='”, orderBy, “‘ />”),                    ”      <filter>”,                              joinConditionPair(attributes, values),                    ”      </filter>”,                    ”   </entity>”        ].join(“”);

        var async = !!callback;
        return fetch(fetchCore, true, async);    };
    var setState = function (entityName, id, stateCode, statusCode, callback) {        ///<summary>        /// Sends synchronous/asynchronous request to setState of a record.        ///</summary>        ///<param name=”entityName” type=”String”>        /// A JavaScript String corresponding to the Schema name of        /// entity that is used for setState operations.        /// </param>        ///<param name=”id” type=”String”>        /// A JavaScript String corresponding to the GUID of        /// entity that is used for setState operations.        /// </param>        ///<param name=”stateCode” type=”Int”>        /// A JavaScript Integer corresponding to the value of        /// entity state that is used for setState operations.        /// </param>        ///<param name=”statusCode” type=”Int”>        /// A JavaScript Integer corresponding to the value of        /// entity status that is used for setState operations.        /// </param>        ///<param name=”callback” type=”Function”>        /// A Function used for asynchronous request. If not defined, it sends a synchronous request.        /// </param>        var request = [            “<request i:type=’b:SetStateRequest’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts&#8217; xmlns:b=’http://schemas.microsoft.com/crm/2011/Contracts’>&#8221;,                “<a:Parameters xmlns:c=’http://schemas.datacontract.org/2004/07/System.Collections.Generic’>&#8221;,                    “<a:KeyValuePairOfstringanyType>”,                        “<c:key>EntityMoniker</c:key>”,                        “<c:value i:type=’a:EntityReference’>”,                          “<a:Id>”, id, “</a:Id>”,                          “<a:LogicalName>”, entityName, “</a:LogicalName>”,                          “<a:Name i:nil=’true’ />”,                        “</c:value>”,                      “</a:KeyValuePairOfstringanyType>”,                      “<a:KeyValuePairOfstringanyType>”,                        “<c:key>State</c:key>”,                        “<c:value i:type=’a:OptionSetValue’>”,                          “<a:Value>”, stateCode.toString(), “</a:Value>”,                        “</c:value>”,                      “</a:KeyValuePairOfstringanyType>”,                      “<a:KeyValuePairOfstringanyType>”,                        “<c:key>Status</c:key>”,                        “<c:value i:type=’a:OptionSetValue’>”,                          “<a:Value>”, statusCode.toString(), “</a:Value>”,                        “</c:value>”,                      “</a:KeyValuePairOfstringanyType>”,                “</a:Parameters>”,                “<a:RequestId i:nil=’true’ />”,                “<a:RequestName>SetState</a:RequestName>”,            “</request>”        ].join(“”);
        var async = !!callback;
        return doRequest(request, “Execute”, async, function (resultXml) {            var response = jQuery(resultXml).find(‘ExecuteResult’).eq(0);            var result = crmXmlDecode(response.text());            if (!async)                return result;            else                callback(result);            // ReSharper disable NotAllPathsReturnValue        });        // ReSharper restore NotAllPathsReturnValue    };
    var associate = function (relationshipName, targetEntityName, targetId, relatedEntityName, relatedBusinessEntities, callback) {        ///<summary>        /// Sends synchronous/asynchronous request to associate records.        ///</summary>        ///<param name=”relationshipName” type=”String”>        /// A JavaScript String corresponding to the relationship name        /// that is used for associate operations.        /// </param>        ///<param name=”targetEntityName” type=”String”>        /// A JavaScript String corresponding to the schema name of the target entity        /// that is used for associate operations.        /// </param>        ///<param name=”targetId” type=”String”>        /// A JavaScript String corresponding to the GUID of the target entity        /// that is used for associate operations.        /// </param>        ///<param name=”relatedEntityName” type=”String”>        /// A JavaScript String corresponding to the schema name of the related entity        /// that is used for associate operations.        /// </param>        ///<param name=”relationshipBusinessEntities” type=”Array”>        /// A JavaScript Array corresponding to the collection of the related entities as BusinessEntity        /// that is used for associate operations.        /// </param>        ///<param name=”callback” type=”Function”>        /// A Function used for asynchronous request. If not defined, it sends a synchronous request.        /// </param>        var relatedEntities = relatedBusinessEntities;
        relatedEntities = isArray(relatedEntities) ? relatedEntities : [relatedEntities];
        var output = [];        for (var i = 0; i < relatedEntities.length; i++) {            if (relatedEntities[i].id != ”) {                output.push(“<a:EntityReference>”,                                “<a:Id>”, relatedEntities[i].id, “</a:Id>”,                                “<a:LogicalName>”, relatedEntityName, “</a:LogicalName>”,                                “<a:Name i:nil=’true’ />”,                            “</a:EntityReference>”);            }        }
        var relatedXml = output.join(“”);
        var request = [            “<request i:type=’a:AssociateRequest’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts’>&#8221;,                “<a:Parameters xmlns:b=’http://schemas.datacontract.org/2004/07/System.Collections.Generic’>&#8221;,                    “<a:KeyValuePairOfstringanyType>”,                        “<b:key>Target</b:key>”,                        “<b:value i:type=’a:EntityReference’>”,                            “<a:Id>”, targetId, “</a:Id>”,                            “<a:LogicalName>”, targetEntityName, “</a:LogicalName>”,                            “<a:Name i:nil=’true’ />”,                        “</b:value>”,                    “</a:KeyValuePairOfstringanyType>”,                    “<a:KeyValuePairOfstringanyType>”,                        “<b:key>Relationship</b:key>”,                        “<b:value i:type=’a:Relationship’>”,                            “<a:PrimaryEntityRole i:nil=’true’ />”,                            “<a:SchemaName>”, relationshipName, “</a:SchemaName>”,                        “</b:value>”,                    “</a:KeyValuePairOfstringanyType>”,                    “<a:KeyValuePairOfstringanyType>”,                    “<b:key>RelatedEntities</b:key>”,                    “<b:value i:type=’a:EntityReferenceCollection’>”,                        relatedXml,                    “</b:value>”,                    “</a:KeyValuePairOfstringanyType>”,                “</a:Parameters>”,                “<a:RequestId i:nil=’true’ />”,                “<a:RequestName>Associate</a:RequestName>”,            “</request>”        ].join(“”);
        var async = !!callback;
        return doRequest(request, “Execute”, async, function (resultXml) {            var response = jQuery(resultXml).find(‘ExecuteResult’).eq(0);            var result = crmXmlDecode(response.text());            if (!async)                return result;            else                callback(result);            // ReSharper disable NotAllPathsReturnValue        });        // ReSharper restore NotAllPathsReturnValue    };
    var disassociate = function (relationshipName, targetEntityName, targetId, relatedEntityName, relatedBusinessEntities, callback) {        ///<summary>        /// Sends synchronous/asynchronous request to disassociate records.        ///</summary>        ///<param name=”relationshipName” type=”String”>        /// A JavaScript String corresponding to the relationship name        /// that is used for disassociate operations.        /// </param>        ///<param name=”targetEntityName” type=”String”>        /// A JavaScript String corresponding to the schema name of the target entity        /// that is used for disassociate operations.        /// </param>        ///<param name=”targetId” type=”String”>        /// A JavaScript String corresponding to the GUID of the target entity        /// that is used for disassociate operations.        /// </param>        ///<param name=”relatedEntityName” type=”String”>        /// A JavaScript String corresponding to the schema name of the related entity        /// that is used for disassociate operations.        /// </param>        ///<param name=”relationshipBusinessEntities” type=”Array”>        /// A JavaScript Array corresponding to the collection of the related entities as BusinessEntity        /// that is used for disassociate operations.        /// </param>        ///<param name=”callback” type=”Function”>        /// A Function used for asynchronous request. If not defined, it sends a synchronous request.        /// </param>        var relatedEntities = relatedBusinessEntities;
        relatedEntities = isArray(relatedEntities) ? relatedEntities : [relatedEntities];
        var output = [];        for (var i = 0; i < relatedEntities.length; i++) {            if (relatedEntities[i].id != ”) {                output.push(“<a:EntityReference>”,                                “<a:Id>”, relatedEntities[i].id, “</a:Id>”,                                “<a:LogicalName>”, relatedEntityName, “</a:LogicalName>”,                                “<a:Name i:nil=’true’ />”,                            “</a:EntityReference>”);            }        }
        var relatedXml = output.join(“”);
        var request = [            “<request i:type=’a:DisassociateRequest’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts’>&#8221;,                “<a:Parameters xmlns:b=’http://schemas.datacontract.org/2004/07/System.Collections.Generic’>&#8221;,                    “<a:KeyValuePairOfstringanyType>”,                        “<b:key>Target</b:key>”,                        “<b:value i:type=’a:EntityReference’>”,                            “<a:Id>”, targetId, “</a:Id>”,                            “<a:LogicalName>”, targetEntityName, “</a:LogicalName>”,                            “<a:Name i:nil=’true’ />”,                        “</b:value>”,                    “</a:KeyValuePairOfstringanyType>”,                    “<a:KeyValuePairOfstringanyType>”,                        “<b:key>Relationship</b:key>”,                        “<b:value i:type=’a:Relationship’>”,                            “<a:PrimaryEntityRole i:nil=’true’ />”,                            “<a:SchemaName>”, relationshipName, “</a:SchemaName>”,                        “</b:value>”,                    “</a:KeyValuePairOfstringanyType>”,                    “<a:KeyValuePairOfstringanyType>”,                    “<b:key>RelatedEntities</b:key>”,                    “<b:value i:type=’a:EntityReferenceCollection’>”,                        relatedXml,                    “</b:value>”,                    “</a:KeyValuePairOfstringanyType>”,                “</a:Parameters>”,                “<a:RequestId i:nil=’true’ />”,                “<a:RequestName>Disassociate</a:RequestName>”,            “</request>”        ].join(“”);
        var async = !!callback;
        return doRequest(request, “Execute”, async, function (resultXml) {            var response = jQuery(resultXml).find(‘ExecuteResult’).eq(0);            var result = crmXmlDecode(response.text());            if (!async)                return result;            else                callback(result);            // ReSharper disable NotAllPathsReturnValue        });        // ReSharper restore NotAllPathsReturnValue    };
    var getCurrentUserId = function () {        ///<summary>        /// Sends synchronous request to retrieve the GUID of the current user.        ///</summary>        var request = “<request i:type=’b:WhoAmIRequest’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts&#8217; xmlns:b=’http://schemas.microsoft.com/crm/2011/Contracts’>&#8221; +                        “<a:Parameters xmlns:c=’http://schemas.datacontract.org/2004/07/System.Collections.Generic&#8217; />” +                        “<a:RequestId i:nil=’true’ />” +                        “<a:RequestName>WhoAmI</a:RequestName>” +                      “</request>”;        var xmlDoc = doRequest(request, “Execute”);        if (jQuery(xmlDoc).find(‘a\\:Results’).length != 0) {            return jQuery(xmlDoc).find(‘a\\:Results’).children().eq(0).children().eq(1).text();        } else {            return jQuery(xmlDoc).find(‘Results’).children().eq(0).children().eq(1).text(); //Chrome 24.0.1312.52 could not find node by the previous code        }
    };
    var getCurrentUserBusinessUnitId = function () {        ///<summary>        /// Sends synchronous request to retrieve the GUID of the current user’s business unit.        ///</summary>        var request = “<request i:type=’b:WhoAmIRequest’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts&#8217; xmlns:b=’http://schemas.microsoft.com/crm/2011/Contracts’>&#8221; +                        “<a:Parameters xmlns:c=’http://schemas.datacontract.org/2004/07/System.Collections.Generic&#8217; />” +                        “<a:RequestId i:nil=’true’ />” +                        “<a:RequestName>WhoAmI</a:RequestName>” +                      “</request>”;        var xmlDoc = doRequest(request, “Execute”);
        if (jQuery(xmlDoc).find(‘a\\:Results’).length != 0) {            return jQuery(xmlDoc).find(‘a\\:Results’).children().eq(1).children().eq(1).text();        } else {            return jQuery(xmlDoc).find(‘Results’).children().eq(1).children().eq(1).text(); //Chrome 24.0.1312.52 could not find node by the previous code        }    };
    var getCurrentUserRoles = function () {        ///<summary>        /// Sends synchronous request to retrieve the list of the current user’s roles.        ///</summary>        var xml =                [                    “<fetch version=’1.0′ output-format=’xml-platform’ mapping=’logical’ distinct=’true’>” +                      “<entity name=’role’>” +                        “<attribute name=’name’ />” +                        “<attribute name=’businessunitid’ />” +                        “<attribute name=’roleid’ />” +                        “<order attribute=’name’ descending=’false’ />” +                        “<link-entity name=’systemuserroles’ from=’roleid’ to=’roleid’ visible=’false’ intersect=’true’>” +                          “<link-entity name=’systemuser’ from=’systemuserid’ to=’systemuserid’ alias=’aa’>” +                            “<filter type=’and’>” +                              “<condition attribute=’systemuserid’ operator=’eq-userid’ />” +                            “</filter>” +                          “</link-entity>” +                        “</link-entity>” +                      “</entity>” +                    “</fetch>”                ].join(“”);
        var fetchResult = fetch(xml);        var roles = [];
        if (fetchResult !== null && typeof fetchResult != ‘undefined’) {            for (var i = 0; i < fetchResult.length; i++) {                roles[i] = fetchResult[i].attributes[“name”].value;            }        }
        return roles;    };
    var isCurrentUserInRole = function () {        ///<summary>        /// Sends synchronous request to check if the current user has certain roles        /// Passes name of role as arguments. For example, IsCurrentUserInRole(‘System Administrator’)        /// Returns true or false.        ///</summary>        var roles = getCurrentUserRoles();        for (var i = 0; i < roles.length; i++) {            for (var j = 0; j < arguments.length; j++) {                if (roles[i] === arguments[j]) {                    return true;                }            }        }
        return false;    };
    var assign = function (targetEntityName, targetId, assigneeEntityName, assigneeId, callback) {        ///<summary>        /// Sends synchronous/asynchronous request to assign an existing record to a user / a team.        ///</summary>        ///<param name=”targetEntityName” type=”String”>        /// A JavaScript String corresponding to the schema name of the target entity        /// that is used for assign operations.        /// </param>        ///<param name=”targetId” type=”String”>        /// A JavaScript String corresponding to the GUID of the target entity        /// that is used for assign operations.        /// </param>        ///<param name=”assigneeEntityName” type=”String”>        /// A JavaScript String corresponding to the schema name of the assignee entity        /// that is used for assign operations.        /// </param>        ///<param name=”assigneeId” type=”String”>        /// A JavaScript String corresponding to the GUID of the assignee entity        /// that is used for assign operations.        /// </param>        ///<param name=”callback” type=”Function”>        /// A Function used for asynchronous request. If not defined, it sends a synchronous request.        /// </param>
        var request = “<request i:type=’b:AssignRequest’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts&#8217; xmlns:b=’http://schemas.microsoft.com/crm/2011/Contracts’>&#8221; +                        “<a:Parameters xmlns:c=’http://schemas.datacontract.org/2004/07/System.Collections.Generic’>&#8221; +                          “<a:KeyValuePairOfstringanyType>” +                            “<c:key>Target</c:key>” +                            “<c:value i:type=’a:EntityReference’>” +                              “<a:Id>” + targetId + “</a:Id>” +                              “<a:LogicalName>” + targetEntityName + “</a:LogicalName>” +                              “<a:Name i:nil=’true’ />” +                            “</c:value>” +                          “</a:KeyValuePairOfstringanyType>” +                          “<a:KeyValuePairOfstringanyType>” +                            “<c:key>Assignee</c:key>” +                            “<c:value i:type=’a:EntityReference’>” +                              “<a:Id>” + assigneeId + “</a:Id>” +                              “<a:LogicalName>” + assigneeEntityName + “</a:LogicalName>” +                              “<a:Name i:nil=’true’ />” +                            “</c:value>” +                          “</a:KeyValuePairOfstringanyType>” +                        “</a:Parameters>” +                        “<a:RequestId i:nil=’true’ />” +                        “<a:RequestName>Assign</a:RequestName>” +                      “</request>”;        var async = !!callback;
        return doRequest(request, “Execute”, async, function (resultXml) {            var response = jQuery(resultXml).find(‘ExecuteResult’).eq(0);            var result = crmXmlDecode(response.text());            if (!async)                return result;            else                callback(result);            // ReSharper disable NotAllPathsReturnValue        });        // ReSharper restore NotAllPathsReturnValue    };
    var grantAccess = function (accessOptions, callback) {        ///<summary>        /// Sends synchronous/asynchronous request to do a grantAccess request.        /// Levels of Access Options are: AppendAccess, AppendToAccess, AssignAccess, CreateAccess, DeleteAccess, None, ReadAccess, ShareAccess, and WriteAccess        ///</summary>        ///<param name=”accessOptions” type=”Object”>        /// A JavaScript Object with properties corresponding to the grantAccess Criteria        /// that are valid for grantAccess operations.        /// accessOptions.targetEntityName is a string represents the name of the target entity        /// accessOptions.targetEntityId is a string represents the GUID of the target entity        /// accessOptions.principalEntityName is a string represents the name of the principal entity        /// accessOptions.principalEntityId is a string represents the GUID of the principal entity        /// accessOptions.accessRights is a array represents the access conditions of the results        /// </param>        ///<param name=”callback” type=”Function”>        /// A Function used for asynchronous request. If not defined, it sends a synchronous request.        /// </param>
        var targetEntityName = accessOptions.targetEntityName;        var targetEntityId = accessOptions.targetEntityId;        var principalEntityName = accessOptions.principalEntityName;        var principalEntityId = accessOptions.principalEntityId;        var accessRights = accessOptions.accessRights;
        accessRights = isArray(accessRights) ? accessRights : [accessRights];
        var accessRightString = “”;        for (var i = 0; i < accessRights.length; i++) {            accessRightString += encodeValue(accessRights[i]) + ” “;        }
        var request = “<request i:type=’b:GrantAccessRequest’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts&#8217; xmlns:b=’http://schemas.microsoft.com/crm/2011/Contracts’>&#8221; +                    “<a:Parameters xmlns:c=’http://schemas.datacontract.org/2004/07/System.Collections.Generic’>&#8221; +                      “<a:KeyValuePairOfstringanyType>” +                    “<c:key>Target</c:key>” +                    “<c:value i:type=’a:EntityReference’>” +                      “<a:Id>” + targetEntityId + “</a:Id>” +                      “<a:LogicalName>” + targetEntityName + “</a:LogicalName>” +                      “<a:Name i:nil=’true’ />” +                    “</c:value>” +                      “</a:KeyValuePairOfstringanyType>” +                      “<a:KeyValuePairOfstringanyType>” +                    “<c:key>PrincipalAccess</c:key>” +                    “<c:value i:type=’b:PrincipalAccess’>” +                      “<b:AccessMask>” + accessRightString + “</b:AccessMask>” +                      “<b:Principal>” +                    “<a:Id>” + principalEntityId + “</a:Id>” +                    “<a:LogicalName>” + principalEntityName + “</a:LogicalName>” +                    “<a:Name i:nil=’true’ />” +                      “</b:Principal>” +                    “</c:value>” +                      “</a:KeyValuePairOfstringanyType>” +                    “</a:Parameters>” +                    “<a:RequestId i:nil=’true’ />” +                    “<a:RequestName>GrantAccess</a:RequestName>” +                    “</request>”;        var async = !!callback;
        return doRequest(request, “Execute”, async, function (resultXml) {            var response = jQuery(resultXml).find(‘ExecuteResult’).eq(0);            var result = crmXmlDecode(response.text());            if (!async)                return result;            else                callback(result);            // ReSharper disable NotAllPathsReturnValue        });        // ReSharper restore NotAllPathsReturnValue    };
    var modifyAccess = function (accessOptions, callback) {        ///<summary>        /// Sends synchronous/asynchronous request to do a modifyAccess request.        /// Levels of Access Options are: AppendAccess, AppendToAccess, AssignAccess, CreateAccess, DeleteAccess, None, ReadAccess, ShareAccess, and WriteAccess        ///</summary>        ///<param name=”accessOptions” type=”Object”>        /// A JavaScript Object with properties corresponding to the modifyAccess Criteria        /// that are valid for modifyAccess operations.        /// accessOptions.targetEntityName is a string represents the name of the target entity        /// accessOptions.targetEntityId is a string represents the GUID of the target entity        /// accessOptions.principalEntityName is a string represents the name of the principal entity        /// accessOptions.principalEntityId is a string represents the GUID of the principal entity        /// accessOptions.accessRights is a array represents the access conditions of the results        /// </param>        ///<param name=”callback” type=”Function”>        /// A Function used for asynchronous request. If not defined, it sends a synchronous request.        /// </param>
        var targetEntityName = accessOptions.targetEntityName;        var targetEntityId = accessOptions.targetEntityId;        var principalEntityName = accessOptions.principalEntityName;        var principalEntityId = accessOptions.principalEntityId;        var accessRights = accessOptions.accessRights;
        accessRights = isArray(accessRights) ? accessRights : [accessRights];
        var accessRightString = “”;        for (var i = 0; i < accessRights.length; i++) {            accessRightString += encodeValue(accessRights[i]) + ” “;        }
        var request = “<request i:type=’b:ModifyAccessRequest’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts&#8217; xmlns:b=’http://schemas.microsoft.com/crm/2011/Contracts’>&#8221; +                    “<a:Parameters xmlns:c=’http://schemas.datacontract.org/2004/07/System.Collections.Generic’>&#8221; +                      “<a:KeyValuePairOfstringanyType>” +                    “<c:key>Target</c:key>” +                    “<c:value i:type=’a:EntityReference’>” +                      “<a:Id>” + targetEntityId + “</a:Id>” +                      “<a:LogicalName>” + targetEntityName + “</a:LogicalName>” +                      “<a:Name i:nil=’true’ />” +                    “</c:value>” +                      “</a:KeyValuePairOfstringanyType>” +                      “<a:KeyValuePairOfstringanyType>” +                    “<c:key>PrincipalAccess</c:key>” +                    “<c:value i:type=’b:PrincipalAccess’>” +                      “<b:AccessMask>” + accessRightString + “</b:AccessMask>” +                      “<b:Principal>” +                    “<a:Id>” + principalEntityId + “</a:Id>” +                    “<a:LogicalName>” + principalEntityName + “</a:LogicalName>” +                    “<a:Name i:nil=’true’ />” +                      “</b:Principal>” +                    “</c:value>” +                      “</a:KeyValuePairOfstringanyType>” +                    “</a:Parameters>” +                    “<a:RequestId i:nil=’true’ />” +                    “<a:RequestName>ModifyAccess</a:RequestName>” +                    “</request>”;        var async = !!callback;
        return doRequest(request, “Execute”, async, function (resultXml) {            var response = jQuery(resultXml).find(‘ExecuteResult’).eq(0);            var result = crmXmlDecode(response.text());            if (!async)                return result;            else                callback(result);            // ReSharper disable NotAllPathsReturnValue        });        // ReSharper restore NotAllPathsReturnValue    };
    var revokeAccess = function (accessOptions, callback) {        ///<summary>        /// Sends synchronous/asynchronous request to do a revokeAccess request.        ///</summary>        ///<param name=”accessOptions” type=”Object”>        /// A JavaScript Object with properties corresponding to the revokeAccess Criteria        /// that are valid for revokeAccess operations.        /// accessOptions.targetEntityName is a string represents the name of the target entity        /// accessOptions.targetEntityId is a string represents the GUID of the target entity        /// accessOptions.revokeeEntityName is a string represents the name of the revokee entity        /// accessOptions.revokeeEntityId is a string represents the GUID of the revokee entity        /// </param>        ///<param name=”callback” type=”Function”>        /// A Function used for asynchronous request. If not defined, it sends a synchronous request.        /// </param>
        var targetEntityName = accessOptions.targetEntityName;        var targetEntityId = accessOptions.targetEntityId;        var revokeeEntityName = accessOptions.revokeeEntityName;        var revokeeEntityId = accessOptions.revokeeEntityId;
        var request = “<request i:type=’b:RevokeAccessRequest’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts&#8217; xmlns:b=’http://schemas.microsoft.com/crm/2011/Contracts’>&#8221; +                    “<a:Parameters xmlns:c=’http://schemas.datacontract.org/2004/07/System.Collections.Generic’>&#8221; +                      “<a:KeyValuePairOfstringanyType>” +                    “<c:key>Target</c:key>” +                    “<c:value i:type=’a:EntityReference’>” +                      “<a:Id>” + targetEntityId + “</a:Id>” +                      “<a:LogicalName>” + targetEntityName + “</a:LogicalName>” +                      “<a:Name i:nil=’true’ />” +                    “</c:value>” +                      “</a:KeyValuePairOfstringanyType>” +                      “<a:KeyValuePairOfstringanyType>” +                    “<c:key>Revokee</c:key>” +                            “<c:value i:type=’a:EntityReference’>” +                              “<a:Id>” + revokeeEntityId + “</a:Id>” +                              “<a:LogicalName>” + revokeeEntityName + “</a:LogicalName>” +                              “<a:Name i:nil=’true’ />” +                            “</c:value>” +                      “</a:KeyValuePairOfstringanyType>” +                    “</a:Parameters>” +                    “<a:RequestId i:nil=’true’ />” +                    “<a:RequestName>RevokeAccess</a:RequestName>” +                    “</request>”;        var async = !!callback;
        return doRequest(request, “Execute”, async, function (resultXml) {            var response = jQuery(resultXml).find(‘ExecuteResult’).eq(0);            var result = crmXmlDecode(response.text());            if (!async)                return result;            else                callback(result);            // ReSharper disable NotAllPathsReturnValue        });        // ReSharper restore NotAllPathsReturnValue    };
    var retrievePrincipalAccess = function (accessOptions, callback) {        ///<summary>        /// Sends synchronous/asynchronous request to do a retrievePrincipalAccess request.        ///</summary>        ///<param name=”accessOptions” type=”Object”>        /// A JavaScript Object with properties corresponding to the retrievePrincipalAccess Criteria        /// that are valid for retrievePrincipalAccess operations.        /// accessOptions.targetEntityName is a string represents the name of the target entity        /// accessOptions.targetEntityId is a string represents the GUID of the target entity        /// accessOptions.principalEntityName is a string represents the name of the principal entity        /// accessOptions.principalEntityId is a string represents the GUID of the principal entity        /// </param>        ///<param name=”callback” type=”Function”>        /// A Function used for asynchronous request. If not defined, it sends a synchronous request.        /// </param>
        var targetEntityName = accessOptions.targetEntityName;        var targetEntityId = accessOptions.targetEntityId;        var principalEntityName = accessOptions.principalEntityName;        var principalEntityId = accessOptions.principalEntityId;
        var request = “<request i:type=’b:RetrievePrincipalAccessRequest’ xmlns:a=’http://schemas.microsoft.com/xrm/2011/Contracts&#8217; xmlns:b=’http://schemas.microsoft.com/crm/2011/Contracts’>&#8221; +                    “<a:Parameters xmlns:c=’http://schemas.datacontract.org/2004/07/System.Collections.Generic’>&#8221; +                      “<a:KeyValuePairOfstringanyType>” +                    “<c:key>Target</c:key>” +                    “<c:value i:type=’a:EntityReference’>” +                      “<a:Id>” + targetEntityId + “</a:Id>” +                      “<a:LogicalName>” + targetEntityName + “</a:LogicalName>” +                      “<a:Name i:nil=’true’ />” +                    “</c:value>” +                      “</a:KeyValuePairOfstringanyType>” +                      “<a:KeyValuePairOfstringanyType>” +                    “<c:key>Principal</c:key>” +                            “<c:value i:type=’a:EntityReference’>” +                              “<a:Id>” + principalEntityId + “</a:Id>” +                              “<a:LogicalName>” + principalEntityName + “</a:LogicalName>” +                              “<a:Name i:nil=’true’ />” +                            “</c:value>” +                      “</a:KeyValuePairOfstringanyType>” +                    “</a:Parameters>” +                    “<a:RequestId i:nil=’true’ />” +                    “<a:RequestName>RetrievePrincipalAccess</a:RequestName>” +                    “</request>”;        var async = !!callback;
        return doRequest(request, “Execute”, async, function (resultXml) {            var response;            if (jQuery(resultXml).find(‘c\\:value’).length != 0) {                response = jQuery(resultXml).find(‘c\\:value’).eq(0);            } else {                response = jQuery(resultXml).find(‘value’).eq(0);; //Chrome 24.0.1312.52 could not find node by the previous code            }            var result = crmXmlDecode(response.text());            if (!async)                return result;            else                callback(result);            // ReSharper disable NotAllPathsReturnValue        });        // ReSharper restore NotAllPathsReturnValue    };
    // Added in 1.4.1 for metadata retrieval     // Inspired From Microsoft SDK code to retrieve Metadata using JavaScript    // Copyright (C) Microsoft Corporation.  All rights reserved.    var arrayElements = [“Attributes”,                         “ManyToManyRelationships”,                         “ManyToOneRelationships”,                         “OneToManyRelationships”,                         “Privileges”,                         “LocalizedLabels”,                         “Options”,                         “Targets”];
    var isMetadataArray = function (elementName) {        for (var i = 0; i < arrayElements.length; i++) {            if (elementName === arrayElements[i]) {                return true;            }        }        return false;    };
    var getNodeName = function (node) {        if (typeof (node.baseName) != “undefined”) {            return node.baseName;        }        else {            return node.localName;        }    };
    var objectifyNode = function (node) {        //Check for null        if (node.attributes != null && node.attributes.length == 1) {            if (node.attributes.getNamedItem(“i:nil”) != null && node.attributes.getNamedItem(“i:nil”).nodeValue == “true”) {                return null;            }        }
        //Check if it is a value        if ((node.firstChild != null) && (node.firstChild.nodeType == 3)) {            var nodeName = getNodeName(node);
            switch (nodeName) {                //Integer Values                        case “ActivityTypeMask”:                case “ObjectTypeCode”:                case “ColumnNumber”:                case “DefaultFormValue”:                case “MaxValue”:                case “MinValue”:                case “MaxLength”:                case “Order”:                case “Precision”:                case “PrecisionSource”:                case “LanguageCode”:                    return parseInt(node.firstChild.nodeValue, 10);                    // Boolean values                case “AutoRouteToOwnerQueue”:                case “CanBeChanged”:                case “CanTriggerWorkflow”:                case “IsActivity”:                case “IsActivityParty”:                case “IsAvailableOffline”:                case “IsChildEntity”:                case “IsCustomEntity”:                case “IsCustomOptionSet”:                case “IsDocumentManagementEnabled”:                case “IsEnabledForCharts”:                case “IsGlobal”:                case “IsImportable”:                case “IsIntersect”:                case “IsManaged”:                case “IsReadingPaneEnabled”:                case “IsValidForAdvancedFind”:                case “CanBeSecuredForCreate”:                case “CanBeSecuredForRead”:                case “CanBeSecuredForUpdate”:                case “IsCustomAttribute”:                case “IsPrimaryId”:                case “IsPrimaryName”:                case “IsSecured”:                case “IsValidForCreate”:                case “IsValidForRead”:                case “IsValidForUpdate”:                case “IsCustomRelationship”:                case “CanBeBasic”:                case “CanBeDeep”:                case “CanBeGlobal”:                case “CanBeLocal”:                    return (node.firstChild.nodeValue === “true”) ? true : false;                    //OptionMetadata.Value and BooleanManagedProperty.Value and AttributeRequiredLevelManagedProperty.Value                case “Value”:                    //BooleanManagedProperty.Value                    if ((node.firstChild.nodeValue === “true”) || (node.firstChild.nodeValue == “false”)) {                        return (node.firstChild.nodeValue == “true”) ? true : false;                    }                    //AttributeRequiredLevelManagedProperty.Value                    if (                          (node.firstChild.nodeValue == “ApplicationRequired”) ||                          (node.firstChild.nodeValue == “None”) ||                          (node.firstChild.nodeValue == “Recommended”) ||                          (node.firstChild.nodeValue == “SystemRequired”)                       ) {                        return node.firstChild.nodeValue;                    }                    else {                        //OptionMetadata.Value                        return parseInt(node.firstChild.nodeValue, 10);                    }                    // ReSharper disable JsUnreachableCode                    break;                // ReSharper restore JsUnreachableCode                   //String values                        default:                    return node.firstChild.nodeValue;            }
        }
        //Check if it is a known array        if (isMetadataArray(getNodeName(node))) {            var arrayValue = [];            for (var iii = 0; iii < node.childNodes.length; iii++) {                var objectTypeName;                if ((node.childNodes[iii].attributes != null) && (node.childNodes[iii].attributes.getNamedItem(“i:type”) != null)) {                    objectTypeName = node.childNodes[iii].attributes.getNamedItem(“i:type”).nodeValue.split(“:”)[1];                }                else {
                    objectTypeName = getNodeName(node.childNodes[iii]);                }
                var b = objectifyNode(node.childNodes[iii]);                b._type = objectTypeName;                arrayValue.push(b);
            }
            return arrayValue;        }
        //Null entity description labels are returned as <label/> – not using i:nil = true;        if (node.childNodes.length == 0) {            return null;        }
        //Otherwise return an object        var c = {};        if (node.attributes.getNamedItem(“i:type”) != null) {            c._type = node.attributes.getNamedItem(“i:type”).nodeValue.split(“:”)[1];        }        for (var i = 0; i < node.childNodes.length; i++) {            if (node.childNodes[i].nodeType == 3) {                c[getNodeName(node.childNodes[i])] = node.childNodes[i].nodeValue;            }            else {                c[getNodeName(node.childNodes[i])] = objectifyNode(node.childNodes[i]);            }
        }        return c;    };
    var retrieveAllEntitiesMetadata = function (entityFilters, retrieveIfPublished, callback) {        ///<summary>        /// Sends an synchronous/asynchronous RetrieveAllEntitieMetadata Request to retrieve all entities metadata in the system        ///</summary>        ///<returns>Entity Metadata Collection</returns>        ///<param name=”entityFilters” type=”Array”>        /// The filter array available to filter which data is retrieved. Case Sensitive filters [Entity,Attributes,Privileges,Relationships]        /// Include only those elements of the entity you want to retrieve in the array. Retrieving all parts of all entities may take significant time.        ///</param>        ///<param name=”retrieveIfPublished” type=”Boolean”>        /// Sets whether to retrieve the metadata that has not been published.        ///</param>        ///<param name=”callBack” type=”Function”>        /// The function that will be passed through and be called by a successful response.        /// This function also used as an indicator if the function is synchronous/asynchronous        ///</param>
        entityFilters = isArray(entityFilters) ? entityFilters : [entityFilters];        var entityFiltersString = “”;        for (var iii = 0; iii < entityFilters.length; iii++) {            entityFiltersString += encodeValue(entityFilters[iii]) + ” “;        }
        var request = [             “<request i:type=\”a:RetrieveAllEntitiesRequest\” xmlns:a=\”http://schemas.microsoft.com/xrm/2011/Contracts\”>”,              “<a:Parameters xmlns:b=\”http://schemas.datacontract.org/2004/07/System.Collections.Generic\”>”,               “<a:KeyValuePairOfstringanyType>”,                “<b:key>EntityFilters</b:key>”,                “<b:value i:type=\”c:EntityFilters\” xmlns:c=\”http://schemas.microsoft.com/xrm/2011/Metadata\”>” + encodeValue(entityFiltersString) + “</b:value>”,               “</a:KeyValuePairOfstringanyType>”,               “<a:KeyValuePairOfstringanyType>”,                “<b:key>RetrieveAsIfPublished</b:key>”,                “<b:value i:type=\”c:boolean\” xmlns:c=\”http://www.w3.org/2001/XMLSchema\”>” + encodeValue(retrieveIfPublished.toString()) + “</b:value>”,               “</a:KeyValuePairOfstringanyType>”,              “</a:Parameters>”,              “<a:RequestId i:nil=\”true\” />”,              “<a:RequestName>RetrieveAllEntities</a:RequestName>”,            “</request>”].join(“”);
        var async = !!callback;        return doRequest(request, “Execute”, async, function (resultXml) {            var response;            if (jQuery(resultXml).find(‘c\\:EntityMetadata’).length != 0) {                response = jQuery(resultXml).find(‘c\\:EntityMetadata’);            } else {                response = jQuery(resultXml).find(‘EntityMetadata’); //Chrome 24.0.1312.52 could not find node by the previous code            }
            var results = [];            for (var i = 0; i < response.length; i++) {                var a = objectifyNode(response[i]);                a._type = “EntityMetadata”;                results.push(a);            }
            if (!async)                return results;            else                callback(results);            // ReSharper disable NotAllPathsReturnValue        });        // ReSharper restore NotAllPathsReturnValue    };
    var retrieveEntityMetadata = function (entityFilters, logicalName, retrieveIfPublished, callback) {        ///<summary>        /// Sends an synchronous/asynchronous RetreiveEntityMetadata Request to retrieve a particular entity metadata in the system        ///</summary>        ///<returns>Entity Metadata</returns>        ///<param name=”entityFilters” type=”String”>        /// The filter string available to filter which data is retrieved. Case Sensitive filters [Entity,Attributes,Privileges,Relationships]        /// Include only those elements of the entity you want to retrieve in the array. Retrieving all parts of all entities may take significant time.        ///</param>        ///<param name=”logicalName” type=”String”>        /// The string of the entity logical name        ///</param>        ///<param name=”retrieveIfPublished” type=”Boolean”>        /// Sets whether to retrieve the metadata that has not been published.        ///</param>        ///<param name=”callBack” type=”Function”>        /// The function that will be passed through and be called by a successful response.        /// This function also used as an indicator if the function is synchronous/asynchronous        ///</param>
        entityFilters = isArray(entityFilters) ? entityFilters : [entityFilters];        var entityFiltersString = “”;        for (var iii = 0; iii < entityFilters.length; iii++) {            entityFiltersString += encodeValue(entityFilters[iii]) + ” “;        }
        var request = [            “<request i:type=\”a:RetrieveEntityRequest\” xmlns:a=\”http://schemas.microsoft.com/xrm/2011/Contracts\”>”,                “<a:Parameters xmlns:b=\”http://schemas.datacontract.org/2004/07/System.Collections.Generic\”>”,                    “<a:KeyValuePairOfstringanyType>”,                        “<b:key>EntityFilters</b:key>”,                        “<b:value i:type=\”c:EntityFilters\” xmlns:c=\”http://schemas.microsoft.com/xrm/2011/Metadata\”>” + encodeValue(entityFiltersString) + “</b:value>”,                    “</a:KeyValuePairOfstringanyType>”,                    “<a:KeyValuePairOfstringanyType>”,                        “<b:key>MetadataId</b:key>”,                        “<b:value i:type=\”c:guid\”  xmlns:c=\”http://schemas.microsoft.com/2003/10/Serialization/\”>” + encodeValue(“00000000-0000-0000-0000-000000000000”) + “</b:value>”,                    “</a:KeyValuePairOfstringanyType>”,                    “<a:KeyValuePairOfstringanyType>”,                        “<b:key>RetrieveAsIfPublished</b:key>”,                        “<b:value i:type=\”c:boolean\” xmlns:c=\”http://www.w3.org/2001/XMLSchema\”>” + encodeValue(retrieveIfPublished.toString()) + “</b:value>”,                    “</a:KeyValuePairOfstringanyType>”,                    “<a:KeyValuePairOfstringanyType>”,                        “<b:key>LogicalName</b:key>”,                        “<b:value i:type=\”c:string\” xmlns:c=\”http://www.w3.org/2001/XMLSchema\”>” + encodeValue(logicalName) + “</b:value>”,                    “</a:KeyValuePairOfstringanyType>”,                “</a:Parameters>”,                “<a:RequestId i:nil=\”true\” />”,                “<a:RequestName>RetrieveEntity</a:RequestName>”,             “</request>”].join(“”);
        var async = !!callback;
        return doRequest(request, “Execute”, async, function (resultXml) {            var response;            if (jQuery(resultXml).find(‘b\\:value’).length != 0) {                response = jQuery(resultXml).find(‘b\\:value’);            } else {                response = jQuery(resultXml).find(‘value’); //Chrome 24.0.1312.52 could not find node by the previous code            }            var results = [];            for (var i = 0; i < response.length; i++) {                var a = objectifyNode(response[i]);                a._type = “EntityMetadata”;                results.push(a);            }
            if (!async)                return results;            else                callback(results);            // ReSharper disable NotAllPathsReturnValue        });        // ReSharper restore NotAllPathsReturnValue    };
    var retrieveAttributeMetadata = function (entityLogicalName, attributeLogicalName, retrieveIfPublished, callback) {        ///<summary>        /// Sends an synchronous/asynchronous RetrieveAttributeMetadata Request to retrieve a particular entity’s attribute metadata in the system        ///</summary>        ///<returns>Entity Metadata</returns>        ///<param name=”entityLogicalName” type=”String”>        /// The string of the entity logical name        ///</param>        ///<param name=”attributeLogicalName” type=”String”>        /// The string of the entity’s attribute logical name        ///</param>        ///<param name=”retrieveIfPublished” type=”Boolean”>        /// Sets whether to retrieve the metadata that has not been published.        ///</param>        ///<param name=”callBack” type=”Function”>        /// The function that will be passed through and be called by a successful response.        /// This function also used as an indicator if the function is synchronous/asynchronous        ///</param>
        var request = [             “<request i:type=\”a:RetrieveAttributeRequest\” xmlns:a=\”http://schemas.microsoft.com/xrm/2011/Contracts\”>”,              “<a:Parameters xmlns:b=\”http://schemas.datacontract.org/2004/07/System.Collections.Generic\”>”,               “<a:KeyValuePairOfstringanyType>”,                “<b:key>EntityLogicalName</b:key>”,                “<b:value i:type=\”c:string\” xmlns:c=\”http://www.w3.org/2001/XMLSchema\”>” + encodeValue(entityLogicalName) + “</b:value>”,               “</a:KeyValuePairOfstringanyType>”,               “<a:KeyValuePairOfstringanyType>”,                “<b:key>MetadataId</b:key>”,                “<b:value i:type=\”ser:guid\”  xmlns:ser=\”http://schemas.microsoft.com/2003/10/Serialization/\”>” + encodeValue(“00000000-0000-0000-0000-000000000000”) + “</b:value>”,               “</a:KeyValuePairOfstringanyType>”,                “<a:KeyValuePairOfstringanyType>”,                “<b:key>RetrieveAsIfPublished</b:key>”,              “<b:value i:type=\”c:boolean\” xmlns:c=\”http://www.w3.org/2001/XMLSchema\”>” + encodeValue(retrieveIfPublished.toString()) + “</b:value>”,               “</a:KeyValuePairOfstringanyType>”,               “<a:KeyValuePairOfstringanyType>”,                “<b:key>LogicalName</b:key>”,                “<b:value i:type=\”c:string\”   xmlns:c=\”http://www.w3.org/2001/XMLSchema\”>” + encodeValue(attributeLogicalName) + “</b:value>”,               “</a:KeyValuePairOfstringanyType>”,              “</a:Parameters>”,              “<a:RequestId i:nil=\”true\” />”,              “<a:RequestName>RetrieveAttribute</a:RequestName>”,             “</request>”].join(“”);
        var async = !!callback;
        return doRequest(request, “Execute”, async, function (resultXml) {            var response;            if (jQuery(resultXml).find(‘b\\:value’).length != 0) {                response = jQuery(resultXml).find(‘b\\:value’);            } else {                response = jQuery(resultXml).find(‘value’); //Chrome 24.0.1312.52 could not find node by the previous code            }            var results = [];            for (var i = 0; i < response.length; i++) {                var a = objectifyNode(response[i]);                results.push(a);            }
            if (!async)                return results;            else                callback(results);            // ReSharper disable NotAllPathsReturnValue        });        // ReSharper restore NotAllPathsReturnValue    };
    //Toolkit’s Return Static Methods    return {        BusinessEntity: businessEntity,        Execute: execute,        Fetch: fetch,        Retrieve: retrieve,        RetrieveMultiple: retrieveMultiple,        Create: sCreate,        Update: sUpdate,        Delete: sDelete,        QueryByAttribute: queryByAttribute,        QueryAll: queryAll,        SetState: setState,        Associate: associate,        Disassociate: disassociate,        Assign: assign,        RetrievePrincipalAccess: retrievePrincipalAccess,        GrantAccess: grantAccess,        ModifyAccess: modifyAccess,        RevokeAccess: revokeAccess,        GetCurrentUserId: getCurrentUserId,        GetCurrentUserBusinessUnitId: getCurrentUserBusinessUnitId,        GetCurrentUserRoles: getCurrentUserRoles,        IsCurrentUserRole: isCurrentUserInRole,        RetrieveAllEntitiesMetadata: retrieveAllEntitiesMetadata,        RetrieveEntityMetadata: retrieveEntityMetadata,        RetrieveAttributeMetadata: retrieveAttributeMetadata    };} ();
XrmServiceToolkit.Extension = function () {    // jQuery Load Help function to add tooltip for attribute in CRM 2011. Unsupported because of the usage of DOM object edit.    //****************************************************    var jQueryXrmFieldTooltip = function (filename, bDisplayImg) {        ///<summary>        /// A generic configurable method to add tooltip to crm 2011 field.         ///</summary>        ///<param name=”filename” type=”String”>        /// A JavaScript String corresponding the name of the configuration web resource name in CRM 2011 instance        /// </param>        ///<param name=”bDisplayImg” type=”boolean”>        /// A JavaScript boolean corresponding if display a help image for the tooltip        /// </param>
        /*        This function is used add tooltips to any field in CRM2011.
        This function requires the following parameters:        filename :   name of the XML web resource        bDisplayImg: boolean to show/hide the help image (true/false)        Returns: nothing        Example:  jQueryLoadHelp(‘cm_xmlhelpfile’, true);        Designed by: http://lambrite.com/?p=221        Adapted by Geron Profet (www.crmxpg.nl), Jaimie Ji        Modified by Jaimie Ji with jQuery and cross browser        */
        if (Xrm.Page.ui.setFormNotification !== undefined) {            alert(‘XrmServiceToolkit.Extension.JQueryXrmFieldTooltip is not supported in CRM2013.\nPlease use the out of box functionality’);            return;        }
        if (typeof jQuery === ‘undefined’) {            alert(‘jQuery is not loaded.\nPlease ensure that jQuery is included\n as web resource in the form load.’);            return;        }
        jQuery.support.cors = true;
        jQuery.ajax({            type: “GET”,            url: “../WebResources/” + filename,            dataType: “xml”,            success: parseHelpXml,            // ReSharper disable UnusedParameter            error: function (xmlHttpRequest, textStatus, errorThrown) {                // ReSharper restore UnusedParameter                alert(‘Something is wrong to setup the tooltip for the fields. Please contact your administrator’);            }        }); //end Ajax
        //****************************************************        function parseHelpXml(data) {            var entity = Xrm.Page.data.entity.getEntityName().toString().toLowerCase();            var entXml = jQuery(“entity[name=” + entity + “]”, data);            jQuery(entXml).children().each(function () {                var attr = jQuery(this).attr(‘name’);                var txt = jQuery(this).find(‘shorthelp’).text();                registerHelp(entity, attr, txt);            });        }        //****************************************************        function registerHelp(entity, attr, txt) {            var obj = jQuery(‘#’ + attr + ‘_c’).children(‘:first’);            if (obj != null) {                var html = ‘<img id=”img_’ + attr + ‘” src=”/_imgs/ico/16_help.gif” alt=”‘ + txt + ‘” width=”16″ height=”16″ /><div id=”help_’ + attr + ‘” style=”visibility: hidden; position: absolute;”>: ‘ + txt + ‘</div>’;                jQuery(obj).append(html);                //20110909 GP: added line to hide/show help image                jQuery(‘#img_’ + attr).css(‘display’, (bDisplayImg) ? ‘inline’ : ‘none’);            }        }    };
    // Generic Dependent Option Set Function. Changed from CRM 2011 SDK example    var jQueryXrmDependentOptionSet = function (filename) {        ///<summary>        /// A generic configurable method to configure dependent optionset for CRM 2011 instance        ///</summary>        ///<param name=”filename” type=”String”>        /// A JavaScript String corresponding the name of the configuration web resource name in CRM 2011 instance        /// </param>        if (typeof jQuery === ‘undefined’) {            alert(‘jQuery is not loaded.\nPlease ensure that jQuery is included\n as web resource in the form load.’);            return;        }
        jQuery.support.cors = true;
        jQuery.ajax({            type: “GET”,            url: “../WebResources/” + filename,            dataType: “xml”,            success: init,            // ReSharper disable UnusedParameter            error: function (xmlHttpRequest, textStatus, errorThrown) {                // ReSharper restore UnusedParameter                alert(‘Something is wrong to setup the dependent picklist. Please contact your administrator’);            }        }); //end Ajax
        function init(data) {            var entity = Xrm.Page.data.entity.getEntityName().toString().toLowerCase();            var configWr = jQuery(“entity[name=” + entity + “]”, data);
            //Convert the XML Data into a JScript object.            var parentFields = configWr.children(“ParentField”);            var jsConfig = [];            for (var i = 0; i < parentFields.length; i++) {                var node = parentFields[i];                var mapping = {};                mapping.parent = jQuery(node).attr(“id”);                mapping.dependent = jQuery(node).children(“DependentField:first”).attr(“id”);                mapping.options = [];                var options = jQuery(node).children(“Option”);                for (var a = 0; a < options.length; a++) {                    var option = {};                    option.value = jQuery(options[a]).attr(“value”);                    option.showOptions = [];                    var optionsToShow = jQuery(options[a]).children(“ShowOption”);                    for (var b = 0; b < optionsToShow.length; b++) {                        var optionToShow = {};                        optionToShow.value = jQuery(optionsToShow[b]).attr(“value”);                        optionToShow.text = jQuery(optionsToShow[b]).attr(“label”); // Label is not used in the code.
                        option.showOptions.push(optionToShow);                    }                    mapping.options.push(option);                }                jsConfig.push(mapping);            }            // Attach the configuration object to jQueryXrmDependentOptionSet            // so it will be available for the OnChange events.            jQueryXrmDependentOptionSet.config = jsConfig;
            //Fire the OnChange event for the mapped optionset fields            // so that the dependent fields are filtered for the current values.            for (var depOptionSet in jQueryXrmDependentOptionSet.config) {                var parent = jQueryXrmDependentOptionSet.config[depOptionSet].parent;                var child = jQueryXrmDependentOptionSet.config[depOptionSet].dependent;                filterDependentField(parent, child, jQueryXrmDependentOptionSet);            }        }
        // This is the function set on the OnChange event for        // parent fields.        // ReSharper disable DuplicatingLocalDeclaration        function filterDependentField(parentField, childField, jQueryXrmDependentOptionSet) {            // ReSharper restore DuplicatingLocalDeclaration            for (var depOptionSet in jQueryXrmDependentOptionSet.config) {                var dependentOptionSet = jQueryXrmDependentOptionSet.config[depOptionSet];                /* Match the parameters to the correct dependent optionset mapping*/                if ((dependentOptionSet.parent === parentField) && (dependentOptionSet.dependent === childField)) {                    /* Get references to the related fields*/                    var parent = Xrm.Page.data.entity.attributes.get(parentField);                    var child = Xrm.Page.data.entity.attributes.get(childField);
                    var parentControl = Xrm.Page.getControl(parentField);                    var childControl = Xrm.Page.getControl(childField);                    /* Capture the current value of the child field*/                    var currentChildFieldValue = child.getValue();
                    /* If the parent field is null the Child field can be set to null */                    var controls;                    var ctrl;                    if (parent.getValue() === null) {                        child.setValue(null);                        child.setSubmitMode(“always”);                        child.fireOnChange();
                        // Any attribute may have any number of controls,                        // so disable each instance.                        controls = child.controls.get();                        for (ctrl in controls) {                            controls[ctrl].setDisabled(true);                        }                        return;                    }
                    for (var os in dependentOptionSet.options) {                        var options = dependentOptionSet.options[os];                        var optionsToShow = options.showOptions;                        /* Find the Options that corresponds to the value of the parent field. */                        if (parent.getValue() === options.value) {                            controls = child.controls.get(); /*Enable the field and set the options*/                            for (ctrl in controls) {                                controls[ctrl].setDisabled(false);                                controls[ctrl].clearOptions();
                                for (var option in optionsToShow) {                                    controls[ctrl].addOption(optionsToShow[option]);                                }                            }                            /*Check whether the current value is valid*/                            var bCurrentValueIsValid = false;                            var childFieldOptions = optionsToShow;
                            for (var validOptionIndex in childFieldOptions) {                                var optionDataValue = childFieldOptions[validOptionIndex].value;
                                if (currentChildFieldValue === optionDataValue) {                                    bCurrentValueIsValid = true;                                    break;                                }                            }                            /*                            If the value is valid, set it.                            If not, set the child field to null                            */                            if (bCurrentValueIsValid) {                                child.setValue(currentChildFieldValue);                            }                            else {                                child.setValue(null);                            }                            child.setSubmitMode(“always”);                            child.fireOnChange();
                            if (parentControl.getDisabled() === true) {                                childControl.setDisabled(true);                            }                            break;                        }                    }                }            }        }    };
    var jQueryXrmCustomFilterView = function (filename) {        ///<summary>        /// A generic configurable method to add custom filter view to lookup field in crm 2011 instance        ///</summary>        ///<param name=”filename” type=”String”>        /// A JavaScript String corresponding the name of the configuration web resource name in CRM 2011 instance        /// </param>        if (typeof jQuery === ‘undefined’) {            alert(‘jQuery is not loaded.\nPlease ensure that jQuery is included\n as web resource in the form load.’);            return;        }
        jQuery.support.cors = true;
        jQuery.ajax({            type: “GET”,            url: “../WebResources/” + filename,            dataType: “xml”,            success: init,            // ReSharper disable UnusedParameter            error: function (xmlHttpRequest, textStatus, errorThrown) {                // ReSharper restore UnusedParameter                alert(‘Something is wrong to setup the custom filter view. Please contact your administrator’);            }        }); //end Ajax
        function init(data) {            var entity = Xrm.Page.data.entity.getEntityName().toString().toLowerCase();            var configWr = jQuery(“entity[name=” + entity + “]”, data);
            //Convert the XML Data into a JScript object.            var targetFields = configWr.children(“TargetField”);            var jsConfig = [];            for (var i = 0; i < targetFields.length; i++) {                var node = targetFields[i];                var mapping = {};                mapping.target = jQuery(node).attr(“id”);                mapping.entityName = jQuery(node).attr(“viewentity”);                mapping.viewName = jQuery(node).attr(“viewname”);                mapping.dynamic = jQuery(node).children(“dynamic”).children();                mapping.fetchXml = xmlToString(jQuery(node).children(“fetch”));                mapping.layoutXml = xmlToString(jQuery(node).children(“grid”));
                jsConfig.push(mapping);            }            // Attach the configuration object to JQueryCustomFilterView            // so it will be available for the OnChange events.            jQueryXrmCustomFilterView.config = jsConfig;
            //Fire the OnChange event for the mapped fields            // so that the lookup dialog are changed with the filtered view for the current values.            for (var customFilterView in jQueryXrmCustomFilterView.config) {                var target = jQueryXrmCustomFilterView.config[customFilterView].target;                var entityName = jQueryXrmCustomFilterView.config[customFilterView].entityName;                var viewName = jQueryXrmCustomFilterView.config[customFilterView].viewName;                var dynamic = jQueryXrmCustomFilterView.config[customFilterView].dynamic;                var fetchXml = jQueryXrmCustomFilterView.config[customFilterView].fetchXml;                var layoutXml = jQueryXrmCustomFilterView.config[customFilterView].layoutXml;
                //TODO: Adding logics for various field and conditions. More tests required.                 if (dynamic != null) {                    for (var a = 0; a < dynamic.length; a++) {                        var dynamicControlType = Xrm.Page.getControl(jQuery(dynamic).attr(‘name’)).getControlType();                        var fieldValueType = jQuery(dynamic).attr(‘fieldvaluetype’); //for optionset, name might be used to filter                        if (Xrm.Page.getAttribute(jQuery(dynamic).attr(‘name’)).getValue() === null) {                            alert(jQuery(dynamic).attr(‘name’) + ‘ does not have a value. Please put validation logic on the field change to call this function. Only use XrmServiceToolkit.Extension.JQueryXrmCustomFilterView when the field has a value.’);                            return;                        }                        var dynamicValue = null;                        switch (dynamicControlType) {                            case ‘standard’:                                dynamicValue = Xrm.Page.getAttribute(jQuery(dynamic).attr(‘name’)).getValue();                                break;                            case ‘optionset’:                                dynamicValue = (fieldValueType != null && fieldValueType === ‘label’) ? Xrm.Page.getAttribute(jQuery(dynamic).attr(‘name’)).getSelectionOption().text : Xrm.Page.getAttribute(jQuery(dynamic).attr(‘name’)).getValue();                                break;                            case ‘lookup’:                                dynamicValue = (fieldValueType != null && fieldValueType === ‘name’) ? Xrm.Page.getAttribute(jQuery(dynamic).attr(‘name’)).getValue()[0].name : Xrm.Page.getAttribute(jQuery(dynamic).attr(‘name’)).getValue()[0].id;                                break;                            default:                                alert(jQuery(dynamic).attr(‘name’) + ” is not supported for filter lookup view. Please change the configuration.”);                                break;                        }
                        var operator = jQuery(dynamic).attr(‘operator’);                        if (operator === null) {                            alert(‘operator is missing in the configuration file. Please fix the issue’);                            return;                        }                        var dynamicString = jQuery(dynamic).attr(‘fetchnote’);                        switch (operator.toLowerCase()) {                            case ‘contains’:                            case ‘does not contain’:                                dynamicValue = ‘%’ + dynamicValue + ‘%’;                                break;                            case ‘begins with’:                            case ‘does not begin with’:                                dynamicValue = dynamicValue + ‘%’;                                break;                            case ‘ends with’:                            case ‘does not end with’:                                dynamicValue = ‘%’ + dynamicValue;                                break;                            default:                                dynamicValue = dynamicValue;                                break;                        }
                        fetchXml = fetchXml.replace(dynamicString, dynamicValue);                    }                }
                //replace the values if required                setCustomFilterView(target, entityName, viewName, fetchXml, layoutXml);            }        }
        function setCustomFilterView(target, entityName, viewName, fetchXml, layoutXml) {            // use randomly generated GUID Id for our new view            var viewId = “{1DFB2B35-B07C-44D1-868D-258DEEAB88E2}”;
            // add the Custom View to the indicated [lookupFieldName] Control            Xrm.Page.getControl(target).addCustomView(viewId, entityName, viewName, fetchXml, layoutXml, true);        }
        function xmlToString(xmlData) {            var xmlString = ”;            try {                if (xmlData != null && xmlData.length > 0) {                    //IE                    if (window.ActiveXObject) {                        xmlString = xmlData[0].xml;                    }                    // code for Mozilla, Firefox, Opera, etc.                    else {                        // ReSharper disable InconsistentNaming                        xmlString = (new XMLSerializer()).serializeToString(xmlData[0]);                        // ReSharper restore InconsistentNaming                    }                    return xmlString;                }            } catch (e) {                alert(“Cannot convert the XML to a string.”);            }            return xmlString;        }    };
    // Disable or Enable to insert/edit note for entity. Unsupported because of DOM object edit    var jQueryXrmFormatNotesControl = function (allowInsert, allowEdit) {        ///<summary>        /// A generic configurable method to format the note control in crm 2011 instance        ///</summary>        ///<param name=”allowInsert” type=”Boolean”>        /// A JavaScript boolean to format if the note control allow insert        /// </param>        ///<param name=”allowEdit” type=”Boolean”>        /// A JavaScript boolean to format if the note control allow edit        /// </param>
        if (Xrm.Page.ui.setFormNotification !== undefined) {            alert(‘XrmServiceToolkit.Extension.JQueryXrmFormatNotesControl is not supported in CRM2013’);            return;        }                if (typeof jQuery === ‘undefined’) {            alert(‘jQuery is not loaded.\nPlease ensure that jQuery is included\n as web resource in the form load.’);            return;        }
        jQuery.support.cors = true;
        var notescontrol = jQuery(‘#notescontrol’);        if (notescontrol === null || notescontrol === undefined) return;        var url = notescontrol.attr(‘url’);        //if (url === null) return;        if (url != null) {        if (!allowInsert) {            url = url.replace(“EnableInsert=true”, “EnableInsert=false”);        }            else if (!allowEdit) {            url = url.replace(“EnableInlineEdit=true”, “EnableInlineEdit=false”);        }        notescontrol.attr(‘url’, url);        } else {        var src = notescontrol.attr(‘src’);            if (src != null) {        if (!allowInsert) {                    src = src.replace(“EnableInsert=true”, “EnableInsert=false”);        }                else if (!allowEdit) {                    src = src.replace(“EnableInlineEdit=true”, “EnableInlineEdit=false”);        }        notescontrol.attr(‘src’, src);            }        }    };
    // Toolkit’s public static members    return {        JQueryXrmFieldTooltip: jQueryXrmFieldTooltip,        JQueryXrmDependentOptionSet: jQueryXrmDependentOptionSet,        JQueryXrmCustomFilterView: jQueryXrmCustomFilterView,        JQueryXrmFormatNotesControl: jQueryXrmFormatNotesControl    };} ();

Format Phone number Using Plugin.

Standard

Using the Below plugin code you can format the phone number

Mention the below code is working and register the dll in plugin registration tool.
On Update step you need to create the step.

***********Source code*************

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Activities;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Workflow;

namespace FormatPhoneNumberWorkflow
{
public class FormatPhoneNumber : CodeActivity
{
protected override void Execute(CodeActivityContext executionContext)
{
string temp=”start of plugin: “;
//throw new NotImplementedException();
//Create the context
IWorkflowContext workflowContext = executionContext.GetExtension<IWorkflowContext>();
IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
IOrganizationService service = serviceFactory.CreateOrganizationService(workflowContext.UserId);

Entity entity = (Entity)workflowContext.InputParameters[“Target”];
Entity account = new Entity();

//temp+=entity.Attributes[“telephone1”].ToString()+entity.Attributes[“telephone2”].ToString()+entity.Attributes[“telephone3”].ToString();
if (entity.LogicalName != “account” || entity.LogicalName != “contact” || entity.LogicalName != “lead”)
return;
bool containsNum = false;

if (entity.Attributes.Contains(“telephone1”))
{

ValidatePhoneNumber(entity, entity.Attributes[“telephone1”].ToString());
containsNum = true;
}
if (entity.Attributes.Contains(“telephone2”))
{
ValidatePhoneNumber(entity, entity.Attributes[“telephone2”].ToString());
containsNum = true;
}
if (entity.Attributes.Contains(“mobilephone”))
{
ValidatePhoneNumber(entity, entity.Attributes[“mobilephone”].ToString());
containsNum = true;
}
if (entity.Attributes.Contains(“address1_telephone1”))
{
ValidatePhoneNumber(entity, entity.Attributes[“address1_telephone1”].ToString());
containsNum = true;
}
if (entity.Attributes.Contains(“managerphone”))
{
ValidatePhoneNumber(entity, entity.Attributes[“managerphone”].ToString());
containsNum = true;
}
if (entity.Attributes.Contains(“assistantphone”))
{
ValidatePhoneNumber(entity, entity.Attributes[“assistantphone”].ToString());
containsNum = true;
}

try
{
temp+=” iam in try”;
if (containsNum)
{
temp+=”contains num”;

Entity entity2Update = new Entity();
entity2Update.Id = entity.Id;
entity2Update[“telephone1”] = entity[“telephone1”];
entity2Update[“telephone2”] = entity[“telephone2”];
entity2Update[“address1_telephone1”] = entity[“address1_telephone1”];
entity2Update[“managerphone”] = entity[“managerphone”];
entity2Update[“assistantphone”] = entity[“assistantphone”];
entity2Update[“mobilephone”] = entity[“mobilephone”];

temp+=”entity.Id”+entity.Id.ToString();
service.Update(entity2Update);
throw new InvalidWorkflowException(temp);
}
}
catch (Exception ex)
{
throw new InvalidWorkflowException(temp);
}
}

private void ValidatePhoneNumber(Entity entity, string attributename)
{
string entityPhnumber = string.Empty;
string formatedPhnumber = string.Empty;
if (entity.Attributes.Contains(attributename) && entity.Attributes[attributename] != null)
{
entityPhnumber = entity.Attributes[attributename].ToString();
if (entityPhnumber.Trim() != “” || entityPhnumber.Trim() != string.Empty)
entityPhnumber = GetNumbersonly(entityPhnumber);
if (entityPhnumber.Length == 10)
{
formatedPhnumber = “(” + entityPhnumber.Substring(0, 3) + “) ” + entityPhnumber.Substring(3, 3) + “-” + entityPhnumber.Substring(6);
entity.Attributes[attributename] = formatedPhnumber;
}
}
}

private string GetNumbersonly(string input)
{
return new String(input.Where(Char.IsDigit).ToArray());
}
[Input(“account”)]
[ReferenceTarget(“account”)]
public InArgument<EntityReference> accountEnt { get; set; }

[Input(“contact”)]
[ReferenceTarget(“contact”)]
public InArgument<EntityReference> contactEnt { get; set; }

[Input(“lead”)]
[ReferenceTarget(“lead”)]
public InArgument<EntityReference> leadEnt { get; set; }
}
}

Happy coding.. 🙂

Finally output will be show in below screen shot…

Phonenumber