This week, while working on a migration from CRM 4.0 to 2011, I discovered a need to back up my web resources so that we could transfer them easily from our prototype environment to the new production environment that will be created tonight.
Rather than create a new utility, I just decided to modify my Export JavaScript 2011 utility to support all web resource types, not just JScript resources. Here's a look at the new interface:
Just check the boxes next to the types of resources you wish to export.
You can download it from my Free Solutions page.
If you've ever explored the CRM SDK folder system, then you have probably noticed it includes various unexpected goodies, which is the topic for today's article.
Look in: sdk\resources\images
and you will find 2,540 files representing the various user interface components, such as icons.
So, if you've ever needed to create an add-on that needs to show a CRM icon, now you know where to look.
If you have ever worked with the Dynamics CRM Opportunity, you know that it contains a function to recalculate the opportunity when you have selected System Calculated for the Revenue.
Here are the major areas of focus for this discussion:
When the user presses the Recalculate button on the Ribbon, all of the associated line items will be summaries and that number placed into the Est. Revenue field (estimatedvalue is the internal field name).
It is important to note the order in which this happens because if you have your own JavaScript running on the form, it may not function in the way you expect.
Est. Revenue Field OnChange Event
If you add an OnChange event to the Est. Revenue field, it will not be fired by the Recalculate Opportunity button. This is because the value of this field is not modified on the form, it is modified in the database.
If you have selected User Provided for the Revenue field, the Est. Revenue field becomes editable and the OnChange event will fire, after someone changes the value and leaves the field.
Recalculate Opportunity Page Life Cycle
When a user clicks the Recalculate Opportunity button, the following events will occur, in this order:
- The page will be saved, and the OnSave event will fire.
- The database record for the opportunity will be updated with the new Est. Revenue value.
- The page is reloaded, which will fire the OnLoad event.
What this means to you
So, what does this mean to your average CRM developer? Not much unless you need to execute JavaScript on the OnChange of the Est. Revenue field. If that is the case, and you are using System Calculated as your Revenue type, you need to add your code to the form's OnLoad event so that it will execute using the most current Est. Revenue value.
Revised 4/16/2012: Added checks for control type to prevent exceptions.
I ran into a need to build a list of all of the fields found in all of the sections of a tab, within Dynamics CRM 2011. Here is the JavaScript to do that:
function getFieldListFromTab(tabId) { var fieldList = new Array(); var tab = Xrm.Page.ui.tabs.get(tabId); tab.sections.forEach(function (section, sectionIndex) { section.controls.forEach(function (control, controlIndex) { switch (control.getControlType()) { case "standard": case "lookup": case "optionset": var attribute = control.getAttribute(); if (attribute != null) { fieldList.push(attribute.getName()); } break; } }); }); return fieldList; }
The field names are placed in a JavaScript Array.
Add this function to one of the web resources which has been linked to an Entity Form, and you can use it like this:
var fieldList = getFieldListFromTab(0);
alert(fieldList.length);
You can pass in the tab number, which is zero-based, or pass in the tab name.
In the example above, we are retrieving all of the fields in the first tab, then displaying the number of field names added to the array ( the length property ).
JavaScript allows an administrator to enhance the functionality of Dynamics CRM 2011 in order to better fit your business processes.
This Lunch and Learn session delivers an introduction to JavaScript development and will cover the following topics:
- Setting up your development environment
- Introduction to the form editor
- Using web resources
- CRM form events
- JavaScript basics
- CRM 2011 JavaScript object model
- Common CRM JavaScript methods
Class Duration:
1 hour, 15 minutes
Cost Per Attendee:
$99USD
( limited to 20 attendees per session )
What to Expect:
At the end of this session, you should at least understand basics of how to write JavaScript and how to utilize the Dynamics CRM 2011 object model to perform the most operations commonly performed by a developer.
Additionally, since this is not a full class, you'll receive homework to be completed on your own, at your own pace.
When:
Session 1:
Thursday, April 12, 2012 from 11:00 AM to 12:15 PM (CT)
Session 2:
Thursday, April 12, 2012 from 9:00 PM to 10:15 PM (CT)
Local APAC Times:
Friday, April 13, 2012 from 7:30AM to 8:45AM (Mumbai)
Friday, April 13, 2012 from 10:00AM to 11:15AM (Beijing)
Friday, April 13, 2012 from 11:00AM to 12:15PM (Tokyo)
Friday, April 13, 2012 from 12:00PM to 1:15PM (Sydney)
Friday, April 13, 2012 from 2:00PM to 3:15PM (Auckland)
Since the first Lunch and Learn session will occur when my friends in the Asia/Pacific region are mostly asleep, I thought it would be a good idea to hold an encore performance later that same day when the other side of the planet is at work.
See below for the new time and the corresponding local times for Asia/Pacific.
JavaScript allows an administrator to enhance the functionality of Dynamics CRM 2011 in order to better fit your business processes.
This Lunch and Learn session delivers an introduction to JavaScript development and will cover the following topics:
- Setting up your development environment
- Introduction to the form editor
- Using web resources
- CRM form events
- JavaScript basics
- CRM 2011 JavaScript object model
- Common CRM JavaScript methods
When:
Thursday, April 12, 2012 from 9:00 PM to 10:15 PM (CT)
Local APAC Times:
Friday, April 13, 2012 from 7:30AM to 8:45AM (Mumbai)
Friday, April 13, 2012 from 10:00AM to 11:15AM (Beijing)
Friday, April 13, 2012 from 11:00AM to 12:15PM (Tokyo)
Friday, April 13, 2012 from 12:00PM to 1:15PM (Sydney)
Friday, April 13, 2012 from 2:00PM to 3:15PM (Auckland)
Class Duration:
1 hour, 15 minutes
Cost Per Attendee:
$99USD
( limited to 20 attendees )
What to Expect:
At the end of this session, you should at least understand basics of how to write JavaScript and how to utilize the Dynamics CRM 2011 object model to perform the most operations commonly performed by a developer.
Additionally, since this is not a full class, you'll receive homework to be completed on your own, at your own pace.
I see a lot of 'interesting' JavaScript working with CRM installations that have been in operation for more than a couple of years.
Last week, I found the ultimate example of not knowing how to utilize the CRM object model. CRM 4.0 in this case:
for (var i = 0; i < crmForm.all.length; i++) { var crmField = crmForm.all[i]; if (crmField.title != null && crmField.title != 'undefined' && crmField.id != null && crmField.id != 'undefined' && crmField.id != '') { var fieldName = crmForm.all[i].id; var eventType = crmForm.all.new_eventType.DataValue; if (crmField.id.indexOf('new_name') == 0) { if (fieldName == 'new_name') { switch (eventType) { } } } } }
What is this code doing?
The idea here, and I am making an assumption, is to find the 'new_name' field then perform some action.
The first thing you will notice is that we are looping through all of the objects found in the CRM form. I checked and there were 2,607 objects in crmForm.all. That is a lot of looping.
Also, as you can see, there are lots and lots of checks to make sure we have the correct field. Once we have the correct field, we perform some specific actions.
A better way?
This code is totally unnecessary and it actually delayed the loading of the form.
Here is all that was needed:
if (crmForm.all.new_name != null && crmForm.all.new_name.DataValue != null) { }
As you can see, this is much less code, it is easier to understand, and is much quicker.
Lessons Learned
First and foremost, know and understand your tools. When in doubt, perform a search for the specific thing you are looking to do. By now, there should be plenty of JavaScript samples that cover a variety of topics so finding something that is close to what you wish to do, should not be that hard.
If that fails, I would suggest visiting the Dynamics CRM Community Forums where the experts hang out.
JavaScript allows an administrator to enhance the functionality of Dynamics CRM 2011 in order to better fit your business processes.
This Lunch and Learn session delivers an introduction to JavaScript development and will cover the following topics:
- Setting up your development environment
- Introduction to the form editor
- Using web resources
- CRM form events
- JavaScript basics
- CRM 2011 JavaScript object model
- Common CRM JavaScript methods
When:
Thursday, April 12, 2012 from 11:00 AM to 12:15 PM (CT)
Class Duration:
1 hour, 15 minutes
Cost Per Attendee:
$99
( limited to 20 attendees )
What to Expect:
At the end of this session, you should at least understand basics of how to write JavaScript and how to utilize the Dynamics CRM 2011 object model to perform the most operations commonly performed by a developer.
Additionally, since this is not a full class, you'll receive homework to be completed on your own, at your own pace.
We are releasing version 1.4 or our CRM JavaScript conversion tool, CRM Migration Assistant, today.
The trial version can be downloaded here.
Version 1.4 contains the following changes:
Fix: Two-byte characters improperly converted from a customization zip file
If you attempted to convert an exported customization file that contained two-byte characters, like an umlaut, that character would be converted to '??'. This has been corrected.
User Interface Additions
We've added a checkbox to allow you to permanently synchronize scrolling when reviewing the post-conversion JavaScript.
New Conversion Alerts:
Conversion alerts have been added for the following JavaScript methods or properties:
- ontop
- appendChild
- createElement
- innerHTML
- outerHTML
- replaceNode
- returnValue
- crmGrid
- document.all.help
- document.all.crmRenderStatus
- document.all.tdRelatedInformationPane
Improperly-Terminated JavaScript Conversion
Some developers, especially those that do not really understand JavaScript, have a habit of not terminating their JavaScript commands with a semi-colon. This can cause issues during the conversion process. We added extra checks to correct some issues seen during the conversion when an improperly-terminated command was encountered.
Navigation Item Visibility
If we encounter code that appears to hide or show a form's navigation item, we will convert that code into the proper CRM 2011 equivalent. For example:
document.getElementById("navExistingProducts").style.display = "none";
Converts to:
Xrm.Page.ui.navigation.items.get("navExistingProducts").setVisible(false);
Expanded Conversion of .all properties
in certain cases the developer may have assigned the value of crmForm to a variable, which is referenced from that point forward. We have enhanced the conversion of such instances. For example:
if (parentForm.all.new_vaeid.DataValue != null) { var VAE = crmForm.all.new_vaeid; lookupData = new Array(); var lookupVAE = new Object(); lookupVAE.id = parentForm.all.new_vaeid.DataValue[0].id; lookupVAE.typename = 'new_vae'; lookupVAE.name = parentForm.all.new_vaeid.DataValue[0].name; lookupData[0] = lookupVAE; VAE.DataValue = lookupData; }
Converts to:
if (parentForm.getAttribute("new_vaeid").getValue() != null) { var VAE = Xrm.Page.getAttribute("new_vaeid"); lookupData = new Array(); var lookupVAE = new Object(); lookupVAE.id = parentForm.getAttribute("new_vaeid").getValue()[0].id; lookupVAE.typename = 'new_vae'; lookupVAE.name = parentForm.getAttribute("new_vaeid").getValue()[0].name; lookupData[0] = lookupVAE; VAE.setValue(lookupData); }
crmForm.all.item Conversion
JavaScript has a built-in iterator called .item, which is sometimes used by CRM JavaScript developers. We have added support for .item, which will be converted just as if it was crmForm.all. Examples:
var Iframe = crmForm.all.item(id); var optionSet = crmForm.all.item(new_country); crmForm.all.item("youRfield" + i + "blabla").style.display = 'none'; crmForm.all.item(fieldName + "_c").style.display = "none"; var type1id = crmForm.all.item("new_type1id").DataValue != null ? crmForm.all.item("new_type1id").DataValue[0].id : null; var defaultValue = crmForm.all.item(fieldName).DataValue; var textField = crmForm.all.item(fieldName); crmForm.all.item(fieldName).DataValue = "UK";
Converts to:
var Iframe = Xrm.Page.getAttribute(id); var optionSet = Xrm.Page.getAttribute(new_country); Xrm.Page.getAttribute("youRfield" + i + "blabla").setVisible(false); Xrm.Page.getAttribute(fieldName + "_c").setVisible(false); var type1id = Xrm.Page.getAttribute("new_type1id").getValue() != null ? Xrm.Page.getAttribute("new_type1id").getValue()[0].id : null; var defaultValue = Xrm.Page.getAttribute(fieldName).getValue(); var textField = Xrm.Page.getAttribute(fieldName); Xrm.Page.getAttribute(fieldName).setValue("UK");
.Refresh
.Refresh is now converted to .refresh.
'text/javascript' and 'stylesheet' Identification
Added a check for the literals: 'text/javascript' and 'stylesheet' which can be used to indicate external files where the developer may be adding external JavaScript or CSS files.
Tab Visibility
Setting a Tab's visibility will be converted to the correct CRM 2011 method. For example:
tabXTab.style.display = 'none';
Converts to:
Xrm.Page.ui.tabs.get(X).setVisible(false);
I have an update to my JavaScript conversion tool, CRM Migration Assistant, coming out this week and I am looking for CRM 4.0 JavaScript that you feel might have a problem converting to CRM 2011.
Just email me the samples to: mitch at crmaccelerators dot net.






