Dynamically load JavaScript file

Sometimes you don’t always want a JavaScript file to load. If, for instance, a control that utilises it is loaded by a page that already references the same JavaScript file, you wouldn’t want to load the script file again.

Note: This being a SharePoint blog, the script shown here is tailored for that platform but will quite easily port to other non SharePoint sites.

A good example of this would be a custom SharePoint WebPart that uses jQuery. Now, say you don’t have control over the page that will host the WebPart and therefore can’t guarantee that the jQuery script will be present in the page\master page\delegate header control. You could dynamically load the script file as the WebPart loads. The problem with this is that the rendering page might already be loading the same script.

Also, by loading the jQuery script file, especially in an environment you have little control over (maybe a WebPart you developed, which is used by many different systems and configurations) you could potentially cause a conflict on the use of the $ alias, which jQuery creates by default.

Before showing the JavaScript side of this post, lets start with the server side code of the web control\WebPart. In the OnLoad method, you could do something like:

protected override void OnLoad(EventArgs e)
{
  // Load your custom JavaScript file, in this case customScript.js
  if (!Page.ClientScript.IsClientScriptIncludeRegistered("custom_Script"))
  {
    Page.ClientScript.RegisterClientScriptInclude(typeof(ThisClass),
                        "custom_Script",
                        "/_layouts/SharePointStu/scripts/customScript.js");
  }
 
  // Next, call a function called <em>ensureJQuery</em> declared in the
  // customScript.js JavaScript file.
  // This function will perform the dynamic loading of the jQuery
  // JavaScript file, checking to make sure it has not already been loaded
  // by another control or the host page.
  if (!Page.ClientScript.IsStartupScriptRegistered("ensureScriptFunction"))
  {
    string serverUrl = string.Format("{0}{1}",
                              SPContext.Current.Web.Url,
                              SPContext.Current.Web.Url.EndsWith("/") ? string.Empty : "/");
 
    string script = string.Format("ensureJQuery('{0}_layouts/SharePointStu/scripts/jquery-1.7.1.min.js');", serverUrl);
 
    Page.ClientScript.RegisterStartupScript(typeof(ThisClass),
                        "ensureScriptFunction", script, true);
  }
}

This piece of server side code, first loads our custom JavaScript file before finally calling a custom function of that script (called ensureJQuery) which performs the dynamic loading of the jQuery script file.

Now, onto the JavaScript file (customScript.js):

function ensureJQuery(scriptUrl) {
    var hasDollarAlias = false;
 
    if (typeof jQuery === 'undefined') {
        if (typeof $ == 'function') {
            hasDollarAlias = true;
        }
 
        // Create the <em>script</em> tag
        var script = document.createElement('script');
        script.src = scriptUrl;
        var head = document.getElementsByTagName('head')[0];
        var scriptAdded = false;
 
        // Add the jQuery script reference
        script.onload = script.onreadystatechange = function () {
            if (!scriptAdded && (!this.readyState ||
                                 this.readyState == 'loaded' || 
                                 this.readyState == 'complete')) {
                scriptAdded = true;
                // Call callback method to confirm the loading of the script file
                callback();
 
                script.onload = script.onreadystatechange = null;
                head.removeChild(script);
            };
        };
 
        head.appendChild(script);
 
        function callback() {
            if (typeof jQuery == 'undefined') {
                // Script failed to load, notify user of this
                if (SP.UI.Status != undefined) {
                    var statusId = SP.UI.Status.addStatus("Adding jQuery script failed", "An error occurred while adding jQuery script reference", true);
                    SP.UI.Status.setStatusPriColor(statusId, "red");
                }
                else {
                    alert('An error occurred while adding jQuery script reference');
                }
            }
            else {
                // Script loaded successfully, if $ alias was being
                // used prior to loading jQuery, relinquish jQuery's
                // use of the alias and revert to what it originally
                // referenced.
                if (hasDollarAlias) {
                    jQuery.noConflict();
                }
            }
        }
    }
}

All this scripts does it check for the existence of the jQuery object and when it’s not found loads a reference for it. There’s an additional check prior to this on the $ alias. When this has been defined (by a non jQuery object) the script ensures jQuery does not take it over once it’s loaded jQuery.noConflict().

Leave a Reply

Your email address will not be published. Required fields are marked *

Solve the maths problem shown below before posting: *

Follow

Get every new post delivered to your Inbox

Join other followers: