Javascript – define functions and programmatically attach events

Since we’re on the subject of javascript I might as well add some more stuff. First of all, how to define you own functions, then how to programmatically bind a function to an event, for instance, onchange of a field.

This mainly concerns Microsoft CRM but the technique can also be used in SharePoint, although javascripts aren’t as common.

First off, how to define a function.

There are actually several different ways, for instance the normal:

function myfunc1(param1, param2)

{

alert(“myfunc1”);

}

 

And the one with a weird sort of syntax:

var myfunc2 = function(param1, param2)

{

alert(“myfunc2”);

}

 

In CRM 3, these can actually be defined within the onLoad, hence creating some ways of code reuse. These functions will be available for all event in the page since they have been declared in the onload.

This leads me to another point, that a function has to be defined before it can be used. Hence, in the example above, myfunc2 can call myfunc1, but not the other way around. If you try, you will get strange error messages saying stuff like “null is not ‘null'”.

Secondly, you can bind events to functions using code. There are several ways of doing this as well (what did you think!?) and they mainly differ based on which browser you are using. If you want to read some more on the subject, if you want some more info on event binding in javascript, please have a look at this very instructive page: http://developer.apple.com/internet/webcontent/eventmodels.html

First the simple method by just setting the onchange attribute.

crmForm.all.ext_myfield.onchange = myfunc2;

 

or

document.getElementById(“objectid”).onchange = myfunc2;

 

This has the advantage of a quite simple syntax and, if you want it, the override of previous events.

The second way of doing this is using the attachEvent method. As far as I’ve read, there are some differences with syntax between browsers, but since neither MS CRM nor SharePoint work in any acceptable way in anything but IE, this is not a big issue. Here is some example syntax:

crmForm.all.ext_myfield.attachEvent(“onchange”, myfunc2);

or

document.getElementById(“objectid”).attachEvent(“onchange”, myfunc2);

 

The main advantage of this method is that you can attach several functions to one event, hence, not overriding other handling.

Bellow is an example html-file which demonstrates this:

<html
xmlns=”http://www.w3.org/1999/xhtml”>

<head>

<script
type=”text/javascript”>

var myfunc1 = function()

{

alert(“myfunc1”);

}

var myfunc2 = function()

{

alert(“myfunc2”);

}

var loading = function()

{

alert(“running”);

document.getElementById(“btTest”).attachEvent(“onclick”, myfunc1);

document.getElementById(“btTest”).attachEvent(“onclick”, myfunc2);

}

</script>

</head>

<body
onload=”loading();”>


<button
id=”btTest”>Click me</button>

</body>

</html>

If you copy this to a file called test.htm and test it, you will see that when clicking the button, myfunc2 will be executed first and then myfunc1.

So, all put together, this can be used to a great extent in MS CRM 3, where you can now put all code in one place, the onLoad script, define some functions and then bind the onchange event of all the attributes you like in the same code. Remember to define the functions before you attach the events.

I havn’t seen CRM 4 / Titan yet, and I don’t know what features it will have in this aspect, but if it includes the feature to be able to add a global javascript file that will be included on all pages, this would be very very useful when using techniques like this.

And remember, javascript is an ugly beast, but it is very useful! J

Gustaf Westerlund

Humandata AB

Window.close() in javascript acts a bit strange…

Javascript is a strange language, it is often confused to be Java, which is very far from right, and the syntax can often be thought to be as consistent as C# or Java. Not the case. Javascript is a strange and weird beast, that when tamed can be a very strong ally. Taming it can however really get on your nerves!

There is one method working on the object window, called close(). Hence it is called using window.close(). It does the simple thing of closing the current browser window. No more, no less.

Well, actually, it does it in a strange way. Have a look at the following code that is executed in body onload. What is going to happen?

Alert(“Start”);

Windows.close();

Alert(“End”);

 

I will give you two options:

Option 1:

  1. A dialog window showing “Start” will show.
  2. The current browser window will close.

Option 2:

  1. A dialog window showing “Start” will show.
  2. A dialog window showing “End” will show.
  3. The current browser window will close.

Well?

You would think that option 1 is correct, well, it isn’t, the script is executed according to option 2. For some reason, window.close() doesn’t actually close the window, it signals it to close and when the onload has reached its end, it is closed. I havn’t checked to see if this behavior only happens when executed in onload or if it is the same all over. Be aware though, it might not work as you’d expect!

Gustaf

How to add a virtual directory below your SharePoint or CRM website

Sometimes you would like to create a virtual directory bellow for instance the SharePoint main site. Lets say you MOSS is installed at http://intranet and you would like to create your own virtual directory with your custom made aspx-pages at for instance http://intranet/custom. Well, if you use the IIS Management Console, add a virtual directory to the website, and add an aspx-page to that virtual directory, you will get errors saying that the application cannot find certain assemblies. This is due to the fact that these assemblies have been referenced in web.config using <add assembly=”name-of-assembly” / > tags. Due to the way IIS works, these references are automatically inherited to all sub-directories, in this case, you virtual directory.
So, what to do? The simplest way to handle this is to add <remove assembly=”name-of-assembly” / > tags to the web.config that resides in your virtual directory. This will explicitly remove the reference created by the parent website. Remove them one by one and soon you will be able to run your code just as you would like.
One good advantage of using adding your code to a virtual directory bellow the main site instead of using a new website at for instance another host header or TCP port, is that you can address your code using server relative urls. In essence, if you created an aspx-page at http://intranet/custom/mycustompage.aspx. If you address this page from the SharePoint, you can use the url: /custom/mycustompage.aspx without http:// or the servername. This also gives you the benefit that the page is on the same server, hence no security problems with IE.
In SharePoint, make sure that the address of your virtual directory is NOT bellow any wildcard included och explicitly included sites (in the setup of the webapplication in central admin).
Please note that adding virtual directories bellow the CRM root is an unsupported customization. This is due to the fact that Microsoft might release an update that adds a directory with the exact name of you virtual directory. This would give rise to either the fact that your code stops working or more likely that the content of the directory added by Microsoft cannot be accessed.
Gustaf Westerlund
Humandata AB