Javascript 如何评估web应用程序中的用户代码输入

Javascript 如何评估web应用程序中的用户代码输入,javascript,jquery,html,codemirror,Javascript,Jquery,Html,Codemirror,我试图建立一个演示网站,以帮助其他人学习代码。我在评估来自代码的用户输入时遇到问题。我知道我可以使用eval()函数,但是我将有很多示例,并且有许多eval()函数似乎不是很理想或简洁。如果我使用eval(),那么实现最佳实践的最佳方法是什么 或者,是否有一种方法可以实现一个简单的编译器或泛型函数,并指定一个按钮单击以运行所述函数,该函数将在编辑器中计算代码并将其显示在页面的某个位置 我目前正在为我的编辑器使用。也许他们的api中有一个函数可以做到这一点,但我找不到它。我也知道我可以使用代码镜像

我试图建立一个演示网站,以帮助其他人学习代码。我在评估来自代码的用户输入时遇到问题。我知道我可以使用
eval()
函数,但是我将有很多示例,并且有许多
eval()
函数似乎不是很理想或简洁。如果我使用
eval()
,那么实现最佳实践的最佳方法是什么

或者,是否有一种方法可以实现一个简单的编译器或泛型函数,并指定一个按钮单击以运行所述函数,该函数将在编辑器中计算代码并将其显示在页面的某个位置

我目前正在为我的编辑器使用。也许他们的api中有一个函数可以做到这一点,但我找不到它。我也知道我可以使用代码镜像,但也不确定他们的解决方案。任何帮助都将不胜感激

