Dynamically loading dependent jQuery, jQuery Plugins and JavaScript files

While working with SharePoint 2010, we might have to use jQuery as per the project need.

Loading jQuery by putting it in a master page/page layouts additional header is one approach. But what if, multiple components are dependent on jQuery and its plugins? Also, they are individually registering their own script blocks?

In this case, we run in to lot of issues like

  • jQuery getting registered multiple times
  • Plugins are not loading properly
  • JavaScript errors on page refresh
  • and many more ...

To overcome this issue, we may prefer to use dynamic loading for these files. However, when dynamically loaded there should be some order of registration. Otherwise one may run in to multiple script related issues.

HTML Document supports different types of listeners and one of them is OnRedyStateChange function. Following script makes use of this function to ensure that the scripts are loaded in a right sequence one after another.

 

//-----------------------------------------------------------------------

// <copyright file="jsloader.js" company="Microsoft Corporation">

// Copyright (c) Microsoft Corporation 2012.

// All rights reserved.

// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY

// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE

// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A

// PARTICULAR PURPOSE.

// </copyright>

// <author>Yogesh M Joshi</author>

// <date>05-01-2012</date>

// <summary></summary>

//-----------------------------------------------------------------------

 

function ShouldLoadjQUery() {

    return !window.jQuery;

}

 

function ShouldLoadCycle() {

    if (!window.jQuery) {

        return false;

    }

    return !window.jQuery.cycle;

}

 

var __dynamicJavaScriptsOnLoadCompleteFunctionNames = new Array();

 

function __DynamicJavaScriptsOnLoadComplete() {

    for (var i = 0; i < __dynamicJavaScriptsOnLoadCompleteFunctionNames.length; i++) {

        var expr = "if(typeof(" + __dynamicJavaScriptsOnLoadCompleteFunctionNames[i] + ")=='function'){" + __dynamicJavaScriptsOnLoadCompleteFunctionNames[i] + "();}";

        eval(expr);

    }

}

 

var __dynamicJavaScriptsConfig = {

    scripts: [{ src: '/_layouts/JavaScript/jquery.min.js', shouldLoad: ShouldLoadjQUery },

              { src: '/_layouts/JavaScript/jquery.cycle.min.all.js', shouldLoad: ShouldLoadCycle}],

    callback: __DynamicJavaScriptsOnLoadComplete

};

 

function __RegisterDynamicJavaScripts(config, index) {

    if (index == config.scripts.length) {

        config.callback();

        return;

    }

 

    if (config.scripts[index].shouldLoad != null && config.scripts[index].shouldLoad() == false) {

       __RegisterDynamicJavaScripts(config, index + 1);

    }

    else {

        var headElement = document.getElementsByTagName('head')[0];

        var script = document.createElement('script');

        script.type = 'text/javascript';

 

        if (script.addEventListener) {

            script.addEventListener("load",

            function () {

                __RegisterDynamicJavaScripts(config, index + 1);

            }, false);

        }

        else if (script.readyState) {

            script.onreadystatechange = function () {

                if (this.readyState == 'complete') __RegisterDynamicJavaScripts(config, index + 1);

            }

        }

        script.src = config.scripts[index].src;

        headElement.appendChild(script);

    }

}

 

function __LoadDynamicJavaScripts() {

    __RegisterDynamicJavaScripts(__dynamicJavaScriptsConfig, 0);

}

 

_spBodyOnLoadFunctionNames.push("__LoadDynamicJavaScripts");

 

How to Use?

  • Copy above code in one JS file
  • Add the reference of this file in your HTML document
  • Deploy required script files like, jQuery or related plugins. You can specify the path inside __dynamicJavaScriptsConfig array using src attribute
  • Write ShouldLoad function to decide whether to load the given script. Specify this function to shouldLoad attribute of given script item
  • Use _dynamicJavaScriptsOnLoadCompleteFunctionNames.push()  function to register your own functions which should be called after successful loading of all scripts

I hope this helps!