diff options
author | Andrew Gerrand <adg@golang.org> | 2012-02-15 12:59:50 +1100 |
---|---|---|
committer | Andrew Gerrand <adg@golang.org> | 2012-02-15 12:59:50 +1100 |
commit | 3509687d6a98ca492d4e64a0cd093c5644266740 (patch) | |
tree | 68f21daf989cbb984fc16c07467c92c20daf8e1f | |
parent | dd91d83d2427e5a076aa92342b70dda63dd1cbb6 (diff) | |
download | go-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.js | 197 | ||||
-rw-r--r-- | doc/root.html | 77 | ||||
-rw-r--r-- | doc/style.css | 1 |
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; |