Search code examples
javascripthtmleval

How to use eval in the program


I am developing a javascript program -- graphing calculator. User inputs an equation (like x*x+2*x ) into text field, presses "get answer" button and should get a graph. If I write in function f(x) an expression, like "Math.sin(x)" it works great, but when I try to use eval method to evaluate the users code, the program stops working. I'm new to javascript. Any help would be appreciated! JavaScript code

//vars
var points = "";
var input = document.querySelector("#input");
var evaluate = document.querySelector("#evaluate");

evaluate.addEventListener('click', function() {
  document.body.appendChild(makeSVG(svgData));
});

function f(x) {
  return eval('(function() { x=' + x + ';' + input.value + ';}())');
}

function getPoints() {
  for (var i = -10; i < 10.0; i += 0.25) {
    var x = 10 * i + 100;
    var y = -10 * f(i) + 100;
    points += "" + x + "," + y + " ";
  }
  return points;
}

var svgData = [{
    type: 'svg',
    data: {
      viewBox: "0 0 500 200"
    }
  },
  {
    type: 'polyline',
    data: {
      fill: "none",
      stroke: "black",
      strokeWidth: "1",
      points: getPoints()
    }
  },
];

function getNode(n, v) {
  n = document.createElementNS("http://www.w3.org/2000/svg", n);
  for (var p in v) {
    n.setAttributeNS(null, p.replace(/[A-Z]/g, function(m, p, o, s) {
      return "-" + m.toLowerCase();
    }), v[p]);
  }
  return n
}

function makeSVG(data) {
  var result;
  data.forEach(
    function(elem, index, array) {
      if (index)
        result.appendChild(getNode(elem.type, elem.data));
      else
        result = getNode(elem.type, elem.data);
    }
  );
  return result;
}
<!DOCTYPE html>

<html>

<head>
  <title>Graphing Calculator</title>
</head>

<body>
  <h1>Graphing Calculator</h1>
  <form>
    <input id="input" type="text">
    <button id="evaluate" type="button">Get answer</button>
  </form>
  <script type="text/javascript" src="code.js"></script>
</body>

</html>


Solution

  • There's no need for the IIFE in f(). Just call eval(x). It will execute in the scope of f(), so it can access x.

    Another problem is that you're calling getPoints() when you initialize svgData, but the user hasn't yet filled in the input field. You need to do that in the click handler.

    //vars
    var points = "";
    var input = document.querySelector("#input");
    var evaluate = document.querySelector("#evaluate");
    
    evaluate.addEventListener('click', function() {
      svgData[1].data.points = getPoints();
      document.body.appendChild(makeSVG(svgData));
    });
    
    function f(x) {
      return eval(input.value);
    }
    
    function getPoints() {
      for (var i = -10; i < 10.0; i += 0.25) {
        var x = 10 * i + 100;
        var y = -10 * f(i) + 100;
        points += "" + x + "," + y + " ";
      }
      return points;
    }
    
    var svgData = [{
        type: 'svg',
        data: {
          viewBox: "0 0 500 200"
        }
      },
      {
        type: 'polyline',
        data: {
          fill: "none",
          stroke: "black",
          strokeWidth: "1",
          points: null
        }
      },
    ];
    
    function getNode(n, v) {
      n = document.createElementNS("http://www.w3.org/2000/svg", n);
      for (var p in v) {
        n.setAttributeNS(null, p.replace(/[A-Z]/g, function(m, p, o, s) {
          return "-" + m.toLowerCase();
        }), v[p]);
      }
      return n
    }
    
    function makeSVG(data) {
      var result;
      data.forEach(
        function(elem, index, array) {
          if (index)
            result.appendChild(getNode(elem.type, elem.data));
          else
            result = getNode(elem.type, elem.data);
        }
      );
      return result;
    }
    <!DOCTYPE html>
    
    <html>
    
    <head>
      <title>Graphing Calculator</title>
    </head>
    
    <body>
      <h1>Graphing Calculator</h1>
      <form>
        <input id="input" type="text">
        <button id="evaluate" type="button">Get answer</button>
      </form>
      <script type="text/javascript" src="code.js"></script>
    </body>
    
    </html>