]> Cypherpunks repositories - gostls13.git/commitdiff
doc: add playground.js
authorAndrew Gerrand <adg@golang.org>
Wed, 15 Feb 2012 01:59:50 +0000 (12:59 +1100)
committerAndrew Gerrand <adg@golang.org>
Wed, 15 Feb 2012 01:59:50 +0000 (12:59 +1100)
R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/5649087

doc/play/playground.js
doc/root.html
doc/style.css

index ce9aa27b49ffcf09c0d16c2a9eca508dced6bc4e..6f1a5c7a2eeaea964231654ca15a84276a4b7ab2 100644 (file)
@@ -1,6 +1,197 @@
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// A dummy playground.js file to silence godoc errors
-// when accessing doc/root.html.
+// opts is an object with these keys
+//     codeEl - code editor element 
+//     outputEl - program output element
+//     runEl - run button element
+//     shareEl - share button element (optional)
+//     shareURLEl - share URL text input element (optional)
+//     preCompile - callback to mutate request data before compiling
+//     postCompile - callback to read response data after compiling
+//      simple - use plain textarea instead of CodeMirror.
+function playground(opts) {
+       var simple = opts['simple'];
+       var code = $(opts['codeEl']);
+       var editor;
+
+       // autoindent helpers for simple mode.
+       function insertTabs(n) {
+               // find the selection start and end
+               var start = code[0].selectionStart;
+               var end   = code[0].selectionEnd;
+               // split the textarea content into two, and insert n tabs
+               var v = code[0].value;
+               var u = v.substr(0, start);
+               for (var i=0; i<n; i++) {
+                       u += "\t";
+               }
+               u += v.substr(end);
+               // set revised content
+               code[0].value = u;
+               // reset caret position after inserted tabs
+               code[0].selectionStart = start+n;
+               code[0].selectionEnd = start+n;
+       }
+       function autoindent(el) {
+               var curpos = el.selectionStart;
+               var tabs = 0;
+               while (curpos > 0) {
+                       curpos--;
+                       if (el.value[curpos] == "\t") {
+                               tabs++;
+                       } else if (tabs > 0 || el.value[curpos] == "\n") {
+                               break;
+                       }
+               }
+               setTimeout(function() {
+                       insertTabs(tabs, 1);
+               }, 1);
+       }
+
+       function keyHandler(e) {
+               if (simple && e.keyCode == 9) { // tab
+                       insertTabs(1);
+                       e.preventDefault();
+                       return false;
+               }
+               if (e.keyCode == 13) { // enter
+                       if (e.shiftKey) { // +shift
+                               run();
+                               e.preventDefault();
+                               return false;
+                       } else if (simple) {
+                               autoindent(e.target);
+                       }
+               }
+               return true;
+       }
+       if (simple) {
+               code.unbind('keydown').bind('keydown', keyHandler);
+       } else {
+               editor = CodeMirror.fromTextArea(
+                       code[0],
+                       {
+                               lineNumbers: true,
+                               indentUnit: 8,
+                               indentWithTabs: true,
+                               onKeyEvent: function(editor, e) { keyHandler(e); }
+                       }
+               );
+       }
+       var output = $(opts['outputEl']);
+
+       function clearErrors() {
+               if (!editor) {
+                       return;
+               }
+               var lines = editor.lineCount();
+               for (var i = 0; i < lines; i++) {
+                       editor.setLineClass(i, null);
+               }
+       }
+       function highlightErrors(text) {
+               if (!editor) {
+                       return;
+               }
+               var errorRe = /[a-z]+\.go:([0-9]+): /g;
+               var result;
+               while ((result = errorRe.exec(text)) != null) {
+                       var line = result[1]*1-1;
+                       editor.setLineClass(line, "errLine")
+               }
+       }
+       function body() {
+               if (editor) {
+                       return editor.getValue();
+               }
+               return $(opts['codeEl']).val();
+       }
+
+       var seq = 0;
+       function run() {
+               clearErrors();
+               output.removeClass("error").html(
+                       '<div class="loading">Waiting for remote server...</div>'
+               );
+               seq++;
+               var cur = seq;
+               var data = {"body": body()};
+               if (opts['preCompile']) {
+                       opts['preCompile'](data);
+               }
+               $.ajax("/compile", {
+                       data: data,
+                       type: "POST",
+                       dataType: "json",
+                       success: function(data) {
+                               if (seq != cur) {
+                                       return;
+                               }
+                               pre = $("<pre/>");
+                               output.empty().append(pre);
+                               if (opts['postCompile']) {
+                                       opts['postCompile'](data);
+                               }
+                               if (!data) {
+                                       return;
+                               }
+                               if (data.compile_errors != "") {
+                                       pre.text(data.compile_errors);
+                                       output.addClass("error");
+                                       highlightErrors(data.compile_errors);
+                                       return;
+                               }
+                               var out = ""+data.output;
+                               if (out.indexOf("IMAGE:") == 0) {
+                                       var img = $("<img/>");
+                                       var url = "data:image/png;base64,";
+                                       url += out.substr(6)
+                                       img.attr("src", url);
+                                       output.empty().append(img);
+                                       return;
+                               }
+                               pre.text(out);
+                       },
+                       error: function() {
+                               output.addClass("error").text(
+                                       "Error communicating with remote server."
+                               );
+                       }
+               });
+       }
+       $(opts['runEl']).click(run);
+
+       if (opts['shareEl'] == null || opts['shareURLEl'] == null) {
+               return editor;
+       }
+
+       function origin(href) {
+               return (""+href).split("/").slice(0, 3).join("/");
+       }
+
+       var shareURL = $(opts['shareURLEl']).hide();
+       var sharing = false;
+       $(opts['shareEl']).click(function() {
+               if (sharing) return;
+               sharing = true;
+               $.ajax("/share", {
+                       processData: false,
+                       data: body(),
+                       type: "POST",
+                       complete: function(xhr) {
+                               sharing = false;
+                               if (xhr.status != 200) {
+                                       alert("Server error; try again.");
+                                       return
+                               }
+                               var url = origin(window.location) + "/p/" +
+                                       xhr.responseText;
+                               shareURL.show().val(url).focus().select();
+                       }
+               });
+       });
+
+       return editor;
+}
index 7007dceb4bede7fd1765af8be15c4b6c8678f5c3..20bd62b2741125cc74be06d8b592e08d14cf6ff3 100644 (file)
@@ -26,7 +26,7 @@ Linux, Mac OS X, Windows, and more.
 <div id="learn">
 <div class="rootHeading">Try Go</div>
 <div class="input">
