You are currently browsing the tag archive for the ‘JavaScript’ tag.

Continuing with THIS series of posts, today we are looking at using the Flot JScript library for visual rendering of data. Flot is a great little library for charting. It is available from HERE.

The Flot library has a few graphing variations available, and we can easily change the CSS as needed to make it look even more appealing. The idea is that presenting information visually will make our users so much faster, and more inclined to quickly glance to see what’s going on, rather than deep dive.

In this short article we focus on the Flot pie charts. What we will achieve is this:

image

Notice how, for the purpose of this demo, I have left the available rendering option buttons on the form. You can change the rendering type as needed, until you figure out which is the best to use. I like to do that with customers because giving them choice empowers them and engages them in the discussion.
Read the rest of this entry »

Advertisements

Keeping in line with a previous article about using the Bootstrap library with Dynamics CRM, in this article we will look at using another JScript library.

This mini-series of articles relates to the topic I’ve presented at eXtreme CRM this year. It all revolves around visual presentation at the record level. While Dashboards are nice, humans are “visual animals”, and as such, presenting information visually at the record level is not only eye-candy, but also can make a user of the system more productive, and more eager to adopt a new tool.

The previous articles in this mini-series are:

HTML Web Resource in Dynamics CRM

HTML Web Resource in Dynamics CRM [2]

Bootstrap Progress Bar in CRM

We’re going to be looking now at Easy Pie Chart. There are two reasons I like this library. First off, it is very light. Second, I like the animation. Makes it more “look here first” like. I’ll be using it as is, with no visual customizations, but if you want, feel free to tinker with the CSS.
Read the rest of this entry »

This post is just an introduction to a set of posts detailing how we can start taking advantage of HTML5 and some open source JavaScript libraries and frameworks within Dynamics CRM.

In this first post, we’ll be looking at getting to the most basic information from within a HTML Web Resource. Of course, knowledge of JavaScript and some basic CSS is required :)

For the sake of this example, and to keep things simple and easy to read, the script and the CSS are all built in the same file. Normally you would create a structure of 3 separate files, a HTML file, a JavaScript file and CSS file.

Start by creating a new HTML web resource. Place it in a iFrame on the Account entity.

The following code is commented to be self-explanatory, and is only meant to serve as a reference. Some of these calls will be used in future articles when we start looking at providing some real functionality on our records.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
    <head>
        <title>Context Info</title>
        <style type="text/css">
            body {
                background-color: #b0c4de;
            }

        </style>
    </head>
    <body>
        <script type="text/javascript">
            // debugger;
            var xrm = window.parent.Xrm;

            // Display the client information
            // Web for Browser
            // Outlook for Outlook
            // Mobile for Mobile
            var _client = xrm.Page.context.client.getClient();
            document.write("Client: " + _client + "<br />");

            // Get the client’s URL
             var _clientURL = xrm.Page.context.getClientUrl();
             document.write("Client URL: " + _clientURL + "<br />");

            // Get the current theme
            // for Outlook
            // returns the following values:
            // Default for Web
            // Office12Blue for Microsoft Dynamics CRM for Outlook 2007 or 2010 Blue Theme
            // Office14Silver for Microsoft Dynamics CRM for Outlook 2007 or 2010 Silver or Black Theme
            var _clientTheme = xrm.Page.context.getCurrentTheme();
            document.write("Client Theme: " + _clientTheme + "<br />");

            // Get the base language
            var _baseLanguage = xrm.Page.context.getOrgLcid();
            document.write("Base Language: " + _baseLanguage + "<br />");

            // Get the Organization Unique Name
            var _orgUniqueName = xrm.Page.context.getOrgUniqueName();
            document.write("Organization Unique Name: " + _orgUniqueName + "<br />");

            // Get the current User ID
            var _userID = xrm.Page.context.getUserId();
            document.write("User ID: " + _userID + "<br />");

            // Get the User Language
            var _userLanguage = xrm.Page.context.getUserLcid();
            document.write("User Language: " + _userLanguage + "<br />");

            // Get the User Name
            var _userName = xrm.Page.context.getUserName();
            document.write("User Name: " + _userName + "<br />");

            // Get the User Roles IDs
            var _userRoles = xrm.Page.context.getUserRoles();
            document.write("User Roles: ");
            for (var i = 0; i < _userRoles.length; i++) {
                document.write(_userRoles[i].toString() + ", ");
            }
            document.write("<br />");

            document.write("Window size: " + this.innerWidth + ", " + this.innerHeight + "<br />");

            document.write("Working with record data: " + "<br />");

            // debugger;

            // Get a reference to the entity
            var _entity = xrm.Page.data.entity;

            // Get the entity name
            var _entityName = _entity.getEntityName();
            document.write("Entity Name: " + _entityName + "<br />");

            // Get the entity ID
            var _entityID = _entity.getId();
            document.write("Entity ID: " + _entityID + "<br />");

        </script>
    </body>
