admin管理员组

文章数量:1129631

Any idea why the piece of code below does not add the script element to the DOM?

var code = "<script></script>";
$("#someElement").append(code);

Any idea why the piece of code below does not add the script element to the DOM?

var code = "<script></script>";
$("#someElement").append(code);
Share Improve this question edited Jun 26, 2013 at 8:21 mekwall 29k6 gold badges76 silver badges77 bronze badges asked Mar 4, 2009 at 15:11 Dan InactiveDan Inactive 10.1k19 gold badges51 silver badges71 bronze badges 4
  • 4 define "not working"- though I suspect the problem is that scripts aren't really part of the dom tree. – Joel Coehoorn Commented Mar 4, 2009 at 15:13
  • 1 My bet is that the script node is being added to the DOM, but the browser just isn't executing the script. – Tim Frey Commented Mar 4, 2009 at 15:18
  • Dan, how have you actually tested this? – James Commented Mar 4, 2009 at 15:56
  • 1 @Joel - "not working" = it does not have any effect, i.e. the code within the script is not executed @Outlaw Programmer - the node is not added to the DOM @Jimmy Yes, I have tested it and it's not working – Dan Inactive Commented Mar 8, 2009 at 15:59
Add a comment  | 

19 Answers 19

Reset to default 364

The Good News is:

It's 100% working.

Just add something inside the script tag such as alert('voila!');. The right question you might want to ask perhaps, "Why didn't I see it in the DOM?".

Karl Swedberg has made a nice explanation to visitor's comment in jQuery API site. I don't want to repeat all his words, you can read directly there here (I found it hard to navigate through the comments there).

All of jQuery's insertion methods use a domManip function internally to clean/process elements before and after they are inserted into the DOM. One of the things the domManip function does is pull out any script elements about to be inserted and run them through an "evalScript routine" rather than inject them with the rest of the DOM fragment. It inserts the scripts separately, evaluates them, and then removes them from the DOM.

I believe that one of the reasons jQuery does this is to avoid "Permission Denied" errors that can occur in Internet Explorer when inserting scripts under certain circumstances. It also avoids repeatedly inserting/evaluating the same script (which could potentially cause problems) if it is within a containing element that you are inserting and then moving around the DOM.

The next thing is, I'll summarize what's the bad news by using .append() function to add a script.


And The Bad News is..

You can't debug your code.

I'm not joking, even if you add debugger; keyword between the line you want to set as breakpoint, you'll be end up getting only the call stack of the object without seeing the breakpoint on the source code, (not to mention that this keyword only works in webkit browser, all other major browsers seems to omit this keyword).

If you fully understand what your code does, than this will be a minor drawback. But if you don't, you will end up adding a debugger; keyword all over the place just to find out what's wrong with your (or my) code. Anyway, there's an alternative, don't forget that javascript can natively manipulate HTML DOM.


Workaround.

Use javascript (not jQuery) to manipulate HTML DOM

If you don't want to lose debugging capability, than you can use javascript native HTML DOM manipulation. Consider this example:

var script   = document.createElement("script");
script.type  = "text/javascript";
script.src   = "path/to/your/javascript.js";    // use this for linked script
script.text  = "alert('voila!');"               // use this for inline script
document.body.appendChild(script);

There it is, just like the old days isn't it. And don't forget to clean things up whether in the DOM or in the memory for all object that's referenced and not needed anymore to prevent memory leaks. You can consider this code to clean things up:

document.body.removechild(document.body.lastChild);
delete UnusedReferencedObjects; // replace UnusedReferencedObject with any object you created in the script you load.

The drawback from this workaround is that you may accidentally add a duplicate script, and that's bad. From here you can slightly mimic .append() function by adding an object verification before adding, and removing the script from the DOM right after it was added. Consider this example:

function AddScript(url, object){
    if (object != null){
        // add script
        var script   = document.createElement("script");
        script.type  = "text/javascript";
        script.src   = "path/to/your/javascript.js";
        document.body.appendChild(script);

        // remove from the dom
        document.body.removeChild(document.body.lastChild);
        return true;
    } else {
        return false;
    };
};

function DeleteObject(UnusedReferencedObjects) {
    delete UnusedReferencedObjects;
}

This way, you can add script with debugging capability while safe from script duplicity. This is just a prototype, you can expand for whatever you want it to be. I have been using this approach and quite satisfied with this. Sure enough I will never use jQuery .append() to add a script.

