Dynamic loading of JavaScript files

I am working on a JavaScript framework that uses JQueryMobile. The framework can be used for both mobile and non-mobile sites. You can set the page for mobile by calling, for example, enableMobile method. So the framework does not load JS files for JQueryMobile up front. It does so only when enableMobile method is called.

First I tried to include JS file for JQueryMobile using document.write method –

document.write("<script src='jquery.mobile-1.1.0.js' type='text/javascript'><\/script>\n");

However this did not work – the page was not converted to JQueryMobile page, i.e. CSS styles of JQM were not applied to the page. Instead I got following error –

Uncaught TypeError: Cannot call method ‘_trigger’ of undefined jquery.mobile-1.1.0.js:2791

I have created a simple test case to show this error –

DOCTYPE html>
<html>
    <head>
        <link type='text/css' href='jquery.mobile-1.1.0.css' rel='stylesheet'/>
        <script src="jquery-1.7.2.js" type="text/javascript"></script>

        <script language="JavaScript">
            $(document).ready(function(){
                loadLibrary();
            });

            function loadLibrary()
            {
                document.write("<script src='jquery.mobile-1.1.0.js' type='text/javascript'><\/script>\n");
            }
        </script>
    </head>
<body>
    <div data-role="page">
        <div data-role="header">
            Header
        </div>
        <div data-role="content">
            This is the main content
        </div>
        <div data-role="footer">
            Footer
        </div>
    </div>
</body>

After some search on the web, I realized that document.write is not the right way to include JS file, if it is loaded asynchronously after the page is loaded. If you include a JS file this way and follow it immediately with JS code that uses the included file, then it may not work. Because the browser does not execute the included page immediately after document.write. It does so later, asynchronously. So the code following included page would not have access to functions of that page.

I found that JQuery has a handy function to load JS files dynamically – $.getScript(..) . It takes script path and callback function as arguments. The callback is called by JQuery after the script is loaded and executed. So when I changed loadLibrary function as follows, everything worked fine.

function loadLibrary()
{
    $.getScript("jquery.mobile-1.1.0.js",function(){
        //write JQM dependent code here
    });
}

However, I am not sure why JQM throws ‘Cannot call method ‘_trigger’ of undefined’ error when I use document.write. My guess is that JQM registers listeners with JQuery and when one of the listeners is called, possibly at that time JQM is not loaded completely. However I could be wrong about this, because I have not investigated the root cause of this error in detail. But, as mentioned above, loading the file using $.getScript fixed the problem.

– Ram Kulkarni

Leave a Reply