How to find Javascript files used in Microsoft Dynamics Forms

Sometimes when you work on a CRM project which contains lots of Javascript files, it can be difficult to determine what Javascript files are being used and which ones are still needed.

The route cause of this is Microsoft Dynamics CRM forms can have lot of methods triggered from fields or ribbon buttons but these can be difficult to find to find what Javascript files are being used.

Where is Javascript triggered in CRM

Javascript files can be used on CRM forms and the code can be triggered on forms loading/saving or by the OnChange event of a field and the Ribbon buttons.  Below is where Javascript files can be used in CRM

  • Javascript triggered by OnChange events
  • Javascript triggered by Ribbon buttons
  • Javascript triggered in form OnLoad/OnSave events
  • Javascript files used in html pages

There are many different areas Javascript can be used but it can be difficult to see what Javascript files are used and linked to field OnChanges, ribbon buttons.

One of the reasons this is difficult is because the CRM UI means it’s not easy to see what fields have Javascript functions triggered via the OnChange event and the only way is to either look at the Javascript files and hope the CRM Developer has used a logical naming structure.

or

You can click the fields in the CRM form and check if there is an OnChange event.

Javascript development and deployment

Javascript development and Javascript deployment can be a bit disjointed.  One method is to write the Javascript file in Visual studio then you copy the Javascript file and paste it into the CRM form changes, save and publish.

It should be noted this isn’t a new problem for CRM 2015/2013 , there have been lots of tools created to help the process.

CRM MVP Mitch Milam created the export Javascript file tool, which I hada used in older versions of Microsoft Dynamics CRM, which you can read about here

The Microsoft Developer toolkit brought big improvements which allowed you to deploy/update Javascript file changes from Visual studio.  I go through the process in this video from Hosk CRM Dev Youtube channel

What Javascript files are used

I recently worked on a project which had gone through some optimization and refactoring, my current task is finding out if all the Javascript files are needed for each of the forms.

The reason the project is in this state is we quickly needed to optimize the code and whilst doing this the Javascript was optimized and refactored, this has resulted in some of the Javascript files not being needed

The code was refactored but some of the Javascript files which were no longer used were not removed.

The code was also part of the Async Javascript load issue, which happened in CRM 2011 Rollup 12

CRM 2011 – Things learnt when reviewing Javascript code on form loads

Here is my blog post on CRM form performance

CRM 2011/2013 Investigating CRM Form Performance issues

 

The Problem

Tidy up Javascript files on forms, remove the WaitForScriptsLoaded Javascript file and replace the onload method with the entity Javascript file.

Remove Javascript files which are no longer referenced.

Factors

To make the problem harder, the Javascript was split over 10 different Javascript projects, which made find if Javascript files were used

To help me the project adhere’s to Javascript best practices and uses Javascript namespaces.

link to Javascript namespaces

Things to consider

When looking at what Javascript files are needed don’t forget to check the Javascript files used for the ribbon buttons, in this particular project most forms had 5 custom ribbon buttons.

Tools used

Fiddler

I used Fiddler to track what calls were being made out of the form

Visual Studio

I used Visual studio to look at the Javascript files included on the FORM.

F12 Debugger

Press F12 on a record and I could see all the Javascript files being used.

Script finder tool

I knew there was a script finder tool but I couldn’t find it when searching the internet.  Thankfully a reader added a comment and of course it’s in the everyone’s favourite CRM tool or collection of Tools the XRMToolbox.

The XRMToolbox has a Script finder tool which will list all the Javascripts and will show the event e.g. OnLoad, OnSave, OnChange as you can see from the screenshot below

image_24 (2)

 

The tool looks great but I would say the project I was working on has a lot of Javascript and when I tried I pressed the find scripts button it never came back.  I think it timed out because there are loads (hundreds) of scripts and functions.

Process of finding unused Javascript files

I did try doing a find in files but this proved to be very slow and seemed difficult, I eventually decided this process wasn’t really working.

So I looked at the problem a different way

How do I find what files are used when the CRM form is being used?

 

I came up with two main methods.

Method 1

Go through the main Javascipt file specified in the form onSave/OnLoad and look what other Javascript files/methods are referred.  Thankfully the Javascript files used were developed with using Javascript Namespaces so I could search for the namespaces in the file to see what other Javascript files were used.

I cold then compare the Javascript files listed in the Javascript files for the form and what Javascript files were referenced in those Javascript files.

Method 2

When the Javascript form is being used in CRM you can press F12 to get the debugger up, I  could see what Javascript files are loaded.

 

Why did this happen

Good CRM Development will mean the CRM developer will create lots of seperate Javascript files which can used in multiple CRM forms.  The reason you split the Javascript file into common Javascript files is because it’s better to use the same Javsacript code in many different forms rather than copy the code in many different Javascript files (e.g. if you have one Javascript file for each form).

