2

I am toying around with some basic constructs in HTML and Javascript (i.e., I am a HTML/Javascript n00b), and there is a feature I simply cannot seem to implement properly. In a nutshell, I'd like to grab text from the body of an HTML page and evaluate it using Javascript (either eval() or new Function()). To see that my use of eval() is right, I first tried the following code, which works as expected (and displays the value 5):

<script>
window.onload = function () {
    eval("var t = function () { if (5>0) return 5; }();");
    document.body.innerHTML = t;
}
</script>

However, when I then attempt to achieve my goal of grabbing the "code" from the HTML and running it, this seems to fail for me. Here's a piece of code that doesn't work (I've tried many variations of this):

<script>
window.onload = function() {
    var x = document.getElementById("myP").innerHTML;
    eval("var e = " + x + ";");
    document.body.innerHTML = e();
}
</script>

<body>
    <p id="myP">function () { if (5>1) { return 5; } } </p>
</body>

I tested that the variable x does in fact contain the desired "code" from the body. But for some reason, the above will just not work correctly; it will just display the body and ignore the eval and the statement after it updating the innerHTML.

What's stranger is that when I try code that is "more complex", it works fine, such as:

<script>
window.onload = function() {
    var x = document.getElementById("myP").innerHTML;
    eval("var e = " + x + ";");
    document.body.innerHTML = e();
}
</script>

<body>
    <p id="myP">function () { var a = []; var b = [1,2,3]; for (var i in b) { a.push([b[i],'q']); } return a; } </p>
</body>

It seems really weird to me that this example should work but not the previous one; does eval() hate if-statements? Am I missing some subtle aspect of eval()? Am I missing some super-basic Javascript syntax? Any help is appreciated, both in getting the above particular instance to work, as well as advice for how to implement what I am trying to do generally, i.e. to pass any code from HTML to eval().

NOTE: If possible, please avoid any comments/answers about how eval() is "evil" or is a major security issue, or any such remarks. I am aware of these concerns. My issue is within the context of a personal project and has no chance of being publicly deployed or used unsafely etc.

Eugene J. Lee
  • 580
  • 2
  • 10
Coffee_Table
  • 262
  • 1
  • 5
  • 14
  • What is the `e()` you are trying to execute? Trying doing just `document.body.innerHTML = e;` – khalid13 May 18 '15 at 18:42
  • @khalid13 its in the statement executed by the eval(); its assigned a function, hence the e(). it executes fine in my 3rd code example... – Coffee_Table May 18 '15 at 18:44
  • 1
    It's probably an encoding issue, like certain characters being converted to their HTML Entity versions. – Paul May 18 '15 at 18:47
  • 1
    To avoid the problem that James described you can enclose in a template. See this post for more information: [Explanation of – Yogi May 18 '15 at 19:02

1 Answers1

6

The problem here is related to the DOM, rather than JavaScript. You're asking for the innerHTML of a node. If you have a look at what you end up with the problem becomes clear:

var x = document.getElementById("myP").innerHTML;
console.log(x); // "function () { if (5&gt;1) { return 5; } }"

The browser has converted the > character into an HTML entity. What you need is the textContent of the node:

var x = document.getElementById("myP").textContent;
console.log(x); // "function () { if (5>1) { return 5; } }"

Here's a working example.

James Allardice
  • 164,175
  • 21
  • 332
  • 312
  • out of curiosity, I notice you use both "innerText" and "textContent"; would you mind briefly commenting on the difference? – Coffee_Table May 18 '15 at 18:53
  • 1
    @Coffee_Table sorry, it should have been `textContent`. `innerText` was introduced in Internet Explorer and AFAIK isn't part of a standard. Most browsers will support it but `textContent` is preferable for reasons discussed in the linked `textContent` page. – James Allardice May 18 '15 at 19:03