JavaScript DHTML/Mochkit/InterpreterManager

Материал из Web эксперт
Перейти к: навигация, поиск

Interpreter - JavaScript Interactive Interpreter

   <source lang="html4strict">
 


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html>

   <head>
       <title>Interpreter - JavaScript Interactive Interpreter</title>
       <style type="text/css">

h1 {

   font-size: 2em;
   color: #4B4545;
   text-align: center;

} textarea.textbox {

   font-family: Monaco, "lucida console", Courier;
   border: 1px solid #CCCCCC;
   font-size: .60em; 
   padding: 2px 4px;
   margin-top: .3em;

} input.textbox {

   font-family: Monaco, "lucida console", Courier;
   border: 1px solid #CCCCCC;
   font-size: .60em; 
   padding: 2px 4px;
   margin-top: .3em;

}

  1. interpreter_area {
   display: block;
   border: 1px solid #CCCCCC;
   padding: 2px 4px;
   margin-top: .3em;
   width: 600px;
   height: 300px;
   overflow: auto;

}

  1. interpreter_output {
   display: inline;
   font-family: Monaco, "lucida console", Courier;
   font-size: .60em;

}

  1. interpreter_output span {
   white-space: -moz-pre-wrap; /* Mozilla */
   white-space: -o-pre-wrap; /* Opera 7 */
   white-space: pre-wrap; /* CSS 2.1 */
   white-space: pre-line; /* CSS 3 (and 2.1 as well, actually) */
   word-wrap: break-word; /* IE */
   wrap-option: emergency; /* CSS 3 */

} input.textbox:focus { background-color: #FFFEE3; } .code { color: blue; } .data { color: black; } .error { color: red; } .banner { color: green; } .invisible { display: none; }

       </style>
       <script type="text/javascript" src="MochiKit-1.4.2/lib/MochiKit/MochiKit.js"></script>
       <script type="text/javascript">

/*

   Interpreter: JavaScript Interactive Interpreter
  • /

InterpreterManager = function () {

   bindMethods(this);

}; InterpreterManager.prototype.initialize = function () {

   connect("interpreter_text", "onkeyup", this.keyUp);
   connect("interpreter_textarea", "onkeydown", this.areaKeyDown);
   connect("interpreter_form", "onsubmit", this.submit);
   getElement("interpreter_text").focus();
   this.banner();
   this.lines = [];
   this.history = [];
   this.currentHistory = "";
   this.historyPos = -1;
   this.blockingOn = null;
   if (typeof(this.doEval) == "undefined") {
       // detect broken eval, warn at some point if a namespace ever gets used
       this.doEval = function () {
           return eval(arguments[0]);
       }
   }
   window.help = this.help;
   this.help.NAME = "type help(func) for help on a MochiKit function";

}; InterpreterManager.prototype.banner = function () {

   var _ua = window.navigator.userAgent;
   var ua = _ua.replace(/^Mozilla\/.*?\(.*?\)\s*/, "");
   if (ua == "") {
       // MSIE
       ua = _ua.replace(/^Mozilla\/4\.0 \(compatible; MS(IE .*?);.*$/, "$1");
   }
   appendChildNodes("interpreter_output",
       SPAN({"class": "banner"},
           "MochiKit v" + MochiKit.Base.VERSION + " [" + ua + "]",
           BR(),
           "Type your expression in the input box below and press return, or see the notes below for more information.",
           BR()
       ),
       BR()
   );

}; InterpreterManager.prototype.submit = function (event) {

   if (this.blockingOn) {
       try {
           this.blockingOn.cancel();
       } catch (e) {
           this.showError(e);
       }
       this.blockingOn = null;
   }
   this.doSubmit();
   this.doScroll();
   event.stop();

}; InterpreterManager.prototype.help = function (fn) {

   if (fn && fn.NAME) {
       fn = fn.NAME;
   }
   if (typeof(fn) != "string" || fn.length == 0) {
       writeln("help(func) on any MochiKit function for help");
       return;
   }
   var comps = fn.split(".");
   var base = comps.splice(0, 2);
   var shortfn = comps.join(".");
   var url = "../../doc/html/" + base.join("/") + ".html";
   var d = doXHR(url, {mimeType: "text/xml"});
   d.addCallback(function (req) {
       var els = getElementsByTagAndClassName(
           "a", "mochidef", req.responseXML);
       var match = "#fn-" + shortfn.toLowerCase();
       for (var i = 0; i < els.length; i++) {
           var elem = els[i];
           var href = elem.href;
           var idx = href.indexOf("#");
           if (idx != -1 && href.substring(idx) == match) {
               writeln(A({href: url + match, target: "_blank"},
                   scrapeText(elem)));
               return;
           }
       }
       writeln("documentation for " + fn + " not found");
   });
   blockOn(d);

};

