Reputation: 726
I am trying to add a script block dynamically to the document. When I do this, the script block is not getting executed.
<body>
<div id="dynamicDiv">
</div>
<script type="text/javascript">
var elem = document.getElementById("dynamicDiv");
var tmpStr = "<script type=\"text\/javascript\"> ";
tmpStr += "function hello (val)";
tmpStr += "{";
tmpStr += "alert('hello ' + val);";
tmpStr += "}";
tmpStr += "<\/script>";
elem.innerHTML = tmpStr;
hello("World");
</script>
</body>
The above code does not work. From another post (How do you execute a dynamically loaded JavaScript block?), I saw a reply that if script is added to innerHTML, it will not be executed. Instead of directly using innerHTML, create a div with this innerHTML and use appendChild to add the script.
<body>
<div id="dynamicDiv">
</div>
<script type="text/javascript">
var elem = document.getElementById("dynamicDiv");
var tmpStr = "<script type=\"text\/javascript\"> ";
tmpStr += "function hello (val)";
tmpStr += "{";
tmpStr += "alert('hello ' + val);";
tmpStr += "}";
tmpStr += "<\/script>";
var newdiv = document.createElement('div');
newdiv.innerHTML = tmpStr;
elem.appendChild(newdiv);
hello("World");
</script>
</body>
How ever, this solution also did not work for me.
In another reply, I again saw that we should get the script elements and execute them using eval.
<body>
<div id="dynamicDiv">
</div>
<script type="text/javascript">
var elem = document.getElementById("dynamicDiv");
var tmpStr = "<script type=\"text\/javascript\"> ";
tmpStr += "function hello (val)";
tmpStr += "{";
tmpStr += "alert('hello ' + val);";
tmpStr += "}";
tmpStr += "<\/script>";
var newdiv = document.createElement('div');
newdiv.innerHTML = tmpStr;
elem.appendChild(newdiv);
var scripts = newdiv.getElementsByTagName('script');
for (var ix = 0; ix < scripts.length; ix++) {
eval(scripts[ix].text);
}
hello("World");
</script>
</body>
This solution works for me.
But if do this in a function then it does not work.
<body>
<div id="dynamicDiv">
</div>
<script type="text/javascript">
function createFunction(){
var elem = document.getElementById("dynamicDiv");
var tmpStr = "<script type=\"text\/javascript\"> ";
tmpStr += "function hello (val)";
tmpStr += "{";
tmpStr += "alert('hello ' + val);";
tmpStr += "}";
tmpStr += "<\/script>";
var newdiv = document.createElement('div');
newdiv.innerHTML = tmpStr;
elem.appendChild(newdiv);
var scripts = newdiv.getElementsByTagName('script');
for (var ix = 0; ix < scripts.length; ix++) {
eval(scripts[ix].text);
}
hello("World 1");
}
createFunction();
hello("World 2");
</script>
</body>
I can see that the function is available after the script is evaled. and is available in the function createFunction. Outside createFunction() scope, hello() is not available.
What am I doing wrong? Am I missing something very basic? Please check and help.
Thanks, Paul
P.S. I don't use jQuery. I am using chrome to test this.
Upvotes: 4
Views: 6246
Reputation: 3355
Would like to point out that the reason the 3rd snippet you provided works inside the for loop, but not outside is because you are using eval
. eval
takes a string and executes it as js, which is why it is working inside the loop, but using eval
isn't parsing it for future use, which is causing it to be unusable elsewhere. Therefore, when you go to call it outside the loop, you get a reference error.
UPDATE:
If you are getting the string back with the <script>
tags in it, you can just parse out the script tags.
var string = "<script type=\"text\/javascript\"> ";
string += "function hello (val)";
string += "{";
string += "alert('hello ' + val);";
string += "}";
string += "<\/script>";
string = string.replace(/<(script|\/script).*?>/g,'');
function createFunction() {
var elem = document.getElementById("dynamicDiv");
var script = document.createElement('script');
script.innerHTML = string;
elem.appendChild(script);
hello("World 1");
}
createFunction()
hello('world 2');
JSFiddle: http://jsfiddle.net/3wYD6/
I don't really see the point of this, but if you really want to do this you can create a new script element and then set it's innerHTML to the function, then append the new script to a div.
var elem = document.getElementById("dynamicDiv"),
script = document.createElement('script');
script.innerHTML =
'function hello (val) {' +
'alert("hello " + val);' +
'}';
elem.appendChild(script);
hello('world');
Upvotes: 2
Reputation: 418
In your first try you are creating a string and js interpreter handle it as a string, not an html tag, so js doesn't really care about your script tags presented in that string.
Then of course it's working when you start using eval() because eval - is evil:))
After all you can create script tags dynamically and then fill it with code:
var elem = document.getElementById("dynamicDiv"),
scriptTag = document.createElement('script'),
scriptTagCode = 'function hello (val){alert("hello " + val);}';
scriptTag.innerHTML = scriptTagCode;
elem.appendChild(scriptTag);
hello('foo');
Upvotes: 0