38

SP.SOD is a nice feature of SharePoint, but how should I use it? For example, I use these lines of code

ExecuteOrDelayUntilScriptLoaded(function () {
   //code
}, "custom.js");

If I understand correctly this code will be invoked when custom.js is loaded. There are several functions that can load this script. For example

SP.SOD.executeFunc('custom.js', null, callbackfunction)

What the best practice to use SP.SOD.executeFunc and ExecuteOrDelayUntilScriptLoaded together?

27

This code is the basic implementation of LoadSodByKey, this is the best implementation of the function as it has the override to allow you to have a callback for when the script is loaded.

After jquery is loaded, the anonymous function will write "Hello World" to the console

<script type="text/javascript">
   LoadSodByKey("js/jquery-1.9.0.min.js", function () {
       console.log("Hello world!")
   });
</script>

These are my thus far best practices for loading and using scripts, and I will continue to update this post as time goes on, and understanding of this increases.

[UPDATE]

A full working compatible pattern for doing this is: Note the called JS file needs to be registered, and run the Notify SOD command

// Callback method
var callback = function () {
    // Code goes here
};

// Expected namespace after loaded
var namespace = "SP.RequestExecutor";

// SOD Key of target js file
var key = "sp.requestexecutor.js";

// Load straight away, or in queue
var bSync = false;

SP.SOD.executeFunc(key, namespace, function () {
    console.log(key + ": Type available (" + namespace + ")");
}, bSync);

// Execute when script has notified loading (Event call)
SP.SOD.executeOrDelayUntilScriptLoaded(callback, key);
  • That is a good blog post, and probably the first on the subject, I have to highlight there will be several more coming shortly. I have found several bugs with FireFox and MDS and I am sharing them with several other JS SP nuts, workarounds will be published for anything found. Stay tuned to my twitter for updates. – Hugh Wood Feb 4 '13 at 11:11
  • can you give an example of callback.. in case of executeOrDelayUntilScriptLoaded please. – variable Jul 23 '14 at 10:38
  • There you go dude – Hugh Wood Jul 23 '14 at 10:42
14

SP.SOD.executeFunc works with OnDemand scripts while ExecuteOrDelayUntilScriptLoaded does not.

Here is an excellent resource on SP.SOD:

SHAREPOINT SCRIPTS ON DEMAND (SP.SOD)

ExecuteOrDelayUntilScriptLoaded(func, scriptName) schedules an asynchronous callback function (func) which will be called when the script has signaled finished loading. Signaled finished loading means that the script has called notifyScriptLoadedAndExecuteWaitingJobs(scriptName). All SharePoint built-in scripts will call notifyScriptLoadedAndExecuteWaitingJobs when they have finished loading. ExcuteOrDelayUntilScriptLoaded does not trigger loading an on demand script (SOD)!

SP.SOD.executeFunc(key, functionName, fn) is used to load on demand scripts (ScriptLink.OnDemand=true). The “key” parameter must match to the ScriptLink’s Name property (Use small letters for key, because an issue with string normalizing in RegisterSodDep)

  • Vardharman, can you copy the relevant code snippets to your answer please incase that site is taken down in the future and the link is broken. The link does contain the best practice - verified. – Hugh Wood Jan 31 '13 at 16:15
  • Updated the answer :) – Vardhaman Deshpande Jan 31 '13 at 16:26
  • why should I use ExecuteOrDelayUntilScriptLoaded function if it does not guarantee that the script will be loaded? Can I use SP.SOD.executeFunc function instead of ExecuteOrDelayUntilScriptLoaded any time, in this case I'm sure that the script will be loaded. What purpose of ExecuteOrDelayUntilScriptLoaded using? – Alexander Jan 31 '13 at 20:27
  • If the script is loaded it runs the function straight away, otherwise it queues the function to be loaded for when the script is available. – Hugh Wood Feb 1 '13 at 8:48
  • 6
    @Alexander ExecuteOrDelayUntilScriptLoaded only works with scripts which are loaded by default on the page (OnDemand=False). It's sole purpose is to make sure that the function is called only after the script has completed loading. executeFunc works with scripts which are not loaded on the page by default (OnDemand=True). It's job is to load the mentioned script on the page and then call the function. – Vardhaman Deshpande Feb 1 '13 at 16:54
