aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Gerrand <adg@golang.org>2012-02-15 12:59:50 +1100
committerAndrew Gerrand <adg@golang.org>2012-02-15 12:59:50 +1100
commit3509687d6a98ca492d4e64a0cd093c5644266740 (patch)
tree68f21daf989cbb984fc16c07467c92c20daf8e1f
parentdd91d83d2427e5a076aa92342b70dda63dd1cbb6 (diff)
downloadgo-3509687d6a98ca492d4e64a0cd093c5644266740.tar.gz
go-3509687d6a98ca492d4e64a0cd093c5644266740.zip
doc: add playground.js
R=golang-dev, dsymonds CC=golang-dev https://golang.org/cl/5649087
-rw-r--r--doc/play/playground.js197
-rw-r--r--doc/root.html77
-rw-r--r--doc/style.css1
3 files changed, 240 insertions, 35 deletions
diff --git a/doc/play/playground.js b/doc/play/playground.js
index ce9aa27b49..6f1a5c7a2e 100644
--- a/doc/play/playground.js
+++ b/doc/play/playground.js
@@ -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;
+}
diff --git a/doc/root.html b/doc/root.html
index 7007dceb4b..20bd62b274 100644
--- a/doc/root.html
+++ b/doc/root.html
@@ -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>
diff --git a/doc/style.css b/doc/style.css
index 68a43f9b21..13a0e04ee4 100644
--- a/doc/style.css
+++ b/doc/style.css
@@ -227,6 +227,7 @@ body {
}
#learn pre, #learn textarea {
+ padding: 0;
margin: 0;
font-family: Menlo, monospace;
font-size: 14px;