You never want to duplicate code because if there is a bug in the code then you would have to fix all the various copies of the code and the chances are you would forget to change some of them.  Later it would be difficult for the CRM developer to know which code was fixed and which code still had the bug in.

When Javascript code is no longer needed CRM developers often forget to remove Javascript files and methods, this can add to the confusion for a CRM developer when there are javascript files and methods which don’t seem to be used.  It can be scary to be the CRM developer to remove unused Javascript files and methods because it’s difficult to be 100 percent sure they are not used anywhere.

 

 

 

 

Beware of the Bad Javascript for loop

I should have written this blog post on halloween, wooooooo but I hadn’t seen the bug then so that would involve time travel and I haven’t got time for that.  Wait if I invented a method of time travel I would have all the time I would need.  Oh no another bad loop I have got myself in.

Yesterday I blogged about an error I had with a for loop, you can read it below

CRM 2011/2013 – What does setSubmitMode do? and how does it work?

 

This was the code that caused the problem

var attributes = Xrm.Page.data.entity.attributes.get();

for (var i in attributes) {
{ attributes[i].setSubmitMode(never); }
}

 

The problem was when looping round the variables in attributes it was also returning functions, which caused a crash.

I fixed the code by doing this

for (var i in attributes) {

{
i f (isNa!N(i)) {
attributes [i]setSubmitMod.e(“never”);
}
}
}

 

 

Not Quite Right

Something was bugging me about the code.  If that problem was a problem whcommon y had I never seen that code before?

Why had I never seen this error before?

I mentioned the problem and solution to another developer and he instantly said

 

The code must have been using the bad for loop

What!, no one told me there was a bad for loop in Javascript, why has no one told me about the bad for loop, come on people.

 

The Good, the bad and the ugly of For statements

 

The Bad – For In Loop for Array Iteration

I searched the internet and found this forum discussion with a great explanation

http://stackoverflow.com/questions/5263847/javascript-loops-for-in-vs-for

I am copying the top answer because it’s awesome

 

Don’t use for..in for Array iteration.

It’s important to understand that Javascript Array’s square bracket syntax ([]) for accessing indicies is actually inherited from the Object

obj.prop === obj['prop']  // true

The for..in structure does not work like a more traditional for..each/in that would be found in other languages (php, python, etc…).

Javascript’s for..in is designed to iterate over the properties of an object. Producing the key of each property. Using this key combined with the Object‘s bracket syntax, you can easily access the values you are after.

var obj = {
    foo: "bar",
    fizz: "buzz",
    moo: "muck"};


for ( var prop in obj)  {
    console.log(prop);      // foo / fizz / moo
    console.log(obj[prop]); // bar / buzz / muck}

And because the Array is simply an Object with sequential numeric property names (indexes) the for..in works in a similar way, producing the numeric indicies just as it produces the property names above.

An important characteristic of the for..in structure is that it continues to search for enumerable properties up the prototype chain. It will also iterate inherited enumerable properties. It is up to you to verify that the current property exists directly on the local object and not the prototype it is attached to with hasOwnProperty()

for ( var prop in obj)  {
    if ( obj.hasOwnProperty(prop) ) {
        // prop is actually obj's property (not inherited)
    }
}

(More on Prototypal Inheritance)

The problem with using the for..in structure on the Array type is that there is no garauntee as to what order the properties are produced… and generally speaking that is a farily important feature in processing an array.

Another problem is that it usually slower than a standard for implementation.

Bottom Line

Using a for...in to iterate arrays is like using the butt of a screw driver to drive a nail… why wouldn’t you just use a hammer (for)?

 

Hosk Interpretation

The important point here is ForIn statements in javascript return user defined properties as well as numeric indexes.  EEK this explains why I was getting “IndexOf” in my for loop.

It also suggests the index numbers are not gauranteed to come out in a sequential order.  This might not be a problem because all the numbers will come out but if you were expecting them in order the for…in could sneak in a very odd bug to find.

Performance is also slow using the forin loop (although in this case it wasn’t really a problem/consideration), this forum discussion also discusses more about performance of for loops if you are interested in finding out more

http://stackoverflow.com/questions/13645890/javascript-for-in-vs-for-loop-performance

 

The Good

So what For loop should you use in your Javascript for iterating arrays.

When I stepped through this for statement the “IndexOf” value wasn’t returned

var attributes = Xrm. Page. data. entity. attributes. get ();

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

attributes[i]. setSubmitMode("never"); }


The Bad

The bad was the original bug someone put in there, it’s the wrong, evil for loop, didn’t the developer know anything!  Well technically I didn’t know about the bad for loop until today.

for (var i in attributes) {
{ attributes[i].setSubmitMode(never);}} 


 

 

The Ugly

The ugly was my original fix

