Tutorial: Script injection by hand

Script injection by hand

Dynamic script tag injection is discussed comprehensively here.

Here this technique is demonstrated without requiring any other source dependencies.

This example contains an optional callback onJSLibraryLoaded which is notified about the success or error of the asynchronous network loading operation. Also note that the library is available just when the global callback onYalstVisitorAPILoaded is invoked, not right after it is loaded into the browser.

(function(callback)
    {
        var YALST_INSTALLATION_URL = "//YALST_PRODUCT_SERVER/YALST_DIRECTORY";

        var anchorElement = document.getElementsByTagName('script')[0];

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

        // load the production version
        script.src = YALST_INSTALLATION_URL + "/visitor_api/v2.1/LiveSupport.min.js";

        if (script.addEventListener) // IE9+
        {
            script.addEventListener('load', onLoad, false);
            script.addEventListener('error', onError, false);

            anchorElement.parentNode.insertBefore(script, anchorElement);
        }
        else
        {
            script.attachEvent('onreadystatechange', function()
                {
                    if (script.readyState == "complete")
                    {
                        anchorElement.parentNode.insertBefore(script, anchorElement);

                        onLoad();
                    }
                    else if (script.readyState == "loaded")
                    {
                        // hack: calling 'children' property changes node's readyState
                        script.children;

                        if (script.readyState == 'loading') // error detected
                        {
                            anchorElement.parentNode.insertBefore(script, anchorElement);

                            onError();
                        }
                    }
                }
            );
        }

        function onLoad(event)
        {
            if (callback && (typeof callback == "function"))
            {
                if ( ( event && (event.type == "load") )
                    || (script.readyState && script.readyState.match(/^(complete|loaded)$/)) )
                {
                    callback();
                }
            }
        }

        function onError()
        {
            if (callback && (typeof callback == "function"))
            {
                callback(new Error("Network error: Could not load " + script.src));
            }
        }
    }(onJSLibraryLoaded));

    function onJSLibraryLoaded(error)
    {
        if (error)
        {
            /// handle the error (file not found or network failure) here
        }


    }

    function onYalstVisitorAPILoaded(api)
    {
        // use the API now globally available in LiveSupport.VisitorAPI
        // as well as in the first function argument api

    }