Loading Script in SharePoint 2010 (Dallas Tester)

SharePoint 2010 ships with a large EcmaScript-based object model. In order to alleviate downloading all of the script at one time, there is a system built into the object model called Script on Demand. Script on Demand is a publicly available script loading mechanism. It contains methods for loading script, registering script dependencies, executing methods within a loaded file, and event notification. I'll describe the methods and show a short example for some of them.

SP.SOD class

All of the public OM can be accessed using the SP.SOD class. This class is defined in the init.js file on the Web front end.  You may have seen examples out there that access these methods without the class specified, but you should always use the class in order to ensure compatibility with future versions of SharePoint. On to the APIs!

SP.SOD.execute(key, functionName, args)

Executes the function functionName in the file identified by key with the arguments specified. This will also load the script if it hasn't been loaded.

SP.SOD.executeFunc(key, functionName, fn)

Ensures that the key file that defines function functionName is loaded and then runs the callback function fn. This will also load the script if it hasn't been loaded.

SP.SOD.registerSod(key, url)

Registers the file at url with the key key. This has a server-side equivalent--ScriptLink.RegisterOnDemand.

SP.SOD.registerSodDep(key, dep)

Registers the file with key dep as a dependency of file with key key.

SP.SOD.executeOrDelayUntilScriptLoaded(func, depScriptFileName)

If the referenced function func is loaded, execute it now. Otherwise, execute after the script depScriptFileName has been loaded. Does not actually load the script.

SP.SOD.executeOrDelayUntilEventNotified(func, eventName)

If the referenced event eventName has happened already, execute the function func now. Otherwise, execute the function when the event happens.

Tip: This expects a function and not a function name. I ran into an error the first time I used this because I put my function in single quotes. As you might guess, a string isn't a function. :)

SP.SOD.notifyScriptLoadedAndExecuteWaitingJobs(scriptFileName)

Notify that the referenced script scriptFileName has loaded and then execute all the things that are waiting for that script. Note that this must be the last line of any JS file that’s registered for use in the SOD system.

SP.SOD.notifyEventAndExecuteWaitingJobs(eventName)

Notify that the referenced event eventName has happened and then execute all the things that are waiting for that event.

Code Sample

The following code sample shows some of these APIs work together. Since I'm the Server ribbon guy, I'm going to put these customizations into the ribbon. For brevity, I'm going to omit a big chunk of the ribbon code. For more information on customizing the ribbon, check it out in the SDK at Declarative Customization of the Ribbon.

Here are my Command UI Handlers for the ribbon customization. Note that I've broken the code into multiple lines for the sake of readability. You may have to put the code on a single line.

         <CommandUIHandler
          Command="RegisterScript"
          CommandAction="javascript:
                          SP.SOD.registerSod('MySODTest', 
                            '/SiteAssets/JavascriptDeploy/MySODTest.js');" />
        <CommandUIHandler
          Command="DisplayAlert"          
          CommandAction="javascript:
                          SP.SOD.execute('MySODTest', 
                            'displayAlertFromSOD', 'Hello, world!');" />
        <CommandUIHandler
          Command="AddNotification"
          CommandAction="javascript:
                          SP.SOD.executeOrDelayUntilEventNotified(displayNotificationFromSOD, 
                            'ReadyForNotifications');" />
        <CommandUIHandler
          Command="NotifyEvent"
          CommandAction="javascript:
                          SP.SOD.notifyEventAndExecuteWaitingJobs('ReadyForNotifications');" />
        <CommandUIHandler
          Command="DisplayDialog"
          CommandAction="javascript:
                          SP.SOD.executeOrDelayUntilScriptLoaded(showDialogFromSOD, 
                            'mysodtest.js');" />

Here is the code inside of MySODTest.js:

 function displayAlertFromSOD(message) {
    alert(message);
}
function showDialogFromSOD() {
    var options = {
        title: "Created in an SOD Call",
        width: 400,
        height: 600,
        url: "/_layouts/settings.aspx"
    };
    SP.UI.ModalDialog.showModalDialog(options);
}
function displayNotificationFromSOD() {
    SP.UI.Notify.addNotification('Hello, world!', false);
}
SP.SOD.notifyScriptLoadedAndExecuteWaitingJobs('mysodtest.js');

A few things to note here:

  • You must always call registerSod before you use the other functions. In the best case (execute), nothing will happen.. In the worst case (everything else), you'll get a script error.
  • After calling registerSod, you must load the script using either execute or executeFunc. This is important because you will run into similar errors as stated above.
  • You must always put the call to notifyScriptLoadedAndExecuteWaitingJobs at the end of the JS file. I put that in the notes above, but I wanted to call it out again. :)

Happy coding!