是指向JSBIN的链接(注意:代码编辑器没有显示在这里,因为我不需要库

是指向我拥有运行版本的站点的链接

如果您需要查看我在下面发布的代码:

HTML

    <!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <title>Learn to Code with Codesmith</title>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
  <link href='http://fonts.googleapis.com/css?family=Open+Sans:400;300' rel='stylesheet' type='text/css'>
  <link href='style.css' rel='stylesheet'>
  <style type="text/css" media="screen">

  </style>
</head>
<body>

  <!-- <div class="page-wrapper">
    <a class="btn trigger" href="javascript:;">Click Me!</a>
  </div> -->
  <div class="modal-wrapper">
    <div class="modal">
      <div class="head">
        <a class="btn-close trigger" href="javascript:;"></a>
      </div>
      <div class="content">
        <form class="" action="" method="post">
          <input id="username" type="text" name="name" value="" placeholder="Username">
          <input id="password" type="text" name="name" value="" placeholder="Password">
          <button id="login-submit" type="button" name="button">LOGIN</button>
        </form>
      </div>
    </div>
  </div>

  <div class="menu">

    <!-- Menu icon -->
    <div class="icon-close">
      <img src="http://s3.amazonaws.com/codecademy-content/courses/ltp2/img/uber/close.png">
    </div>

    <!-- Menu -->
    <ul>
      <li class="main-cat"><a href="#">FOUNDATIONS</a></li>
      <ul>
        <li class="sub-cat"><a href="#">Intro to Javascript</a></li>
        <li class="sub-cat"><a href="#">Algorithms</a></li>
        <li class="sub-cat"><a href="#">Data Structures</a></li>
        <li class="sub-cat"><a href="#">Data Types</a></li>
        <li class="sub-cat"><a href="#">Syntax</a></li>
        <li class="sub-cat"><a href="#">Variables</a></li>
        <li class="sub-cat"><a href="#">Strings</a></li>
        <li class="sub-cat"><a href="#">Arrays</a></li>
        <li class="sub-cat"><a href="#">Objects</a></li>
        <li class="sub-cat"><a href="#">Functions</a></li>
        <li class="sub-cat"><a href="#">Scope</a></li>
      </ul>
      <li class="main-cat"><a href="#">Intermediate</a></li>
      <li class="main-cat"><a href="#">Advanced</a></li>

    </ul>
  </div>



  <!-- Main body -->
  <div class="nav">

    <button class="sign-up" type="button" name="button" onclick="">SIGN UP</button>

    <!-- <a class="btn trigger" href="javascript:;">Click Me!</a> -->
    <!-- <button class="login trigger" type="button" name="button" onclick="">LOGIN</button> -->
    <a class="login trigger" type="button" name="button" onclick="" href="javascript:;">LOGIN</a>

    <div class="icon-menu">
      <i class="fa fa-bars"></i>
      Menu
    </div>

  <div class="video">
    <iframe width="560" height="315" src="https://www.youtube.com/embed/JeyH_8pWVJ4" frameborder="0" allowfullscreen></iframe>
  </div>

  <div class="code-snippet sandbox">
    <pre id="editor"> // Write your code here and when finished, click the run button below...
    <!-- function greeting() {
      console.log("Hello, World!");
    } -->
    </pre>



    <div id="run-code">
      <button class="run-code" type="button" name="button" onclick="evaluate()" >RUN</button>
    </div>
  </div>

  <!-- <textarea class="code-eval" name="output" rows="8" cols="40"></textarea> -->


  <!-- <a class="jsbin-embed" href="http://jsbin.com/iwovaj/73/embed?html,output&height=315px&width=700px"></a>
  <script src="http://static.jsbin.com/js/embed.js"></script> -->

  <script src="src-noconflict/ace.js" type="text/javascript" charset="utf-8"></script>
  <script>
      var editor = ace.edit("editor");
      editor.setTheme("ace/theme/chaos");
      editor.session.setMode("ace/mode/javascript");
      editor.session.getLength(true);
      document.getElementById('editor').style.fontSize='14px';
      editor.getSession().setUseWrapMode(true);
      editor.setHighlightActiveLine(true);
  </script>
  <script src="sandbox.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script></script>
  <script src="app.js"></script>
</body>
</html>
JAVASCRIPT

var main = function() {
  /* Push the body and the nav over by 285px over */
  $('.icon-menu').click(function() {
    $('.menu').animate({
      left: "0px"
    }, 100);

    $('body').animate({
      left: "285px"
    }, 100);
  });

  /* Then push them back */
  $('.icon-close').click(function() {
    $('.menu').animate({
      left: "-285px"
    }, 100);

    $('body').animate({
      left: "0px"
    }, 100);
  });
};


/* ========== Evaluate Code ========== */

var app = {};

// go through the application and find every single instance of a div
// with the class of 'sandbox'
app.bootstrap = function() {
  var sandboxes = document.getElementsByClassName('sandbox');

  // for each sandbox, run the createSandbox function
  [].forEach.call(sandboxes, app.createSandbox);
};

// given a parent element, find the first textarea inside and
// create a sandbox around it
app.createSandbox = function(parent) {
  var textarea = parent.getElementsByTagName('textarea')[0],
      // create an instance of Sandbox using this textarea
      sandbox = Sandbox(textarea);

  parent.appendChild(sandbox.label);
};

// when the DOM loads bootstrap the application
window.addEventListener('load', app.bootstrap);

// Sandbox class
// This class is based around a textarea element, which will contain
// the code. However, it could just as easily be the DOM element for
// an Ace/Codemirror editor.
function Sandbox(textarea) {
  var sandbox = {};

  // create a label to show output
  sandbox.label = document.createElement('label');
  sandbox.label.setAttribute('class', 'output');
  sandbox.label.addEventListener('click', evaluate);

  // evaluate code whenever there is input into the textarea
  textarea.addEventListener('input', evaluate);
  sandbox.textarea = textarea;

  // initial resize and evaluation
  resize();
  evaluate();

  // resize to within the appropriate height for the textarea
  function resize() {
    var scrollHeight = textarea.scrollHeight;

    if(scrollHeight > Sandbox.MAX_HEIGHT) {
      height = Sandbox.MAX_HEIGHT;
    } else if(scrollHeight < Sandbox.MIN_HEIGHT) {
      height = Sandbox.MIN_HEIGHT;
    } else {
      height = scrollHeight;
    }

    textarea.style.height = height + 'px';
  }

  // evaluate the code within the textarea
  function evaluate() {
    // get the code
    var src = textarea.value,
    // create a console proxy (for logging to the label)
        console = Sandbox.consoleProxy(sandbox.label);

    // clear the output first
    sandbox.label.innerText = '';
    // try the eval and catch errors to send to the console
    try {
      /* jshint ignore:start */
      eval(src);
      /* jshint ignore:end */
    } catch(err) {
      console.error(err);
    }
  }

  return sandbox;
}

// config
Sandbox.MAX_HEIGHT = 500;
Sandbox.MIN_HEIGHT = 50;

// A function which spoofs the native console object, by writing
// text to output elements, rather than the dev tools console.
Sandbox.consoleProxy = function(element) {
  return {
    log: function(message) {
      message = [].join.call(arguments, ' ');
      element.innerText += (message + '\n');
      element.setAttribute('disabled', false);
      // write to the original console too
      console.log.apply(console, arguments);
    },
    error: function(message) {
      element.setAttribute('disabled', true);
      element.innerText = message;
    }
  };
};


/* ========== Modal  ========== */

$('.trigger').click(function() {
     $('.modal-wrapper').toggleClass('open');
    $('.page-wrapper').toggleClass('blur');
     return false;
  });

$(document).ready(main);
var main=function(){
/*将车身和导航装置推过285px*/
$('.icon-menu')。单击(函数(){
$('.menu')。设置动画({
左:“0px”
}, 100);
$('body')。设置动画({
左:“285px”
}, 100);
});
/*然后把他们推回去*/
$('.icon close')。单击(函数(){
$('.menu')。设置动画({
左:“-285px”
}, 100);
$('body')。设置动画({
左:“0px”
}, 100);
});
};
/*=============评估代码===================*/
var-app={};
//检查应用程序并找到div的每个实例
//使用“沙盒”类
app.bootstrap=函数(){
var sandboxes=document.getElementsByClassName('sandbox');
//对于每个沙盒,运行createSandbox函数
[].forEach.call(沙盒,app.createSandbox);
};
//给定一个父元素,找到内部的第一个textarea并
//在它周围创建一个沙箱
app.createSandbox=函数(父级){
var textarea=parent.getElementsByTagName('textarea')[0],
//使用此textarea创建沙盒实例
沙箱=沙箱(文本区域);
parent.appendChild(sandbox.label);
};
//当DOM加载引导应用程序时
window.addEventListener('load',app.bootstrap);
//沙箱类
//此类基于textarea元素,该元素将包含
//但是,它也可以很容易地成为的DOM元素
//Ace/Codemirror编辑器。
功能沙盒(文本区域){
var sandbox={};
//创建一个标签以显示输出
sandbox.label=document.createElement('label');
sandbox.label.setAttribute('class','output');
sandbox.label.addEventListener('click',evaluate');
//每当文本区域中有输入时,对代码求值
textarea.addEventListener(“输入”,评估);
sandbox.textarea=textarea;
//初始调整和评估
调整大小();
评估();
//将大小调整到文本区域的适当高度范围内
函数resize(){
var scrollHeight=textarea.scrollHeight;
如果(滚动高度>沙箱最大高度){
高度=沙箱最大高度;
}否则如果(滚动高度<沙箱最小高度){
高度=沙箱最小高度;
}否则{
高度=滚动高度;
}
textarea.style.height=高度+px;
}
//计算textarea中的代码
函数求值(){
//获取代码
var src=textarea.value,
//创建控制台代理(用于记录到标签)
console=Sandbox.consoleProxy(Sandbox.label);
//首先清除输出
sandbox.label.innerText='';
//尝试eval和catch错误以发送到控制台
试一试{
/*jshint忽略:开始*/
eval(src);
/*jshint忽略:结束*/
}捕捉(错误){
控制台错误(err);
}
}
返回沙箱;
}
//配置
沙箱最大高度=500;
沙箱最小高度=50;
//一个函数,通过写入
//文本输出元素,而不是开发工具控制台。
Sandbox.consoleProxy=函数(元素){
返回{
日志:功能(消息){
message=[].join.call(参数“”);
element.innerText+=(消息+'\n');
元素setAttribute('disabled',false);
//也可以写入原始控制台
console.log.apply(控制台,参数);
},
错误:函数(消息){
元素。setAttribute('disabled',true);
element.innerText=消息;
}
};
};
/*================模式=========================*/
$('.trigger')。单击(函数(){
$('.modal wrapper').toggleClass('open');
$('.page wrapper').toggleClass('blur');
返回false;
});
$(文件).ready(主);

eval
是一种运行代码的实际方式。由于它与安全漏洞的关联,它的声誉不太好,但是,如果这不是一个问题,用户将在沙箱中运行自己的代码,这正是
eval
设计的目的,而且它做得很好

为Javascript实现一个简单的编译器不是一件容易的事情,但是如果您确信这是正确的方法,那么您可以利用开源项目,例如在解析和评估代码时为您完成一些繁重的工作


我为我过去参与的一个项目开发了一个通用代码评估小部件,只需使用
eval
。它支持对控制台的日志和错误进行沙箱处理。仔细查看可能会有所帮助。

谢谢Dan!我相信您的方法最适合于此。有什么方法可以查看您的应用程序吗?另外,由于我的耳朵还有些湿,对我来说实现你的方法的最佳方式是什么。这是我的思考过程,请告诉我我离基础有多远…在我的HTML中创建一个
,也创建一个
var main = function() {
  /* Push the body and the nav over by 285px over */
  $('.icon-menu').click(function() {
    $('.menu').animate({
      left: "0px"
    }, 100);

    $('body').animate({
      left: "285px"
    }, 100);
  });

  /* Then push them back */
  $('.icon-close').click(function() {
    $('.menu').animate({
      left: "-285px"
    }, 100);

    $('body').animate({
      left: "0px"
    }, 100);
  });
};


/* ========== Evaluate Code ========== */

var app = {};

// go through the application and find every single instance of a div
// with the class of 'sandbox'
app.bootstrap = function() {
  var sandboxes = document.getElementsByClassName('sandbox');

  // for each sandbox, run the createSandbox function
  [].forEach.call(sandboxes, app.createSandbox);
};

// given a parent element, find the first textarea inside and
// create a sandbox around it
app.createSandbox = function(parent) {
  var textarea = parent.getElementsByTagName('textarea')[0],
      // create an instance of Sandbox using this textarea
      sandbox = Sandbox(textarea);

  parent.appendChild(sandbox.label);
};

// when the DOM loads bootstrap the application
window.addEventListener('load', app.bootstrap);

// Sandbox class
// This class is based around a textarea element, which will contain
// the code. However, it could just as easily be the DOM element for
// an Ace/Codemirror editor.
function Sandbox(textarea) {
  var sandbox = {};

  // create a label to show output
  sandbox.label = document.createElement('label');
  sandbox.label.setAttribute('class', 'output');
  sandbox.label.addEventListener('click', evaluate);

  // evaluate code whenever there is input into the textarea
  textarea.addEventListener('input', evaluate);
  sandbox.textarea = textarea;

  // initial resize and evaluation
  resize();
  evaluate();

  // resize to within the appropriate height for the textarea
  function resize() {
    var scrollHeight = textarea.scrollHeight;

    if(scrollHeight > Sandbox.MAX_HEIGHT) {
      height = Sandbox.MAX_HEIGHT;
    } else if(scrollHeight < Sandbox.MIN_HEIGHT) {
      height = Sandbox.MIN_HEIGHT;
    } else {
      height = scrollHeight;
    }

    textarea.style.height = height + 'px';
  }

  // evaluate the code within the textarea
  function evaluate() {
    // get the code
    var src = textarea.value,
    // create a console proxy (for logging to the label)
        console = Sandbox.consoleProxy(sandbox.label);

    // clear the output first
    sandbox.label.innerText = '';
    // try the eval and catch errors to send to the console
    try {
      /* jshint ignore:start */
      eval(src);
      /* jshint ignore:end */
    } catch(err) {
      console.error(err);
    }
  }

  return sandbox;
}

// config
Sandbox.MAX_HEIGHT = 500;
Sandbox.MIN_HEIGHT = 50;

// A function which spoofs the native console object, by writing
// text to output elements, rather than the dev tools console.
Sandbox.consoleProxy = function(element) {
  return {
    log: function(message) {
      message = [].join.call(arguments, ' ');
      element.innerText += (message + '\n');
      element.setAttribute('disabled', false);
      // write to the original console too
      console.log.apply(console, arguments);
    },
    error: function(message) {
      element.setAttribute('disabled', true);
      element.innerText = message;
    }
  };
};


/* ========== Modal  ========== */

$('.trigger').click(function() {
     $('.modal-wrapper').toggleClass('open');
    $('.page-wrapper').toggleClass('blur');
     return false;
  });

$(document).ready(main);