E

very now and then I come across a question dealing with the order of execution for client-side code (Client Scripts and UI Policies). In my experience, the need to order client-side code is pretty rare and really only applies in a few ‘onLoad’ scenarios and even fewer ‘onChange’ scenarios. Usually, the way that a browser parses and executes client-side code means that the ordering is pretty unpredictable. It’s worth mentioning that this issue doesn’t exist with server-side code precisely because the browser isn’t involved (which is why you can neatly order all of your business rules without issue).

In this post I’ll show you some of the techniques I’ve used in the past to provide some control over the order of execution of client-side code. I’ll also show you a pretty cool trick that you can use to ensure that a piece of client-side code runs before any other client script or UI policy…or after ALL of those scripts finish running.

Solving the ‘before…and after’ problem

The first thing you should be aware of is that you do have some limited ability built-in to control the order of execution for client-side code with the ‘Order’ field on UI policies.

UI Policy Order

There are a few caveats with the ordering of client-side code though.

  1. Ordering IS NOT available to client scripts, only UI policies
  2. Client scripts will start their execution before UI policies
  3. Even with the order field on the UI policies, it only controls the start order of execution for the scripts. The actual order that various portions of those scripts run depends on the complexity and variety of the scripts so you can’t really guarantee that a particular piece of client-side code will run before or after another.

You can also set up a wait or delay in your script by using the ‘setTimeout’ method (or something similar).

Guaranteeing absolute before…and after…

I was recently asked to help solve a problem with a long-loading form. The form took several seconds to render and hide various form sections, fields, and related lists. The problem was that during this time, users could interact with the form before it was ready to use. This can cause issues with incorrect submissions, mis-routed calls, and the general undoing of all of the great things you designed the form to do in the first place. Before I explain this solution you should know that the overwhelming majority of issues in this area can be prevented by following a few simple rules…

  • Limit the amount of information on your form to what is absolutely necessary. Dozens of form sections and related lists and hundreds of fields on a form just aren’t going to load quickly no matter what you do…even if they’re hidden!
  • Stay away from ‘GlideRecord’, ‘getReference’, and ‘GlideAJAX’ in your client scripts and UI policies! If you do need to use any of these then use asynchronous processing if at all possible!
  • Follow these best practice guidelines in your client scripts.

Sometimes process and bureaucracy win out over performance and sensibility however, and you have to deal with a problem that you would rather avoid in the first place. One idea would be to use the loading dialog that I described in a previous post on ServiceNowGuru. This would prevent user interaction with the form until the entire thing finished loading and all of the scripts had finished their execution.

Long Loading Form Dialog

The dialog is easy enough to execute, but the real problem is guaranteeing that the dialog displays before anything else on the form (which you can’t do with client scripts or UI policies) and knowing definitively when the form finishes loading so that you can close the dialog.

There’s simply no way to guarantee that a client script or UI policy will run before the form loads. The actual fields (and formatters) will be rendered before the scripts run though. The solution I came up with was to create a custom hidden field (by utilizing a UI macro and UI formatter) to execute some code before any other client scripts run. The script is actually very simple. It just shows the loading dialog, uses Prototype’s ‘Event.observe’ function to identify when the form has finished loading, and hides the dialog.

//Show the loading dialog immediately as the form loads
var loadingDialog = new GlideDialogWindow("dialog_loading", true);
loadingDialog.setPreference('table', 'loading');
loadingDialog.setTitle('Loading...'); //Set the loading dialog title here...
loadingDialog.render();
                 
//Wait until the form has finished loading
addLateLoadEvent(function(){
    loadingDialog.destroy();
});

You can set up the UI macro and UI formatter as follows…

‘form_loading_dialog’ UI macro
Name: form_loading_dialog
XML:

<?xml version="1.0" encoding="utf-8" ?>
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
   <g:evaluate var="jvar_show_dialog" expression="!RP.isPopup()" />
   <j:if test="${jvar_show_dialog}" >
      <script>
         //Show the loading dialog immediately as the form loads
         var loadingDialog = new GlideDialogWindow("dialog_loading", true);
         loadingDialog.setPreference('table', 'loading');
         loadingDialog.setTitle('Loading...'); //Set the loading dialog title here...
         loadingDialog.render();
                 
         //Wait until the form has finished loading
         addLateLoadEvent(function(){
             loadingDialog.destroy();
         });
      </script>
   </j:if>
</j:jelly>
‘Form Loading Dialog’ Formatter
Name: Form Loading Dialog
Formatter: form_loading_dialog (or the name of your UI macro)
Table: Task
Type: Formatter

Once you’ve set up the UI macro and UI formatter for the table(s) of your choice, all you have to do is personalize the form for any long-loading form and add the ‘Form Loading Dialog’ formatter to the first form section on the form. Enjoy!

Personalize Form Loading Dialog