-<textarea spellcheck="false">// You can edit this code!
+<textarea spellcheck="false" id="code">// You can edit this code!
 // Click here and start typing.
 package main
 
@@ -36,14 +36,14 @@ func main() {
        fmt.Println("Hello, 世界")
 }</textarea>
 </div>
-<div class="output">
+<div class="output" id="output">
 <pre>
 Hello, 世界
 </pre>
 </div>
 <div class="buttons">
-<a href="#">Run</a>
-<a href="#">Share</a>
+<a id="run" href="#">Run</a>
+<a id="share" href="#">Share</a>
 </div>
 </div>
 
@@ -75,39 +75,52 @@ Hello, 世界
 <div id="plusoneRoot"><g:plusone annotation="none"></g:plusone></div>
 
 <script type="text/javascript" src="https://www.google.com/jsapi"></script>
-<script>
+<script type="text/javascript" src="/doc/play/playground.js"></script>
+<script type="text/javascript">
 google.load("feeds", "1");
+google.load("jquery", "1.7.1");
 
 function feedLoaded(result) {
-  if (result.error) {
-    console.log(result.error);
-    return;
-  }
-  var blog = document.getElementById("blog");
-  var read = blog.getElementsByClassName("read")[0];
-  for (var i = 0; i < result.feed.entries.length && i < 2; i++) {
-    var entry = result.feed.entries[i];
-    var title = document.createElement("a");
-    title.className = "title";
-    title.href = entry.link;
-    title.innerHTML = entry.title;
-    blog.insertBefore(title, read);
-    var extract = document.createElement("div");
-    extract.className = "extract";
-    extract.innerHTML = entry.contentSnippet;
-    blog.insertBefore(extract, read);
-    var when = document.createElement("div");
-    when.className = "when";
-    var pub = entry.publishedDate.split(" ").slice(1,3).join(" ");
-    when.innerHTML = "Published " + pub
-    blog.insertBefore(when, read);
-  }
+       if (result.error) {
+               console.log(result.error);
+               return;
+       }
+       var blog = document.getElementById("blog");
+       var read = blog.getElementsByClassName("read")[0];
+       for (var i = 0; i < result.feed.entries.length && i < 2; i++) {
+               var entry = result.feed.entries[i];
+               var title = document.createElement("a");
+               title.className = "title";
+               title.href = entry.link;
+               title.innerHTML = entry.title;
+               blog.insertBefore(title, read);
+               var extract = document.createElement("div");
+               extract.className = "extract";
+               extract.innerHTML = entry.contentSnippet;
+               blog.insertBefore(extract, read);
+               var when = document.createElement("div");
+               when.className = "when";
+               var pub = entry.publishedDate.split(" ").slice(1,3).join(" ");
+               when.innerHTML = "Published " + pub
+               blog.insertBefore(when, read);
+       }
 }
 
-function fetchFeeds() {
-  var feed = new google.feeds.Feed("http://blog.golang.org/feeds/posts/default");
-  feed.load(feedLoaded);
+function init() {
+       // Load blog feed.
+       var feed = new google.feeds.Feed("http://blog.golang.org/feeds/posts/default");
+       feed.load(feedLoaded);
+
+       // Set up playground.
+       playground({
+               "simple":     true,
+               "codeEl":     "#code",
+               "outputEl":   "#output",
+               "runEl":      "#run",
+               "shareEl":    "#share",
+               "shareURLEl": "#shareURL"
+       });
 }
 
-google.setOnLoadCallback(fetchFeeds);
+google.setOnLoadCallback(init);
 </script>
index 68a43f9b21bc8b5b573f326d7c5732a141ed5197..13a0e04ee4d16a904ceb866c2b465ebcb4a6fcdc 100644 (file)
@@ -227,6 +227,7 @@ body {
 }
 
 #learn pre, #learn textarea {
+       padding: 0;
        margin: 0;
        font-family: Menlo, monospace;
        font-size: 14px;