</html>

The output when opening a new Account form should be as follows:

image

On an existing record you will also get the Entity ID.

Now with all this information, we can start building something more interesting. Future posts will go into retrieving related data, and building some other functionality with it. So, stay tuned :)

Enjoy!

With Dynamics CRM 2013 now we have even more opportunities to play with the UI. We have more choice with regards to layout, more choice with regards to user experience, and implicitly more opportunities to make it better for the user. But, once we start to analyze the user experience, we could find that we’re missing a lot by not being able to do everything we can do on a regular web page. Or, can we?

NOTE: some of the items presented in this post are not officially “supported”, and should only be used with that in mind.

A previous post was describing the proper way to use jQuery in the context of Dynamics CRM. See more details HERE.

In this post I’m going to be talking about Twitter Bootstrap, and how we can leverage it in the context of Dynamics CRM 2013. We want to add a progress bar to our Case form, to show graphically how far we are in resolving this case. It should look something like this:

image

First off, head to getbootstrap.com and download the files.

image

Extract the files, and you will get this structure:

image

Go in the css folder, and get the bootstrap.min.css file. also, from the js file get the bootstrap.min.js file. We will be using the min files for better performance.

Now, in your CRM environment, load these as web resources.

In addition, create a new JScript web resource that will hold our custom script. Let’s name this one new_bootstrap_case as we want to make our modifications on the Case form. The structure should look as follows:

image

Now, let’s add the following script to the OnLoad of the Case form:

function AddProgressBar() {
    // add the CSS reference

    var _css = "WebResources/new_bootstrap_css";
    var _cssref = document.createElement("link");
    _cssref.setAttribute("rel", "stylesheet");
    _cssref.setAttribute("type", "text/css");
    _cssref.setAttribute("href", _css);
    $("head").append(_cssref);

    // add the progress bar
    var _innerHTML = "";

    _innerHTML += "<div class=’progress progress-striped’ width=’100%’>";
    _innerHTML += "<div class=’progress-bar progress-bar-success’ role=’progressbar’ aria-valuenow=’40’ aria-valuemin=’0′ aria-valuemax=’100′ style=’width: 40%’>";
    _innerHTML += "<span class=’sr-only’>40% Complete (success)</span>";
    _innerHTML += "</div>";
    _innerHTML += "</div>";

    $("h2.ms-crm-Form").prepend(_innerHTML);
}

 

Basically, we are doing two things here:

In the first part, we are adding our CSS web resource to the page. This will help us with the rendering of the progress bar.

The second part of the function simply generates the HTML required to render the progress bar. In this example I am setting it to 40% by default, but you can define the value as needed based on your current business rules.

Your form properties will look as such when done:

image

Now, open a Case form, and find your new progress bar rendered as such:

image

Enjoy!

While often times the values of a sub-grid can be defined only through the grid settings, you will find that there are situations where you want the grid to display a set of custom results. You can control the results selection/filtering using FetchXML, and here’s how to do it:

First off, I have a function that triggers on page load. It looks like this:

function PopulateRecentCaseSubGrid() {
    var ruleConditionID = Xrm.Page.data.entity.getId(); //Get Rule ID  
    var ruleConditionName = Xrm.Page.getAttribute("new_name").getValue();
    if (ruleConditionID != null) {
        var guid = ruleConditionID.substring(1, ruleConditionID.length – 1);
        var fetchXml = "<fetch version=’1.0′ output-format=’xml-platform’ mapping=’logical’ distinct=’false’>" +
                       "<entity name=’incident’>" +
                       "<attribute name=’title’ />" +
                       "<attribute name=’ticketnumber’ />" +
                       "<attribute name=’casetypecode’ />" +
                       "<attribute name=’statecode’ />" +
                       "<attribute name=’new_project’ />" +
                       "<attribute name=’ownerid’ />" +
                       "<attribute name=’incidentid’ />" +
                       "<order attribute=’title’ descending=’false’ />" +
                       "<filter type=’and’>" +
                        "<filter type=’or’>" +
                         "<condition attribute=’new_rule_condition1′ operator=’eq’ uiname=’" + ruleConditionName + "’ uitype=’new_rulecondition’ value=’" + guid + "’ />" +
                         "<condition attribute=’new_rule_condition2′ operator=’eq’ uiname=’" + ruleConditionName + "’ uitype=’new_rulecondition’ value=’" + guid + "’ />" +
                         "<condition attribute=’new_rule_condition3′ operator=’eq’ uiname=’" + ruleConditionName + "’ uitype=’new_rulecondition’ value=’" + guid + "’ />" +
                         "<condition attribute=’new_rule_condition4′ operator=’eq’ uiname=’" + ruleConditionName + "’ uitype=’new_rulecondition’ value=’" + guid + "’ />" +
                         "<condition attribute=’new_rule_condition5′ operator=’eq’ uiname=’" + ruleConditionName + "’ uitype=’new_rulecondition’ value=’" + guid + "’ />" +
                        "</filter>" +
                       "</filter>" +
                       "</entity>" +
                       "</fetch>";

        setTimeout(function () {
            PopulateGridFetchXML(‘Compliance_Cases’, fetchXml);
        }, 5000)

    }
}

 

This defines the FetchXML with all the required filters, and calls another function called PopulateGridFetchXML.

function PopulateGridFetchXML(subGridName, fetchXML) {

    try {

        var subGrid = document.getElementById(subGridName);
        subGrid.control.SetParameter("fetchXml", fetchXML);
        subGrid.control.refresh();

    } catch (err) {
        alert(err.message);
    }
}

Our PopulateGridFetchXML function takes in the name of the sub-grid we want to refresh, along with the fetch query. It simply sets the FetchXML parameter to the grid, and calls a refresh on it.

You can build your FetchXML using advanced find or manually.

Enjoy!

While this is a scenario that could potentially be achieved using real time workflows, if you want things to happen really real-time, you have to go back to using JScript.

For this example we have an entity called Rule, with a reference to an Organization (lookup to Account). We also have an entity called Rule Condition, which relates to a Rule. On the Rule Condition, once we populate the Rule, we need to also populate the Organization based on the Organization selected on the Rule related entity.

The process is relatively simple.

1. Retrieve the value populated in the Rule field on Rule Condition.

2. Make a call to retrieve the values from the Rule, specifically the Organization.

3. Create and populate the Organization on Rule Condition based on the Organization retrieved from Rule.

And here’s the code. The first function retrieves the Rule ID, and passes it to the second function, which, in turn, makes the call and retrieves the Organization from the Rule, and populates the Organization on the Rule Condition.

Attach this first function to the onChange event of the Rule field on the Rule Condition form:

function PopulateAuthorityFromRuleAuthority() {
    var _lookupObject = Xrm.Page.getAttribute("new_rule_id");

    if (_lookupObject != null) {
        // debugger;

        var _lookupObjectValue = _lookupObject.getValue();

        if (_lookupObjectValue != null) {
            var _ruleName = _lookupObjectValue[0].name;
            var _ruleId = _lookupObjectValue[0].id;
            var _ruleType = _lookupObjectValue[0].entityType;

            /* Retrieve the Rule values, including the Authority */
            GetRuleAuthority(_ruleId);

        }
    }
}

And place this next function in the same web resource:

function GetRuleAuthority(ruleId) {

    var oDataURI = Xrm.Page.context.getClientUrl()
        + "/XRMServices/2011/OrganizationData.svc/"
        + "new_ruleSet(guid’" + ruleId + "’)"
        + "?$select="
        + "new_organization";

    var req = new XMLHttpRequest();
    req.open("GET", encodeURI(oDataURI), true);
    req.setRequestHeader("Accept", "application/json");
    req.setRequestHeader("Content-Type", "application/html; charset=utf-8");
    req.onreadystatechange = function () {

        if (this.readyState == 4) {
            req.onreadystatechange = null; 
            if (this.status == 200) {
                
                var _ruleOrganization = new Array();
                _ruleOrganization [0] = new Object();
                var _organization= JSON.parse(this.responseText).d.new_organization;
                _ruleOrganization [0].id = _organization.Id;
                _ruleOrganization [0].name = _organization.Name;
                _ruleOrganization [0].entityType = _organization.LogicalName;
                
                Xrm.Page.getAttribute("new_organization").setValue(_ruleOrganization);
                Xrm.Page.data.save();
                
            }
            else {
                /* errorCallback(accountId);
                   an error occured, handle it as you wish. */
            }
        }
    };
    req.send();

}

If you find working with lookups a little more daunting then working with other fields, this should help.

Enjoy!

Just a quick note, for those implementations taking advantage of script customizations, if you are using

Xrm.Page.ui.getCurrentControl

when upgrading to UR2, remember to check your scripts. This method is now deprecated.

For more details see HERE.

Happy scripting!

This is another new feature of Dynamics CRM 2013. While in previous versions, we used to use JScript alerts to bring up field specific messages on forms, now we have two new functions available:

setNotification(“message”);

and

clearNotification();

So how do we use then, and what do they do?

First off, let’s bring up a message on a field if a condition is met, or clear it otherwise:

function SetCustomNotification(controlName, controlMessage)
{
    var field = Xrm.Page.getControl(controlName);
    var condition = [evaluate your condition here];
    if (condition)
    {
        field.setNotification(controlMessage);
    }
    else
    {
        field.clearNotification();
    }
}

Pass in strings for controlName and controlMessage.

Set your function on either the onChange event of the field, or on the onSave event of the form. If you set it on form save, it’s a good idea to stop the save if the condition fails and the message comes up.

And the end results is your custom message showing as below:

image

Enjoy!

This quick snippet comes in handy every now and then, and now it’s also tested for Dynamics CRM 2013.

Scenario:

I have a bunch of organizations, and a set of Organization Types. Let’s say, we have various client types, with various SLA’s.

In the Case entity, I want to show only the Organizations of specific type(s), that I can support through Cases.

Solution:

First off, create a new web resource if one is not already created for the Case entity.

Then, from the form load event, call this function which uses addPreSearch.

function preFilterLookupOrganization() {   
    Xrm.Page.getControl("control_name").addPreSearch(function () {
        addLookupFilter();
   });
}

This is from the SDK:

addPreSearch

Use this method to apply changes to lookups based on values current just as the user is about to view results for the lookup.

JavaScript 
Xrm.Page.getControl(arg).addPreSearch(handler)

Arguments
Type: Function to add.
Remarks
This method is only available for Updated Entities.

The argument is a function that will be run just before the search to provide results for a lookup occurs. You can use this handler to call one of the other lookup control functions and improve the results to be displayed in the lookup.

 

Next let’s build the handler. We’re building the filter query and add the filter to our control as such:

function addLookupFilter() {
    var myControl = Xrm.Page.getAttribute("control_name").getValue();

    if (myControl != null) {
        fetchXml = "<filter type=’and’><condition attribute=’customertypecode’ value=’1′ operator=’eq’/></filter>";
        Xrm.Page.getControl("control_name").addCustomFilter(fetchXml);
    }
}

Now, it’s all in the filter, and the current example only looks for one specific Organization type. You can build that fetchXml filter as complex as needed, either by pulling if from an advanced find, creating it by hand, or using a 3rd party tool.

Enjoy!

Often times we created scripts with alerts to the user, or getting some sort of simplistic interaction with the user. Some of those do change in Dynamics CRM 2013.

If we used window.alert or window.confirm now it’s time to stop that. The new SDK has a warning for us to use the newly provided functions.

alertDialog

instead of using window.alert now the recommended way is to use

Xrm.Utility.alertDialog(message, onCloseCallback);

confirmDialog

instead of using the old window.confirm now we should use

Xrm.Utility.confirmDialog(message, yesCloseCalback, noCloseCallback);

Observe the use of the callback function to continue processing your business flow.

Unfortunately these are only available for the entities where the UI has been updated, but they will definitely come in handy.

The change was prompted by the support for all browsers, and the use of tablets and other devices. On tablets, calls to functions that block the flow of code is not allowed.

Enjoy!