for (var i in attributes) {
    if(!isNaN(i)) {
    attributes [i]setSubmitMod.e(never);}}
    


 

It worked but it wasn’t quite right, it was working around the problem of using the wrong for loop.  It took longer because it was returning functions as well as numbers.

 

what have I learnt

I have learnt there are good and bad for loops in Javascript, yes, I went back and changed the code to use the correct for loop.

I  learned it’s good to discuss things with your fellow developers because you might teach them something new or they might teach you a new trick or way to do something.

 

It’s good to talk

It’s good to talk/blog about quirks and problems you experience programming.  Often developers build up areas of expertease which is usually based around the experience they have gained from projects they have worked on.

 

Be willing to learn

I believe in continuous improvement, always striving to learn and improve.  Every mistake/bad coding practice you can get rid off will be replaced by good code.

More good code == better developer

 

Don’t base your knowledge just on experience

Good developers learn the best practices through their own ideas/experience, reading articles/books on programming.

Good developers are always trying new technology/releases, not only does this get them ready for the new functionality but it gives them ideas

On a related subject is my blog on why you should read the what’s new for CRM 2015, it’s all about learning baby!

CRM 2015 SDK – Why you should read the What’s new for developers

 

I believe CRM certifications (customization and extending) are good ways to learn the new functionality in CRM 2013 and broaden your CRM development knowledge.  I  read and used parts of CRM I hadn’t used in any projects I had worked on but which came up in future projects.

My point is you can learn areas of coding/CRM you haven’t used in a project by reading and trying the functionality yourself.  When the time comes to use it in a project you already have a good idea (and maybe a bit of experience) of how to use it, which means your learning curve on new functionality will be shorter than someone with no knowledge of it.

With CRM 2013 it’s easy, you can easily create a CRM 2013 on line trial to try out all the new functionality, you have no excuse because I have created a blog on how to get a CRM 2013 up and running

Step by Step guide to creating a CRM 2013 Online trial

 

Times change but standards must remain

and if the Hosk catches you writing poor code, I will send round the heavy mob

CRM 2013 – Using Dynamic Javascript

Javascript is a slippery beast, Slave to no one and master to many.   It’s just a quick blog post today, not as quick as this article I found written by me

CRM 2011 – Javascript snippet – How to remove all existing values from an OptionSet

 

I’m more happy in the .net and C# world with it’s static variables.

What I mean by this is C# you have to declare the variable you are going to use e.g.

  • string
  • int
  • bool
  • custom type

 

but with Javascript a var can be anything, it’s like something out of X-men changing and morphing it’s way along.

Here is a good article about static and dynamic languages

Static vs. dynamic typing of programming languages

 

Why doesn’t Hosk like Dynamic Javascript

Good question, surely I should like dynamic things.

Some of the reasons I don’t like it are

  • Hard to read/understand other peoples code
  • Bugs can be compiled and then appear in runtime when the code is run
  • It encourages the cowboy coders to go to town
  • It’s strange and different

 

Get to the point

I’m not saying I don’t like Javascript it’s just sometimes I want to do things and I’m not sure HOW because the syntax can be a bit crazy.  Like all developers once we have a working example in our hands, we are off.  So recently I saw some interesting Javascript in a project I am working and I was intrigued to understand how it worked and use it again.

One cool feature about Javascript is the ability to pass in function names using variables, a bit like reflection(ish), but only once you know how because I tried searching for this on the internet and fell down a big dark hole.

 

Example

On a form I have 4 OptionSets which we are dynamically setting the values to.

If I pass in the OptionSetField name I can dynamically get the control


var control = Xrm .Page .getControl (OptionSetFieldName);

I can then clear this control


control. clearOptions();

I can then add in the new values and build it up.  The beauty of dynamic code is I can use the same code for all the OptionSets because I can pass in the name of the control.

When adding a the new optionSet values in, I can use a dynamic variable to retrieve the field name from array, which contains values retrieved from a fetchXML query.  The childField is the name of the field in CRM.


      var option = {
                    value: retrievedOptionSet[i]. text == "" ? "null" : retrievedOptionSet[0].attributes [childField]. value,
                    text: retrievedOptionSet[0].attributes [childField]. formattedValue
                };
                control. addOption(option);
            }


Summary

It may be common knowledge to all you JavaScript wizards out there, but I hadn’t used or seen JavaScript using dynamic names.  It makes sense and it’s very useful so I thought I would share it with you

 

CRM JavaScript Programming Best Practices in different versions

Microsoft has a very good page on Javascript programming in CRM – http://msdn.microsoft.com/en-us/library/hh771584.aspx

I was reading this today and I noticed it had a Javascript Programming Best Practices section.  Javascript is very useful but I often feel the code produced in Javascript is not alway the best quality because there is no type checking and the process of writing the code and uploading is a bit of a hassle.

 

I have selected a couple of the best Practices but to read the full list go to the article

