a weblog by Ed Eliot

Full of lovely web standards information and a large helping of PHP

This weblog is the online home of , a Senior Technical Manager at GCap Media living and working in London, United Kingdom.

Entries for August 2007

You are currently viewing posts from the archive. Click here to return to the latest posts.

  • Dynamically loading JS libraries and detecting when they're loaded

    9 months, 1 day ago

    Sometimes it makes sense to dynamically load JavaScript library code only at the point at which it's required. If functionality which uses that library is used rarely then it makes little sense incur the overhead of an additional HTTP request or data transfer on page load.

    We can dynamically load any JavaScript and add it to the document with the following function.

    Making a dynamic request

    1. function loadScript(sScriptSrc) {
    2. var oHead = document.getElementById('head')[0];
    3. var oScript = document.createElement('script');
    4. oScript.type = 'text/javascript';
    5. oScript.src = sScriptSrc;
    6. oHead.appendChild(oScript);
    7. }

    This approach isn't without problems though. The request will load asynchronously which means that any JavaScript which depends on code returned by the request may continue to run before the request completes resulting in errors.

    Callback event handlers

    As described in far greater detail in JavaScript Madness: Dynamic Script Loading browsers provide the ability to specify a callback function to run once the script load completes. In most it's as simple as assigning a callback function to the script.onload event handler.

    1. oScript.onload = callback;

    Internet Explorer, as in so many cases, does things differently. It supports a onreadystatechange event handler to which we can assign a callback function. It's slightly more complicated than that used by other browsers as one has to check a return status before running the callback.

    1. oScript.onreadystatechange = function() {
    2. if (this.readyState == 'complete') {
    3. callback();
    4. }
    5. }

    Combining the parts gives us:

    1. function loadScript(sScriptSrc, oCallback) {
    2. var oHead = document.getElementById('head')[0];
    3. var oScript = document.createElement('script');
    4. oScript.type = 'text/javascript';
    5. oScript.src = sScriptSrc;
    6. // most browsers
    7. oScript.onload = oCallback;
    8. // IE 6 & 7
    9. oScript.onreadystatechange = function() {
    10. if (this.readyState == 'complete') {
    11. oCallback();
    12. }
    13. }
    14. oHead.appendChild(oScript);
    15. }

    Detecting script load with timeouts

    Reading a number of sources however it seems that there is a lack of trust in the cross browser robustness of these event handlers. One could instead use timeouts to poll for the existence of required functions returned by the script request and run our callback once detected.

    I wrote the following function to achieve just this recently. The function takes two main parameters, a string representing the function to poll for and a reference to the callback function to run once it's found.

    1. function onFunctionAvailable(sMethod, oCallback, oObject, bScope) {
    2. if (typeof(eval(sMethod)) === 'function') {
    3. bScope ? oCallback.call(oObject) : oCallback(oObject);
    4. } else {
    5. setTimeout(function () {
    6. onFunctionAvailable(sMethod, oCallback, oObject, bScope);
    7. }), 50
    8. }
    9. }

    Two additional parameters allow one to define the scope of "this" within the callback function.

    The hardest part of this function was working out how to detect the existence of a function from a string. Fortunately there's no shortage of people I can turn to with JavaScript skills better than my own. Thanks to Christian, Stuart and Andrew for their input.

    Further Reading