4

SP.SOD.executeFunc(key, functionName, fn) method ensures that the specified file (key) that contains the specified function (functionName) is loaded and then runs the specified callback function (fn). Use case for SP.SOD.executeFunc can be that at some point you wish a JavaScript library like jQuery be loaded before you call a function defined inside it via callback function.

SP.SOD.executeOrDelayUntilScriptLoaded(func, depScriptFileName) method executes the specified function (func) if the file (depScriptFileName) containing it is loaded; otherwise, adds it to the pending job queue. Use case for SP.SOD.executeOrDelayUntilScriptLoaded can be that you want to override a function definition within the Core.js, sample code

function CustomCIMOpt() {
CIMOpt = function (menuElement, title, action, imageSource, sequence, description){
    if(title == 'Compliance Details') return '';
    ULSrLq:;
    var menuOption = CMOpt(title, action, imageSource, sequence, description);
    if(!menuOption) return null;
    for(var i=0; i < menuElement.childNodes.length; i++) {
            var iSeq = menuElement.childNodes[i].getAttribute("sequence");
                if(iSeq)
                if(iSeq > description){
                    menuElement.childNodes[i].parentNode.insertBefore(menuOption, menuElement.childNodes[i]);
                    return menuOption
                }
        }
        AChld(menuElement, menuOption);
        return menuOption;
    };
}

ExecuteOrDelayUntilScriptLoaded(CustomCIMOpt, "core.js");
  • 1
    Overriding a function definition within the Core.js can be done using both executeFunc as well as executeOrDelayUntilScriptLoaded also. Isnt it? – variable Jul 23 '14 at 10:36
2

While a few people have provided some good info regarding the usage of the two common commands for pre-loading registered and unregistered scripts, no one has addressed the various challenges in actually getting them to work as advertised.

Having implemented hundreds of SharePoint customisations - and particularly those that rely on SharePoint to complete it's AJAX calls - I can tell you that most of the official methods invariably fail...often without reason. What's most frustrating is that the code will work sometimes, in some browsers, on some OSs - sometimes for days! :)

The most affective method I have found to date to ensure near 100% success is to make certain that any calls to SP.SOD methods are encapsulated within the $(document).ready() function.

Moreover, that any Template Overrides (CSR) methods are also called within the anonymous function of executeFunc.

A simple example to illustrate this by overriding a document's CallOut window footer and inserting a new action to "Send Link By Email":

$(document).ready(function() {
    // Run this after callout.js has loaded.
    SP.SOD.executeFunc("callout.js", "Callout", function () {
        var itemCtx = {};
        itemCtx.Templates = {};
        itemCtx.BaseViewID = 'Callout';
        // Define the list template type
        itemCtx.ListTemplateType = 101;
        // Override the default footer
        itemCtx.Templates.Footer = function (itemCtx) {
            // context, custom action function, show the ECB menu (boolean)
            return CalloutRenderFooterTemplate(itemCtx, AddCustomAction, true);
        };
        SPClientTemplates.TemplateManager.RegisterTemplateOverrides(itemCtx);
    });
});

// Add your Custom Action
function AddCustomAction (renderCtx, calloutActionMenu) {   
    calloutActionMenu.addAction (new CalloutAction ({
        text: "Send Link By Email",
        tooltip: 'Click to create a new email message containining a link to this document.',
        onClickCallback: function() { sendMailLink(); }
    }));

    // Re-render the default actions
    CalloutOnPostRenderTemplate(renderCtx, calloutActionMenu);  
}

/* Callback function for Custom Action */
function sendMailLink() {

    var itemUrl = "<" + _spPageContextInfo.siteAbsoluteUrl + currentItemFileUrl + ">";
    var itemName = currentItemFileUrl.split("/").pop(); 
    window.location.href =
        "mailto:%20?subject=Link to: "
        + itemName 
        + "&body=Here's a link to '" + itemName + "':%0D%0A"
        + itemUrl + "%0D%0A%0D%0A";

    return false;
}

Hope this example helps others.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.