InterpreterManager.prototype.doScroll = function () {

   var p = getElement("interpreter_output").lastChild;
   if (typeof(p) == "undefined" || p == null) {
       return;
   }
   var area = getElement("interpreter_area");
   if (area.offsetHeight > area.scrollHeight) {
       area.scrollTop = 0;
   } else {
       area.scrollTop = area.scrollHeight;
   }

}; InterpreterManager.prototype.moveHistory = function (dir) {

   // totally bogus value
   if (dir == 0 || this.history.length == 0) {
       return;
   }
   var elem = getElement("interpreter_text");
   if (this.historyPos == -1) {
       this.currentHistory = elem.value;
       if (dir > 0) {
           return;
       }
       this.historyPos = this.history.length - 1;
       elem.value = this.history[this.historyPos];
       return;
   }
   if (this.historyPos == 0 && dir < 0) {
       return;
   }
   if (this.historyPos == this.history.length - 1 && dir > 0) {
       this.historyPos = -1;
       elem.value = this.currentHistory;
       return;
   } 
   this.historyPos += dir;
   elem.value = this.history[this.historyPos];

} InterpreterManager.prototype.runMultipleLines = function (text) {

   var lines = rstrip(text).replace("\r\n", "\n").split(/\n/);
   appendChildNodes("interpreter_output",
       SPAN({"class": "code"}, ">>> ", izip(lines, imap(BR, cycle([null]))))
   );
   this.runCode(text);

} InterpreterManager.prototype.areaKeyDown = function (e) {

   var mod = e.modifier();
   var hasMod = mod.alt || mod.ctrl || mod.meta;
   if (e.key().string == "KEY_ENTER" && hasMod) {
       var elem = getElement("interpreter_textarea");
       var text = elem.value;
       elem.value = "";
       this.runMultipleLines(text);
       e.stop();
   }

}; InterpreterManager.prototype.keyUp = function (e) {

   var key = e.key();
   // if any meta key is pressed, don"t handle the signal
   if (e.modifier().any) {
       return;
   }
   switch (key.string) {
       case "KEY_ARROW_UP": this.moveHistory(-1); break;
       case "KEY_ARROW_DOWN": this.moveHistory(1); break;
       default: return;
   }
   e.stop();

}; InterpreterManager.prototype.blockOn = function (d) {

   var node = SPAN({"class": "banner"}, "blocking on " + repr(d) + "...");
   this.blockingOn = d;
   appendChildNodes("interpreter_output", node);
   this.doScroll();
   d.addBoth(function (res) {
       swapDOM(node);
       this.blockingOn = null;
       if (res instanceof CancelledError) {
           window.writeln(SPAN({"class": "error"}, repr(d) + " cancelled!"));
           return undefined;
       }
       return res;
   });
   d.addCallbacks(this.showResult, this.showError);

}; InterpreterManager.prototype.showError = function (e) {

   if (typeof(e) != "object") {
       e = new Error(e);
   }
   appendChildNodes("interpreter_output",
       SPAN({"class": "error"}, "Error:"),
       TABLE({"class": "error"},
           THEAD({"class": "invisible"}, TD({"colspan": 2})),
           TFOOT({"class": "invisible"}, TD({"colspan": 2})),
           TBODY(null,
               map(function (kv) {
                   var v = kv[1];
                   if (typeof(v) == "function") {
                       return;
                   }
                   if (typeof(v) == "object") {
                       v = repr(v);
                   }
                   return TR(null,
                       TD({"class": "error"}, kv[0]),
                       TD({"class": "data"}, v)
                   );
               }, sorted(items(e)))
           )
       )
   );
   window.last_exc = e;
   this.doScroll();

}; EvalFunctions = {

   evalWith: function () {
       with (arguments[1] || window) { return eval(arguments[0]); };
   },
   evalCall: function () {
       return eval.call(arguments[1] || window, arguments[0]);
   },
   choose: function () {
       var ns = {__test__: this};
       var e;
       try {
           if (this.evalWith("return __test__", ns) === this) { 
               return this.evalWith;
           }
       } catch (e) {
           // pass
       }
       try {
           if (this.evalCall("return __test__", ns) === this) { 
               return this.evalCall;
           }
       } catch (e) {
           // pass
       }
       return undefined;
   }

};