The new SDK for Dynamics CRM 2013 is out (see previous post for the link), and a few calls stand out when working with JavaScript:

getClient

instead of using the old isOutlookClient now we have more flexibility to determine the client. the returned values include

  • Web
  • Outlook
  • Mobile

use as follows:

context.client.getClient();

Pay attention to the list of entities where this works, as it works on those that have received an updated user interface. A list of these is provided at the end of this post.

getClientUrl

this replaces the old getServerUrl().

Use this to determine of the URL used to access the application. Distinction is made now not only between whether we are dealing with an Online or on-premise, but also if using the offline feature of the Outlook plugin.

Values returned are:

Use as follows:

context.getClientUrl();

getCurrentTheme

use for instances where Outlook is being used. This will return the selected Outlook theme the user has configured. This can be helpful when you design your web resources to match the Outlook client theme.

NOTE: Forms will not adapt to the various themes selected, only the custom web resources can be made to adapt.

Standard values returned as of now are:

  • default (web app)
  • Office12Blue (for the Blue theme)
  • Office14Silver (for the Silver or black theme)

Use as follows:

context.getCurrentTheme();

getOrgLcid

returns the selected base language for your organization. For a default English you will get 1033.

Use as follows:

context.getOrgLcid();

getUserId

return the GUID for the current user. Note that you still need a call to the web service to retrieve the Full Name if you need to display that in a web resource.

Use as follows:

context.getUserId();

getUserLcid

Returns the user selected preferred language. You can use this when customizing communication from a specific user, or any other situations where you need to compare the user selected language versus organization default language.

Use as follows:

context.getUserLcid();

getUserName

Unfortunately available only for the updated entities, but this is returning the user name of the current user.

Use as follows:

context.getUserName()

Updated Entities

The following entities have received the updated user interface to the time of this writing:

Account, Appointment, Campaign, Campaign Activity, Campaign Response, Case, Competitor, Contact, Contract, Contract Line, Email, Fax, Invoice, Lead, Letter, Marketing List, Opportunity, Opportunity Product, Order, Phone Call, Price List Item, Product, Quick Campaign, Quote, Recurring Appointment, Sales Literature, Team, Task and User.

I’ve got to start by stating: I like what I see…

Let’s take a Phone field, on the Contact form. You will see a new tab called Business Rules. Go to it :)

image

Click on New, and create a new rule to check if the field contains data. Bring a message to the user if number is blank. The rule could look like this (not very fond of the size of that title, it doesn’t have to knock me over the head):

image

Activate it. You get prompted for confirmation:

image

Click OK and return to your Contact form. Now try and see what you did. remove the number from an existing contact, and try to tab out. You will get this:

image

So now you don’t have to overload your instance with your possibly buggy JavaScript, and waste your time debugging it. You can easily shave off some of the common scripts we probably all have in our library we built from previous versions.

Of course, the example is as basic as possible, and it could have been achieved by marking the field as mandatory :)

Enjoy!

Microsoft Business Solutions MVP

Check out my course [Video]

Dynamics 365 Customer Engagement Administration

Dynamics 365 Customer Engagement Administration

Check out my course [Video]

Configuring and Extending Dynamics 365 Customer Engagement

Configuring and Extending Dynamics 365 Customer Engagement

Check out my course [Video]

Getting Started with Dynamics 365 Customer Engagement

Reviewed Book

Implementing Microsoft Dynamics 365 for Finance and Operations

Implementing Microsoft Dynamics 365 for Finance and Operations

Reviewed Book

Microsoft Dynamics 365 Extensions Cookbook

Microsoft Dynamics 365 Extensions Cookbook

Check out my Book

Microsoft Dynamics CRM 2016 Customization - Second Edition

Microsoft Dynamics CRM 2016 Customization - Second Edition

Check out my Book

Microsoft Dynamics CRM Customization Essentials

Microsoft Dynamics CRM Customization Essentials

Check out my Book

Microsoft Dynamics CRM 2011 Scripting Cookbook

Microsoft Dynamics CRM 2011 Scripting Cookbook

Reviewed Book

Microsoft Dynamics CRM 2011: Dashboards Cookbook

Microsoft Dynamics CRM 2011: Dashboards Cookbook

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 604 other followers

Follow Dynamics 365 Wizardry on WordPress.com