Microsoft have also created best practices for different versions, links to below to the different pages

CRM 2011 – Javascript best practices

CRM 2013 – Javascript best practices

CRM 2015 – Javascript best practices

 

There are a lot of best practices and it’s a really good article, but below are my top 4 best practices from the article.  I would definitely recommend you read the different articles.

 

Use a Cross-browser JavaScript Library for HTML Web Resource User Interfaces

A cross-browser JavaScript library, such as jQuery, provides many advantages when developing HTML web resources that must support multiple browsers. JavaScript libraries like jQuery provide a unified development experience for all browsers supported by Microsoft Dynamics CRM. These capabilities are most appropriate when you are using HTML web resources to provide user interfaces. JavaScript libraries like jQuery provide consistent ways to interact with the Document Object Model (DOM).

Use Feature Detection When Writing Functions for Multiple Browsers

Even when you use a cross-browser library like jQuery, you need to be very aware of differences between browsers. You can generally detect which browser is being used by querying thenavigator.useragent property. This is called browser detection. Browser detection is not a good strategy for most cases because it can’t take into account what features newer versions of a browser have. Also, some browsers provide the capability to modify the navigation.useragent property so that they appear to be a different browser.

Feature detection is the recommended approach. By detecting what features are available, you can create code paths for the browsers you support without knowing exactly which browser is being used. For more information about feature detection, see How to Detect Features Instead of Browsers.

Define Unique Names for Your JavaScript Functions

When you are the only developer for an HTML page you can easily manage the names of the JavaScript functions you use. In Microsoft Dynamics CRM, other solutions may add JavaScript functions to the page where your function is used.

If two JavaScript functions on a page have the same name, the first function defined is overwritten by the second. For this reason, make sure that you define unique names for your JavaScript functions. For more information, see Creating Script Libraries.

Use Asynchronous Data Access Methods

When you access data by using the Microsoft Dynamics CRM web services that use the REST or SOAP endpoint for web resources, always use an XMLHttpRequest that is configured to execute asynchronously. The reason is that the browser operates on a single thread. If that thread is being used to execute a long-running process synchronously the browser will stop responding.

CRM 2011 – IFrame opening new page problem

I had a tricky problem, where I wanted to show a grid of records on an entity which didn’t have a direct relationship with those records.

Because there wasn’t a direct relationship I couldn’t show a grid of filtered records.

The way I got around this was to show a view inside an iFrame.  On the onload of the page I would adjust the view to use guid of the regarding item on my task.

This showed a view of items filtered by the guid of the record in the regarding.  The problem then occurred when I clicked on one of the items in grid.  Instead of taking me to the item, it loaded a new page which contained just the view and then I could click the item.

I couldn’t work out why this wasn’t working so I had a look at the properties of the iFrame and there is an option

Restrict cross-frame scripting

I noticed this was ticked, so I unticked and then it was working.

The reason I think it wasn’t working was because I was trying to click on a hyperlink which would take me to the record.  I guess this hyperlink was seen as cross frame scripting, so by allowing this it allowed the hyperlink to work.

CRM 2011 – Be careful removing fields from a form

I had written some javascript which retrieved values from a field which I was displaying on the form.

I had added an account field onto a quote product, so I could then use the account id to inject into some fetchXML in a subgrid so I only showed quote products which had only been sold to the the account selected on the quote.

I could have looked this up using a query but I thought I would add it onto the Quote Product form and pass the value using relationships.

It worked fine but as I came to release the code I thought I didn’t really need the account lookup field on the form so I took it off.

Then when testing my code it wasn’t working, so I pressed F12 and was ready to debug, except it wasn’t running my code because it was erroring whilst trying to get the account lookup field, with this error.

SCRIPT5007: Unable to get value of the property ‘getValue’: object is null or undefined

So the morale of the story is, you can only access fields in Javascript which are on the form.  The solution to this problem was to make the fields not visible.

This is logical when I stop to think about it because why would CRM load up all the variables which are not being used on the form, it would be a complete waste of time.

This was an early morning, not fully awake error but it does show you the danger of taking off variables from a form without seeing if any javascript uses those fields for something

CRM 2011 – Javascript to set the current date and time

A quick blog entry and a suprisingly easy and small piece of code

In the code below I have function which gets triggered when a user ticks the confirm Closed checkbox it then sets the current date and time.

if the user untick the checkbox I wipe the date and time value.

The date functionality in javascript holds the current time as well

 function confirmClosedOnChange() {
 var closedConfirmed = Xrm.Page.getAttribute("new_closedconfirmed").getValue()

if (closedConfirmed) {
var currentDateTime = new Date();
Xrm.Page.getAttribute("new_confirmedcloseddate").setValue(currentDateTime);
} else {

Xrm.Page.getAttribute("new_confirmedcloseddate").setValue(null);
}
 }