InterpreterManager.prototype.doEval = EvalFunctions.choose(); InterpreterManager.prototype.doSubmit = function () {

   var elem = getElement("interpreter_text");
   var code = elem.value;
   elem.value = "";
   var isContinuation = false;
   if (code.length >= 2 && code.lastIndexOf("//") == code.length - 2) {
       isContinuation = true;
       code = code.substr(0, code.length - 2);
   }
   appendChildNodes("interpreter_output",
       SPAN({"class": "code"}, ">>> ", code),
       BR()
   );
   this.lines.push(code);
   this.history.push(code);
   this.historyPos = -1;
   this.currentHistory = "";
   if (isContinuation) {
       return;
   }
   var allCode = this.lines.join("\n");
   this.lines = [];
   this.runCode(allCode);
   return;

}; InterpreterManager.prototype.runCode = function (allCode) {

   var res;
   try {
       res = this.doEval(allCode);
   } catch (e) {
       // mozilla shows some keys more than once!
       this.showError(e);
       return;
   }
   this.showResult(res);

}; InterpreterManager.prototype.showResult = function (res) {

   if (typeof(res) != "undefined") {
       window._ = res;
   }
   if (typeof(res) != "undefined") {
       appendChildNodes("interpreter_output",
           SPAN({"class": "data"}, repr(res)),
           BR()
       );
       this.doScroll();
   }

}; window.writeln = function () {

   appendChildNodes("interpreter_output",
       SPAN({"class": "data"}, arguments),
       BR()
   );
   interpreterManager.doScroll();

}; window.clear = function () {

   replaceChildNodes("interpreter_output");
   getElement("interpreter_area").scrollTop = 0;

}; window.blockOn = function (d) {

   if (!(d instanceof Deferred)) {
       throw new TypeError(repr(d) + " is not a Deferred!");
   }
   interpreterManager.blockOn(d);

}; window.dir = function (o) {

   // Python muscle memory!
   return sorted(keys(o));

}; window.inspect = function (o) {

   window._ = o;
   if ((typeof(o) != "function" && typeof(o) != "object") || o == null) {
       window.writeln(repr(o));
       return;
   }
   var pairs = items(o);
   if (pairs.length == 0) {
       window.writeln(repr(o));
       return;
   }
   window.writeln(TABLE({"border": "1"},
       THEAD({"class": "invisible"}, TR(null, TD(), TD())),
       TFOOT({"class": "invisible"}, TR(null, TD(), TD())),
       TBODY(null,
           map(
               function (kv) {
                   var click = function () {
                       try {
                           window.inspect(kv[1]);
                       } catch (e) {
                           interpreterManager.showError(e);
                       }
                       return false;
                   }
                   return TR(null,
                       TD(null, A({href: "#", onclick: click}, kv[0])),
                       TD(null, repr(kv[1]))
                   );
               },
               pairs
           )
       )
   ));

};

interpreterManager = new InterpreterManager(); addLoadEvent(interpreterManager.initialize); // rewrite the view-source links addLoadEvent(function () {

   var elems = getElementsByTagAndClassName("A", "view-source");
   var page = "interpreter/";
   for (var i = 0; i < elems.length; i++) {
       var elem = elems[i];
       var href = elem.href.split(/\//).pop();
       elem.target = "_blank";
       elem.href = "../view-source/view-source.html#" + page + href;
   }

});

       </script>
   </head>
   <body>

Interpreter - JavaScript Interactive Interpreter

This demo is a JavaScript interpreter. Type some code into the text input and press enter to see the results. It uses <a href="http://mochikit.ru">MochiKit</a>"s <a href="../../doc/html/lib/MochiKit/DOM.html">MochiKit.DOM</a> to manipulate the display. It also supports waiting for <a href="../../doc/html/lib/MochiKit/Async.html">MochiKit.Async</a> Deferreds via blockOn(aDeferred).

           View Source: [
           <a href="index.html" class="view-source">index.html</a> |
           <a href="interpreter.js" class="view-source">interpreter.js</a>
           ]
       <form id="interpreter_form" autocomplete="off">
               <input id="interpreter_text" name="input_text" type="text" class="textbox" size="100" />
               <textarea id="interpreter_textarea" name="input_textarea" type="text" class="textbox" cols="97" rows="10"></textarea>
               
       </form>
           Notes:
  • To show the signature of a MochiKit function and link to its documentation, type help(fn) on any MochiKit function.
  • To write multi-line code snippets, use the lower text area and press ctrl-enter or cmd-enter to submit.
  • function name() {} syntax might not end up in window scope, so use name = function () {} syntax instead
  • If you want to stuff something into the output window other than the repr(...) of the expression result, use the writeln(...) function. It accepts anything that MochiKit.DOM does, so you can even put styled stuff in there!
  • Use clear() to clear the interpreter window.
  • You can use blockOn(aDeferred) to wait on a Deferred. This expression must be used by itself, so the value must be obtained from _ or last_exc. Typing any expression will cancel the Deferred.
  • Up and down arrow keys work as a rudimentary history
  • _ is the value of the last expression that was not undefined, last_exc is the value of the last unhandled exception.
   </body>

</html>


 </source>