Ensuring your AJAX control on the client-side loads after the DOM - Load functions

Most JavaScript frameworks include a means of ensuring that a developer's code is not loaded until after the HTML DOM has been fully loaded. It is actually quite a feat to achieve this in all of the major browsers (most difficult in IE...obviously...snicker). All of the JavaScript that drives the AJAX Control Framework is written not with any JavaScript framework, but with native JavaScript syntax. As such, I've implemented a means of ensuring that your custom control's JavaScript doesn't execute until after your control has been loaded into the DOM.

To do this I took a leaf out of the book of Matthias Miller, Dean Edwards, and John Resig. Major cudos to all 3 of them for their genius. Following their example, as outlined here http://blog.outofhanwell.com/2006/06/08/the-windowonload-problem-revisited/), the AJAX Control Framework ensures you that you won't have JavaScript errors when your custom control's JavaScript executes.

There's a catch though. Just like with the jQuery library where you need to attach a handler function to the "onload" event of the <body> with a call to the $(document).ready() function, you have to create a handler function to that encapsulates your control's init code. The AJAX Control Framework will control how this loading function is invoked. Your loading function only needs to be present in the global namespace for the AJAX Control Framework to find it.

So what goes in this loading function?

You should put your initialization code in the loading function. In general, initialization code includes all your event handlers and the code that attaches these handler functions to DOM events (like "onclick" or "onmouseover").

How do I define the loading function?

Here is a list of all the requirements of the loading function:
  • The name of the function must start with "load_".
  • After load_, the name of the function must be the full name of your AJAX enabled control's type, where all '.' are replaced with the '_' character. The full name of your control's type would be its namespace + "_" + class name. For example (from the BingMapsSample project), the name of the loading function for the ucSearchResultsList User Control would be load_BingMapsSample_ucSearchResultsList, where "BingMapsSample" is the type's namespace and "ucSearchResultsList" is the type's class name. Another example from the BingMapsSample project: the ucSearchResultsMap User Control would have a loading function with the name load_BingMapsSample_ucSearchResultsMap.
  • The loading function must be declared globally. Look at the first "best practice" below to see the best way to do this.
  • It must accept 1 parameter. This parameter references the object representation of your custom control that the AJAX Control Framework will emit the JavaScript for automatically, and instantiate and pass to the loading function for you automatically. I usually just call the parameter "obj". The object this parameter references contains all of the methods that you've annotated with the AjaxControlMethod attribute in your custom control's server code. This feature allows you to reference and invoke server-side methods using AJAX by name. You can see an example of this in the BingMapsSample project within the ucSearchResultsMap.js file.
  • In order for the loading function to be invoked automatically (or take part in any of the AJAX Control Framework's features), your custom control must implement the IAjaxControl interface or derive from the AjaxControl or AjaxUserControl implementations that come out of the box with AJAX Control Framework.


Best Practice
Your loading functions must be declared globally. Problems arise only if your implementing OOP in your JavaScript or you want to nest the loading function declaration within another function. As a "catch-all", what I like to do is set the function as a property of the native "window" JavaScript object. Your JavaScript would look something like this:

window["load_BingMapsSample_ucSearchResultsMap"] = function(obj) {
        ...
};


Best Practice
If you're following the best practice described on the 1 Script for Every AJAX control page and maintaining a single .js file for each one of your custom controls, you should have only 1 loading function in every .js file associated with an AJAX enabled control.


Best Practice for those who use jQuery
jQuery is usually not the only JavaScript framework that we load on a page. To help reduce collisions with function names (especially with the "$" helper function) jQuery comes with the "noConflict" function. Calling this function in your code returns a reference to the "$" helper function so that if you are using any other JavaScript frameworks on the same page that use this same function name, there won't be any ambiguity. Here's how I like to define my loading functions:

(function($) {
    window["load_BingMapsSample_ucSearchResultsMap"] = function(obj) {
        ...
    };
})(jQuery.noConflict());
Doing it this way ensures I don't have naming conflicts with other JavaScript frameworks and still allows me to use the standard "$" notation.


If you've never implemented OOP in your JavaScript before, and don't know how to for that matter, check out this article. It gives an amazing overview of how to do it. What are you waiting for? Seriously read this article! It'll change your life and open up doors for you. You cannot get into JavaScript Heaven if you don't know this stuff ;-).

Last edited May 2, 2010 at 3:18 PM by peanutbutterlou, version 10

Comments

No comments yet.