From 3509687d6a98ca492d4e64a0cd093c5644266740 Mon Sep 17 00:00:00 2001 From: Andrew Gerrand Date: Wed, 15 Feb 2012 12:59:50 +1100 Subject: [PATCH] doc: add playground.js R=golang-dev, dsymonds CC=golang-dev https://golang.org/cl/5649087 --- doc/play/playground.js | 197 ++++++++++++++++++++++++++++++++++++++++- doc/root.html | 77 +++++++++------- doc/style.css | 1 + 3 files changed, 240 insertions(+), 35 deletions(-) diff --git a/doc/play/playground.js b/doc/play/playground.js index ce9aa27b49f..6f1a5c7a2ee 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 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( + '
Waiting for remote server...
' + ); + 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 = $("
");
+				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 = $("");
+					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 7007dceb4be..20bd62b2741 100644
--- a/doc/root.html
+++ b/doc/root.html
@@ -26,7 +26,7 @@ Linux, Mac OS X, Windows, and more.
 
Try Go
-
-
+
 Hello, 世界
 
@@ -75,39 +75,52 @@ Hello, 世界
- + diff --git a/doc/style.css b/doc/style.css index 68a43f9b21b..13a0e04ee4d 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;