I've seen issues where some browsers don't respect some changes when you do them directly (by which I mean creating the HTML from text like you're trying with the script tag), but when you do them with built-in commands things go better. Try this:

var script = document.createElement( 'script' );
script.type = 'text/javascript';
script.src = url;
$("#someElement").append( script );

From: JSON for jQuery

It is possible to dynamically load a JavaScript file using the jQuery function getScript

$.getScript('http://www.whatever.com/shareprice/shareprice.js', function() {
  Display.sharePrice();
});

Now the external script will be called, and if it cannot be loaded it will gracefully degrade.

What do you mean "not working"?

jQuery detects that you're trying to create a SCRIPT element and will automatically run the contents of the element within the global context. Are you telling me that this doesn't work for you? -

$('#someElement').append('<script>alert("WORKING");</script>');

Edit: If you're not seeing the SCRIPT element in the DOM (in Firebug for example) after you run the command that's because jQuery, like I said, will run the code and then will delete the SCRIPT element - I believe that SCRIPT elements are always appended to the body... but anyway - placement has absolutely no bearing on code execution in this situation.

This works:

$('body').append($("<script>alert('Hi!');<\/script>")[0]);

It seems like jQuery is doing something clever with scripts so you need to append the html element rather than jQuery object.

Try this may be helpful:

var fileref=document.createElement('script');
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src","scriptAnalytics.js");
document.getElementsByTagName("head")[0].appendChild(fileref);

I want to do the same thing but to append a script tag in other frame!

var url = 'library.js'; 
var script = window.parent.frames[1].document.createElement('script' ); 
script.type = 'text/javascript'; 
script.src = url;
$('head',window.parent.frames[1].document).append(script);
<script>
    ...
    ...jQuery("<script></script>")...
    ...
</script>

The </script> within the string literal terminates the entire script, to avoid that "</scr" + "ipt>" can be used instead.

Adding the sourceURL in the script file helped as mentioned in this page: https://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/

  1. In the script file, add a statement with sourceURL like "//@ sourceURL=foo.js"
  2. Load the script using jQuery $.getScript() and the script will be available in "sources" tab in chrome dev tools

Your script is executing , you just can't use document.write from it. Use an alert to test it and avoid using document.write. The statements of your js file with document.write will not be executed and the rest of the function will be executed.

This is what I think is the best solution. Google Analytics is injected this way.

var (function(){
    var p="https:" == document.location.protocol ? "https://" : "http://";
        d=document,
        g=d.createElement('script'),
        s=d.getElementsByTagName('script')[0];
        g.type='text/javascript';
        g.src=p+'url-to-your-script.js';
        s.parentNode.insertBefore(g,s); })();

You don't need jQuery to create a Script DOM Element. It can be done with vanilla ES6 like so:

const script = "console.log('Did it work?')"
new Promise((resolve, reject) => {
  (function(i,s,o,g,r,a,m){
      a=s.createElement(o),m=s.getElementsByTagName(o)[0];
      a.innerText=g;
      a.onload=r;m.parentNode.insertBefore(a,m)}
  )(window,document,'script',script, resolve())
}).then(() => console.log('Sure did!'))

It doesn't need to be wrapped in a Promise, but doing so allows you to resolve the promise when the script loads, helping prevent race conditions for long-running scripts.

Append script to body:

$(document).ready(function() {
    $("<script>", {  src : "bootstrap.min.js",  type : "text/javascript" }).appendTo("body");
});

Another way you can do it if you want to append code is using the document.createElement method but then using .innerHTML instead of .src.

var script = document.createElement( 'script' );
script.type = 'text/javascript';
script.innerHTML = 'alert("Hey there... you just appended this script to the body");';
$("body").append( script );

I tried this one and works fine. Just replace the < symbol with that \x3C.

// With Variable
var code = "\x3Cscript>SomeCode\x3C/script>";
$("#someElement").append(code);

or

//Without Variable
$("#someElement").append("\x3Cscript>SomeCode\x3C/script>");

You can test the code here.

Can try like this

var code = "<script></" + "script>";
$("#someElement").append(code);

The only reason you can't do "<script></script>" is because the string isn't allowed inside javascript because the DOM layer can't parse what's js and what's HTML.

I wrote an npm package that lets you take an HTML string, including script tags and append it to a container while executing the scripts

Example:

import appendHtml from 'appendhtml';

const html = '<p>Hello</p><script src="some_js_file.js"></script>'; 
const container = document.getElementById('some-div');

await appendHtml(html, container);

// appendHtml returns a Promise, some_js_file.js is now loaded and executed (note the await)

Find it here: https://www.npmjs.com/package/appendhtml

/* SELECTOR */


$T = document.getElementsByTagName.bind( document );


/* INCLUDE */


function include( file_js )
{
    // Create script
    var s       = document.createElement( "script" );
        s.src   = file_js;
        s.type  = "text/javascript";
        s.defer = true;

    // Append script
    $T( "head" ).item(0).appendChild( s );
}

 /* TEST CODE */


<script>
    include( "<? echo ROOT ?>/lib/js/test.js" ); // Test.js contains: console.log( "Hello World" );
</script>


/* RESULT (in Google Chrome DevTool: Elements) */


    <script src="http://localhost/mysite/lib/js/test.js" type="text/javascript" defer></script>
</head>


/* RESULT (in Google Chrome DevTool: Console) */


Hello World

Defer attribute: a script that will be downloaded in parallel to parsing the page, and executed after the page has finished parsing:

Just create an element by parsing it with jQuery.

<div id="someElement"></div>
<script>
    var code = "<script>alert(123);<\/script>";
    $("#someElement").append($(code));
</script>

Working example: https://plnkr.co/edit/V2FE28Q2eBrJoJ6PUEBz

本文标签: javascriptCan39t append ltscriptgt elementStack Overflow