lvil
lvil

Reputation: 4326

Insert and execute javascript

I have a javascript variable:

var foo='<script type="text/javascript">alert("Hello World");<\/script>'  

The variable is inserted with element.innerHTML=foo; after an event occurs on the page, about 10 seconds after the page is loaded.

Is there a way to execute the 'alert' function right after the insertion?

Upvotes: 3

Views: 3065

Answers (2)

T.J. Crowder
T.J. Crowder

Reputation: 1074028

If you absolutely, positively have to take JavaScript code that's in a string and execute it, you basically have to use eval or an eval-like mechanism. In some years of JavaScript programming, I've never had to resort to it, and I do suggest that you look at whether there's another way to achieve your actual overall goal.

So here, you'd strip off the script tag stuff and just eval the code, e.g.:

var script = foo.replace(/^<script[^>]*>/, "").replace(/<\/script>$/, "");
eval(script);
// Or window.evalInGlobalScope(script); // -- See below

Obviously you have to be sure you trust the source of the string, since you're executing the code therein.

eval is a slippery beast and plays very odd games with context and scope. If you need something that looks more like what you'd get if you did add a script tag to the page, here's a function that does that cross-browser (from my answer to this other question here on Stack Overflow):

window.evalInGlobalScope = (function() {
    var fname, scr;

    // Get a unique function name
    do {
        fname = "__eval_in_global_test_" + Math.floor(Math.random() * 100000);
    }
    while (typeof window[fname] !== 'undefined');

    // Create test script
    scr = "function " + fname + "() { }";

    // Return the first function that works:
    return test(evalInGlobalScope_execScript) ||
           test(evalInGlobalScope_windowEval) ||
           test(evalInGlobalScope_theHardWay) ||
           evalInGlobalScope_fail;

    function test(f) {
        try {
            f(scr);
            if (typeof window[fname] === 'function') {
                return f;
            }
        }
        catch (e) {
            return false;
        }
        finally {
            try { delete window[fname]; } catch (e) { window[fname] = undefined; }
        }
    }
    function evalInGlobalScope_execScript(str) {
        window.execScript(str);
    }
    function evalInGlobalScope_windowEval(str) {
        window.eval(str);
    }
    function evalInGlobalScope_theHardWay(str) {
        var parent, script, d = document;

        parent = d.body || d.documentElement || d.getElementsByTagName('head')[0];
        if (parent) {
            script = d.createElement('script');
            script.appendChild(d.createTextNode(str));
            parent.appendChild(script);
        }
    }
    function evalInGlobalScope_fail() {
        throw "evalInGlobalScope: Unable to determine how to do global eval in this environment";
    }
})();

Live example using the above

Upvotes: 5

Shadow Wizard
Shadow Wizard

Reputation: 66389

You don't need to make lots of changes, just one small change.

Right now you have such line of code:

oDiv.innerHTML = foo;

Just change it to those three lines instead:

var oScript = document.createElement("script");
oScript.innerHTML = foo;
oDiv.appendChild(oScript);

And have foo contain only the raw JS, without the <script> and </script> tags.

Live text case.

Upvotes: 0

Related Questions