tags:

views:

197

answers:

6

Hi guys,

I want to include a remote js file and then invoke a function once that has finished executing. I thought I could do something like this:

var sc = document.createElement('script');
sc.setAttribute('type', 'text/javascript');
sc.setAttribute('src', src);
sc.innerHTML = "alert('testing');"
parentNode.appendChild(sc);

Turns out, the alert('testing') gets wiped out be whatever is in the file. Is there anyway to do this?

+1  A: 

Adding another

<script></script>

section after the first one should work. AFAIK you can't mix external and inline JS in one tag.

However I'm not sure whether putting code into "innerHTML" will work as expected. I'm interested to see whether it does.

Pekka
Good point, it might be safer to use CreateTextNode and append it to the script node.
AnthonyWJones
+1  A: 

Have you tried just creating a second script element containing the code you want to run and adding that after the you've added the one that needs downloading?

AnthonyWJones
A: 

You might be able to use the sc load event to figure out when that script has loaded then do some action.

example http://iamnoah.blogspot.com/2008/01/ie-script-load-event.html

John Boker
A: 

I created this script for myself yesterday. It uses jQuery to load JavaScript files via AJAX and adds them in a script tag to the header, and then calls a callback function I pass it.

Has been working fine for me.

/**
 * Fetches and executes JavaScript files from the server.
 * @param files A list of files to load, or a single filename as a string.
 * @param callback The function to call when the process is done. Passes a boolean success value as the only parameter.
 * @param thisObject The calling object for the callback.
 */
window.include = function(files, callback, thisObject) {
    var current_location = null;
    var recursive = false;

    if(!(thisObject instanceof Object)) {
        thisObject = window;
    }

    if(files instanceof Array || files instanceof Object) {
        if(files.length > 0) {
            current_location = files.shift();
            recursive = true;
        }
        else {
            callback.apply(thisObject, [true]);
            return;
        }
    }
    else if(typeof files == 'string') {
        current_location = files;
    }
    else {
        callback.apply(thisObject, [false]);
        return;
    }

    if((current_location instanceof String || typeof current_location == 'string') && current_location != '')
    {
        $.ajax({
            type : 'GET',
            url  : current_location,
            timeout : 5000,
            success : function(data) {
                var scriptTag = $(document.createElement('script'));
                scriptTag.attr('type', 'text/javascript');
                scriptTag.html(data);
                $('head').append(scriptTag);

                if(recursive) {
                    window.adlib.include(files, callback, thisObject);
                }
                else {
                    callback.apply(thisObject, [true]);
                }
            },
            error : function() {
                callback.apply(thisObject, [false]);
            }
        });
    }
}
Atli
+1  A: 

First thing is, forget about using src and inner contents on the same script tag. It doesn't work in any general way, although John Resig gave it some thought in this blog post.

Second thing is, decide whether you want to load the script synchronously or asynchronously. If the script is large or long-running, you'll either want to do it asynchronously, or do it synchronously at the bottom of the page so as not to block rendering.

Your approach (dynamically appending script tags) will load and run it asynchronously, which means the code that should run after it's finished needs to go in a callback that fires when the script is finished. Setting this up isn't very straightforward, so I'd suggest either using jQuery and its ajax.getScript function, or just copy the getScript functionality right out of the jQuery source (lines 3473-3505 of jQuery 1.3.2).

If you want to avoid all of that, just load it synchronously. This is done by using document.write. Your provided example would look like:

document.write("<scr" + "ipt src='" + src + "' type='text/javascript'></script>");
// The script is guaranteed to have executed at this point
alert('testing');

Be sure to keep "script" split up like that, I'm not sure why but it's a quirk of JavaScript.

darkporter
A: 

This function will load library from scriptPath and execute passed handler function once script is loaded:

loadExternalScript : function(scriptPath, handler) {

 var head = document.getElementsByTagName('head')[0];
 var script = document.createElement('script');
 script.type = 'text/javascript';
 script.src = scriptPath;
 script.charset = 'utf-8';

 script.onload = handler;

 head.appendChild(script);

}
Rudi