mirror of
https://github.com/golang/go
synced 2024-11-18 11:04:42 -07:00
x/tools/present: display presenter notes and synchronize browser windows
Change-Id: If7d5cc52f7594c141060d40e8393ac69cb7ba9ad Reviewed-on: https://go-review.googlesource.com/21488 Reviewed-by: Andrew Gerrand <adg@golang.org>
This commit is contained in:
parent
6eef0b4fad
commit
19c2ab042a
32
cmd/present/static/notes.css
Normal file
32
cmd/present/static/notes.css
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
p {
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#presenter-slides {
|
||||||
|
display: block;
|
||||||
|
margin-top: -10px;
|
||||||
|
margin-left: -17px;
|
||||||
|
position: fixed;
|
||||||
|
border: 0;
|
||||||
|
width : 146%;
|
||||||
|
height: 750px;
|
||||||
|
|
||||||
|
transform: scale(0.7, 0.7);
|
||||||
|
transform-origin: top left;
|
||||||
|
-moz-transform: scale(0.7);
|
||||||
|
-moz-transform-origin: top left;
|
||||||
|
-o-transform: scale(0.7);
|
||||||
|
-o-transform-origin: top left;
|
||||||
|
-webkit-transform: scale(0.7);
|
||||||
|
-webkit-transform-origin: top left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#presenter-notes {
|
||||||
|
margin-top: -180px;
|
||||||
|
font-family: 'Open Sans', Arial, sans-serif;
|
||||||
|
height: 30%;
|
||||||
|
width: 100%;
|
||||||
|
overflow: scroll;
|
||||||
|
position: fixed;
|
||||||
|
top: 706px;
|
||||||
|
}
|
158
cmd/present/static/notes.js
Normal file
158
cmd/present/static/notes.js
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
// Copyright 2016 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.
|
||||||
|
|
||||||
|
// Store child window object which will display slides with notes
|
||||||
|
var notesWindow = null;
|
||||||
|
|
||||||
|
var isParentWindow = window.parent == window;
|
||||||
|
|
||||||
|
// When parent window closes, clear storage and close child window
|
||||||
|
if (isParentWindow) {
|
||||||
|
window.onbeforeunload = function() {
|
||||||
|
localStorage.clear();
|
||||||
|
if (notesWindow) notesWindow.close();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function toggleNotesWindow() {
|
||||||
|
if (!isParentWindow) return;
|
||||||
|
if (notesWindow) {
|
||||||
|
notesWindow.close();
|
||||||
|
notesWindow = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
initNotes();
|
||||||
|
};
|
||||||
|
|
||||||
|
function initNotes() {
|
||||||
|
notesWindow = window.open('', '', 'width=1000,height=700');
|
||||||
|
var w = notesWindow;
|
||||||
|
var slidesUrl = window.location.href;
|
||||||
|
|
||||||
|
var curSlide = parseInt(localStorage.getItem('destSlide'), 10);
|
||||||
|
var formattedNotes;
|
||||||
|
var section = sections[curSlide - 1];
|
||||||
|
// curSlide is 0 when initialized from the first page of slides.
|
||||||
|
// Check if section is valid before retrieving Notes.
|
||||||
|
if (section) {
|
||||||
|
formattedNotes = formatNotes(section.Notes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hack to apply css. Requires existing html on notesWindow.
|
||||||
|
w.document.write("<div style='display:none;'></div>");
|
||||||
|
|
||||||
|
w.document.title = window.document.title;
|
||||||
|
|
||||||
|
var slides = w.document.createElement('iframe');
|
||||||
|
slides.id = 'presenter-slides';
|
||||||
|
slides.src = slidesUrl;
|
||||||
|
w.document.body.appendChild(slides);
|
||||||
|
// setTimeout needed for Firefox
|
||||||
|
setTimeout(function() {
|
||||||
|
slides.focus();
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
var notes = w.document.createElement('div');
|
||||||
|
notes.id = 'presenter-notes';
|
||||||
|
notes.innerHTML = formattedNotes;
|
||||||
|
w.document.body.appendChild(notes);
|
||||||
|
|
||||||
|
w.document.close();
|
||||||
|
|
||||||
|
function addPresenterNotesStyle() {
|
||||||
|
var el = w.document.createElement('link');
|
||||||
|
el.rel = 'stylesheet';
|
||||||
|
el.type = 'text/css';
|
||||||
|
el.href = PERMANENT_URL_PREFIX + 'notes.css';
|
||||||
|
w.document.body.appendChild(el);
|
||||||
|
w.document.querySelector('head').appendChild(el);
|
||||||
|
}
|
||||||
|
|
||||||
|
addPresenterNotesStyle();
|
||||||
|
|
||||||
|
// Add listener on notesWindow to update notes when triggered from
|
||||||
|
// parent window
|
||||||
|
w.addEventListener('storage', updateNotes, false);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function formatNotes(notes) {
|
||||||
|
var formattedNotes = '';
|
||||||
|
if (notes) {
|
||||||
|
for (var i = 0; i < notes.length; i++) {
|
||||||
|
formattedNotes = formattedNotes + '<p>' + notes[i] + '</p>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return formattedNotes;
|
||||||
|
};
|
||||||
|
|
||||||
|
function updateNotes() {
|
||||||
|
// When triggered from parent window, notesWindow is null
|
||||||
|
// The storage event listener on notesWindow will update notes
|
||||||
|
if (!notesWindow) return;
|
||||||
|
var destSlide = parseInt(localStorage.getItem('destSlide'), 10);
|
||||||
|
var section = sections[destSlide - 1];
|
||||||
|
var el = notesWindow.document.getElementById('presenter-notes');
|
||||||
|
|
||||||
|
if (!el) return;
|
||||||
|
|
||||||
|
if (section && section.Notes) {
|
||||||
|
el.innerHTML = formatNotes(section.Notes);
|
||||||
|
} else {
|
||||||
|
el.innerHTML = '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Playground syncing */
|
||||||
|
|
||||||
|
// When presenter notes are enabled, playground click handlers are
|
||||||
|
// stored here to sync click events on the correct playground
|
||||||
|
var playgroundHandlers = {onRun: [], onKill: [], onClose: []};
|
||||||
|
|
||||||
|
function updatePlay(e) {
|
||||||
|
var i = localStorage.getItem('play-index');
|
||||||
|
|
||||||
|
switch (e.key) {
|
||||||
|
case 'play-index':
|
||||||
|
return;
|
||||||
|
case 'play-action':
|
||||||
|
// Sync 'run', 'kill', 'close' actions
|
||||||
|
var action = localStorage.getItem('play-action');
|
||||||
|
playgroundHandlers[action][i](e);
|
||||||
|
return;
|
||||||
|
case 'play-code':
|
||||||
|
// Sync code editing
|
||||||
|
var play = document.querySelectorAll('div.playground')[i];
|
||||||
|
play.innerHTML = localStorage.getItem('play-code');
|
||||||
|
return;
|
||||||
|
case 'output-style':
|
||||||
|
// Sync resizing of playground output
|
||||||
|
var out = document.querySelectorAll('.output')[i];
|
||||||
|
out.style = localStorage.getItem('output-style');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Reset 'run', 'kill', 'close' storage items when synced
|
||||||
|
// so that successive actions can be synced correctly
|
||||||
|
function updatePlayStorage(action, index, e) {
|
||||||
|
localStorage.setItem('play-index', index);
|
||||||
|
|
||||||
|
if (localStorage.getItem('play-action') === action) {
|
||||||
|
// We're the receiving window, and the message has been received
|
||||||
|
localStorage.removeItem('play-action');
|
||||||
|
} else {
|
||||||
|
// We're the triggering window, send the message
|
||||||
|
localStorage.setItem('play-action', action);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action === 'onRun') {
|
||||||
|
if (localStorage.getItem('play-shiftKey') === 'true') {
|
||||||
|
localStorage.removeItem('play-shiftKey');
|
||||||
|
} else if (e.shiftKey) {
|
||||||
|
localStorage.setItem('play-shiftKey', e.shiftKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
@ -14,17 +14,17 @@ var curSlide;
|
|||||||
/* classList polyfill by Eli Grey
|
/* classList polyfill by Eli Grey
|
||||||
* (http://purl.eligrey.com/github/classList.js/blob/master/classList.js) */
|
* (http://purl.eligrey.com/github/classList.js/blob/master/classList.js) */
|
||||||
|
|
||||||
if (typeof document !== "undefined" && !("classList" in document.createElement("a"))) {
|
if (typeof document !== 'undefined' && !('classList' in document.createElement('a'))) {
|
||||||
|
|
||||||
(function (view) {
|
(function (view) {
|
||||||
|
|
||||||
var
|
var
|
||||||
classListProp = "classList"
|
classListProp = 'classList'
|
||||||
, protoProp = "prototype"
|
, protoProp = 'prototype'
|
||||||
, elemCtrProto = (view.HTMLElement || view.Element)[protoProp]
|
, elemCtrProto = (view.HTMLElement || view.Element)[protoProp]
|
||||||
, objCtr = Object
|
, objCtr = Object
|
||||||
strTrim = String[protoProp].trim || function () {
|
strTrim = String[protoProp].trim || function () {
|
||||||
return this.replace(/^\s+|\s+$/g, "");
|
return this.replace(/^\s+|\s+$/g, '');
|
||||||
}
|
}
|
||||||
, arrIndexOf = Array[protoProp].indexOf || function (item) {
|
, arrIndexOf = Array[protoProp].indexOf || function (item) {
|
||||||
for (var i = 0, len = this.length; i < len; i++) {
|
for (var i = 0, len = this.length; i < len; i++) {
|
||||||
@ -41,16 +41,16 @@ var
|
|||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
, checkTokenAndGetIndex = function (classList, token) {
|
, checkTokenAndGetIndex = function (classList, token) {
|
||||||
if (token === "") {
|
if (token === '') {
|
||||||
throw new DOMEx(
|
throw new DOMEx(
|
||||||
"SYNTAX_ERR"
|
'SYNTAX_ERR'
|
||||||
, "An invalid or illegal string was specified"
|
, 'An invalid or illegal string was specified'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (/\s/.test(token)) {
|
if (/\s/.test(token)) {
|
||||||
throw new DOMEx(
|
throw new DOMEx(
|
||||||
"INVALID_CHARACTER_ERR"
|
'INVALID_CHARACTER_ERR'
|
||||||
, "String contains an invalid character"
|
, 'String contains an invalid character'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return arrIndexOf.call(classList, token);
|
return arrIndexOf.call(classList, token);
|
||||||
@ -79,18 +79,18 @@ classListProto.item = function (i) {
|
|||||||
return this[i] || null;
|
return this[i] || null;
|
||||||
};
|
};
|
||||||
classListProto.contains = function (token) {
|
classListProto.contains = function (token) {
|
||||||
token += "";
|
token += '';
|
||||||
return checkTokenAndGetIndex(this, token) !== -1;
|
return checkTokenAndGetIndex(this, token) !== -1;
|
||||||
};
|
};
|
||||||
classListProto.add = function (token) {
|
classListProto.add = function (token) {
|
||||||
token += "";
|
token += '';
|
||||||
if (checkTokenAndGetIndex(this, token) === -1) {
|
if (checkTokenAndGetIndex(this, token) === -1) {
|
||||||
this.push(token);
|
this.push(token);
|
||||||
this._updateClassName();
|
this._updateClassName();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
classListProto.remove = function (token) {
|
classListProto.remove = function (token) {
|
||||||
token += "";
|
token += '';
|
||||||
var index = checkTokenAndGetIndex(this, token);
|
var index = checkTokenAndGetIndex(this, token);
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
this.splice(index, 1);
|
this.splice(index, 1);
|
||||||
@ -98,7 +98,7 @@ classListProto.remove = function (token) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
classListProto.toggle = function (token) {
|
classListProto.toggle = function (token) {
|
||||||
token += "";
|
token += '';
|
||||||
if (checkTokenAndGetIndex(this, token) === -1) {
|
if (checkTokenAndGetIndex(this, token) === -1) {
|
||||||
this.add(token);
|
this.add(token);
|
||||||
} else {
|
} else {
|
||||||
@ -106,7 +106,7 @@ classListProto.toggle = function (token) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
classListProto.toString = function () {
|
classListProto.toString = function () {
|
||||||
return this.join(" ");
|
return this.join(' ');
|
||||||
};
|
};
|
||||||
|
|
||||||
if (objCtr.defineProperty) {
|
if (objCtr.defineProperty) {
|
||||||
@ -211,6 +211,8 @@ function prevSlide() {
|
|||||||
|
|
||||||
updateSlides();
|
updateSlides();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (notesEnabled) localStorage.setItem('destSlide', curSlide);
|
||||||
};
|
};
|
||||||
|
|
||||||
function nextSlide() {
|
function nextSlide() {
|
||||||
@ -220,6 +222,8 @@ function nextSlide() {
|
|||||||
|
|
||||||
updateSlides();
|
updateSlides();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (notesEnabled) localStorage.setItem('destSlide', curSlide);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Slide events */
|
/* Slide events */
|
||||||
@ -395,9 +399,12 @@ function updateHash() {
|
|||||||
|
|
||||||
function handleBodyKeyDown(event) {
|
function handleBodyKeyDown(event) {
|
||||||
// If we're in a code element, only handle pgup/down.
|
// If we're in a code element, only handle pgup/down.
|
||||||
var inCode = event.target.classList.contains("code");
|
var inCode = event.target.classList.contains('code');
|
||||||
|
|
||||||
switch (event.keyCode) {
|
switch (event.keyCode) {
|
||||||
|
case 78: // 'N' opens presenter notes window
|
||||||
|
if (!inCode && notesEnabled) toggleNotesWindow();
|
||||||
|
break;
|
||||||
case 72: // 'H' hides the help text
|
case 72: // 'H' hides the help text
|
||||||
case 27: // escape key
|
case 27: // escape key
|
||||||
if (!inCode) hideHelpText();
|
if (!inCode) hideHelpText();
|
||||||
@ -481,11 +488,13 @@ function handleDomLoaded() {
|
|||||||
|
|
||||||
setupInteraction();
|
setupInteraction();
|
||||||
|
|
||||||
if (window.location.hostname == "localhost" || window.location.hostname == "127.0.0.1" || window.location.hostname == "::1") {
|
if (window.location.hostname == 'localhost' || window.location.hostname == '127.0.0.1' || window.location.hostname == '::1') {
|
||||||
hideHelpText();
|
hideHelpText();
|
||||||
}
|
}
|
||||||
|
|
||||||
document.body.classList.add('loaded');
|
document.body.classList.add('loaded');
|
||||||
|
|
||||||
|
setupNotesSync();
|
||||||
};
|
};
|
||||||
|
|
||||||
function initialize() {
|
function initialize() {
|
||||||
@ -521,3 +530,56 @@ if (!window['_DEBUG'] && document.location.href.indexOf('?debug') !== -1) {
|
|||||||
} else {
|
} else {
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Synchronize windows when notes are enabled */
|
||||||
|
|
||||||
|
function setupNotesSync() {
|
||||||
|
if (!notesEnabled) return;
|
||||||
|
|
||||||
|
function setupPlayResizeSync() {
|
||||||
|
var out = document.getElementsByClassName('output');
|
||||||
|
for (let i = 0; i < out.length; i++) {
|
||||||
|
$(out[i]).bind('resize', function(event) {
|
||||||
|
if ($(event.target).hasClass('ui-resizable')) {
|
||||||
|
localStorage.setItem('play-index', i);
|
||||||
|
localStorage.setItem('output-style', out[i].style.cssText);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function setupPlayCodeSync() {
|
||||||
|
var play = document.querySelectorAll('div.playground');
|
||||||
|
for (let i = 0; i < play.length; i++) {
|
||||||
|
play[i].addEventListener('input', inputHandler, false);
|
||||||
|
|
||||||
|
function inputHandler(e) {
|
||||||
|
localStorage.setItem('play-index', i);
|
||||||
|
localStorage.setItem('play-code', e.target.innerHTML);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
setupPlayCodeSync();
|
||||||
|
setupPlayResizeSync();
|
||||||
|
localStorage.setItem('destSlide', curSlide);
|
||||||
|
window.addEventListener('storage', updateOtherWindow, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// An update to local storage is caught only by the other window
|
||||||
|
// The triggering window does not handle any sync actions
|
||||||
|
function updateOtherWindow(e) {
|
||||||
|
// Ignore remove storage events which are not meant to update the other window
|
||||||
|
var isRemoveStorageEvent = !e.newValue;
|
||||||
|
if (isRemoveStorageEvent) return;
|
||||||
|
|
||||||
|
var destSlide = localStorage.getItem('destSlide');
|
||||||
|
while (destSlide > curSlide) {
|
||||||
|
nextSlide();
|
||||||
|
}
|
||||||
|
while (destSlide < curSlide) {
|
||||||
|
prevSlide();
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePlay(e);
|
||||||
|
updateNotes();
|
||||||
|
}
|
||||||
|
@ -6,7 +6,18 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>{{.Title}}</title>
|
<title>{{.Title}}</title>
|
||||||
<meta charset='utf-8'>
|
<meta charset='utf-8'>
|
||||||
|
<script>
|
||||||
|
var notesEnabled = {{.NotesEnabled}};
|
||||||
|
</script>
|
||||||
<script src='/static/slides.js'></script>
|
<script src='/static/slides.js'></script>
|
||||||
|
|
||||||
|
{{if .NotesEnabled}}
|
||||||
|
<script>
|
||||||
|
var sections = {{.Sections}};
|
||||||
|
</script>
|
||||||
|
<script src='/static/notes.js'></script>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Initialize Google Analytics tracking code on production site only.
|
// Initialize Google Analytics tracking code on production site only.
|
||||||
if (window["location"] && window["location"]["hostname"] == "talks.golang.org") {
|
if (window["location"] && window["location"]["hostname"] == "talks.golang.org") {
|
||||||
|
@ -3,16 +3,16 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
function initPlayground(transport) {
|
function initPlayground(transport) {
|
||||||
"use strict";
|
'use strict';
|
||||||
|
|
||||||
function text(node) {
|
function text(node) {
|
||||||
var s = "";
|
var s = '';
|
||||||
for (var i = 0; i < node.childNodes.length; i++) {
|
for (var i = 0; i < node.childNodes.length; i++) {
|
||||||
var n = node.childNodes[i];
|
var n = node.childNodes[i];
|
||||||
if (n.nodeType === 1) {
|
if (n.nodeType === 1) {
|
||||||
if (n.tagName === "BUTTON") continue
|
if (n.tagName === 'BUTTON') continue
|
||||||
if (n.tagName === "SPAN" && n.className === "number") continue;
|
if (n.tagName === 'SPAN' && n.className === 'number') continue;
|
||||||
if (n.tagName === "DIV" || n.tagName == "BR") {
|
if (n.tagName === 'DIV' || n.tagName == 'BR') {
|
||||||
s += "\n";
|
s += "\n";
|
||||||
}
|
}
|
||||||
s += text(n);
|
s += text(n);
|
||||||
@ -22,41 +22,53 @@ function initPlayground(transport) {
|
|||||||
s += n.nodeValue;
|
s += n.nodeValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s.replace("\xA0", " "); // replace non-breaking spaces
|
return s.replace('\xA0', ' '); // replace non-breaking spaces
|
||||||
}
|
}
|
||||||
|
|
||||||
function init(code) {
|
// When presenter notes are enabled, the index passed
|
||||||
|
// here will identify the playground to be synced
|
||||||
|
function init(code, index) {
|
||||||
var output = document.createElement('div');
|
var output = document.createElement('div');
|
||||||
var outpre = document.createElement('pre');
|
var outpre = document.createElement('pre');
|
||||||
var running;
|
var running;
|
||||||
|
|
||||||
if ($ && $(output).resizable) {
|
if ($ && $(output).resizable) {
|
||||||
$(output).resizable({
|
$(output).resizable({
|
||||||
handles: "n,w,nw",
|
handles: 'n,w,nw',
|
||||||
minHeight: 27,
|
minHeight: 27,
|
||||||
minWidth: 135,
|
minWidth: 135,
|
||||||
maxHeight: 608,
|
maxHeight: 608,
|
||||||
maxWidth: 990
|
maxWidth: 990
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onKill() {
|
function onKill() {
|
||||||
if (running) running.Kill();
|
if (running) running.Kill();
|
||||||
|
if (notesEnabled) updatePlayStorage('onKill', index);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onRun(e) {
|
function onRun(e) {
|
||||||
onKill();
|
var sk = e.shiftKey || localStorage.getItem('play-shiftKey') === 'true';
|
||||||
output.style.display = "block";
|
if (running) running.Kill();
|
||||||
outpre.innerHTML = "";
|
output.style.display = 'block';
|
||||||
run1.style.display = "none";
|
outpre.innerHTML = '';
|
||||||
var options = {Race: e.shiftKey};
|
run1.style.display = 'none';
|
||||||
|
var options = {Race: sk};
|
||||||
running = transport.Run(text(code), PlaygroundOutput(outpre), options);
|
running = transport.Run(text(code), PlaygroundOutput(outpre), options);
|
||||||
|
if (notesEnabled) updatePlayStorage('onRun', index, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onClose() {
|
function onClose() {
|
||||||
onKill();
|
if (running) running.Kill();
|
||||||
output.style.display = "none";
|
output.style.display = 'none';
|
||||||
run1.style.display = "inline-block";
|
run1.style.display = 'inline-block';
|
||||||
|
if (notesEnabled) updatePlayStorage('onClose', index);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notesEnabled) {
|
||||||
|
playgroundHandlers.onRun.push(onRun);
|
||||||
|
playgroundHandlers.onClose.push(onClose);
|
||||||
|
playgroundHandlers.onKill.push(onKill);
|
||||||
}
|
}
|
||||||
|
|
||||||
var run1 = document.createElement('button');
|
var run1 = document.createElement('button');
|
||||||
@ -91,13 +103,12 @@ function initPlayground(transport) {
|
|||||||
output.classList.add('output');
|
output.classList.add('output');
|
||||||
output.appendChild(buttons);
|
output.appendChild(buttons);
|
||||||
output.appendChild(outpre);
|
output.appendChild(outpre);
|
||||||
output.style.display = "none";
|
output.style.display = 'none';
|
||||||
code.parentNode.insertBefore(output, button.nextSibling);
|
code.parentNode.insertBefore(output, button.nextSibling);
|
||||||
}
|
}
|
||||||
|
|
||||||
var play = document.querySelectorAll('div.playground');
|
var play = document.querySelectorAll('div.playground');
|
||||||
for (var i = 0; i < play.length; i++) {
|
for (var i = 0; i < play.length; i++) {
|
||||||
init(play[i]);
|
init(play[i], i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2043,16 +2043,16 @@ perl -i -pe 'chomp if eof' package.txt
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
function initPlayground(transport) {
|
function initPlayground(transport) {
|
||||||
"use strict";
|
'use strict';
|
||||||
|
|
||||||
function text(node) {
|
function text(node) {
|
||||||
var s = "";
|
var s = '';
|
||||||
for (var i = 0; i < node.childNodes.length; i++) {
|
for (var i = 0; i < node.childNodes.length; i++) {
|
||||||
var n = node.childNodes[i];
|
var n = node.childNodes[i];
|
||||||
if (n.nodeType === 1) {
|
if (n.nodeType === 1) {
|
||||||
if (n.tagName === "BUTTON") continue
|
if (n.tagName === 'BUTTON') continue
|
||||||
if (n.tagName === "SPAN" && n.className === "number") continue;
|
if (n.tagName === 'SPAN' && n.className === 'number') continue;
|
||||||
if (n.tagName === "DIV" || n.tagName == "BR") {
|
if (n.tagName === 'DIV' || n.tagName == 'BR') {
|
||||||
s += "\n";
|
s += "\n";
|
||||||
}
|
}
|
||||||
s += text(n);
|
s += text(n);
|
||||||
@ -2062,41 +2062,53 @@ function initPlayground(transport) {
|
|||||||
s += n.nodeValue;
|
s += n.nodeValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s.replace("\xA0", " "); // replace non-breaking spaces
|
return s.replace('\xA0', ' '); // replace non-breaking spaces
|
||||||
}
|
}
|
||||||
|
|
||||||
function init(code) {
|
// When presenter notes are enabled, the index passed
|
||||||
|
// here will identify the playground to be synced
|
||||||
|
function init(code, index) {
|
||||||
var output = document.createElement('div');
|
var output = document.createElement('div');
|
||||||
var outpre = document.createElement('pre');
|
var outpre = document.createElement('pre');
|
||||||
var running;
|
var running;
|
||||||
|
|
||||||
if ($ && $(output).resizable) {
|
if ($ && $(output).resizable) {
|
||||||
$(output).resizable({
|
$(output).resizable({
|
||||||
handles: "n,w,nw",
|
handles: 'n,w,nw',
|
||||||
minHeight: 27,
|
minHeight: 27,
|
||||||
minWidth: 135,
|
minWidth: 135,
|
||||||
maxHeight: 608,
|
maxHeight: 608,
|
||||||
maxWidth: 990
|
maxWidth: 990
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onKill() {
|
function onKill() {
|
||||||
if (running) running.Kill();
|
if (running) running.Kill();
|
||||||
|
if (notesEnabled) updatePlayStorage('onKill', index);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onRun(e) {
|
function onRun(e) {
|
||||||
onKill();
|
var sk = e.shiftKey || localStorage.getItem('play-shiftKey') === 'true';
|
||||||
output.style.display = "block";
|
if (running) running.Kill();
|
||||||
outpre.innerHTML = "";
|
output.style.display = 'block';
|
||||||
run1.style.display = "none";
|
outpre.innerHTML = '';
|
||||||
var options = {Race: e.shiftKey};
|
run1.style.display = 'none';
|
||||||
|
var options = {Race: sk};
|
||||||
running = transport.Run(text(code), PlaygroundOutput(outpre), options);
|
running = transport.Run(text(code), PlaygroundOutput(outpre), options);
|
||||||
|
if (notesEnabled) updatePlayStorage('onRun', index, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onClose() {
|
function onClose() {
|
||||||
onKill();
|
if (running) running.Kill();
|
||||||
output.style.display = "none";
|
output.style.display = 'none';
|
||||||
run1.style.display = "inline-block";
|
run1.style.display = 'inline-block';
|
||||||
|
if (notesEnabled) updatePlayStorage('onClose', index);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notesEnabled) {
|
||||||
|
playgroundHandlers.onRun.push(onRun);
|
||||||
|
playgroundHandlers.onClose.push(onClose);
|
||||||
|
playgroundHandlers.onKill.push(onKill);
|
||||||
}
|
}
|
||||||
|
|
||||||
var run1 = document.createElement('button');
|
var run1 = document.createElement('button');
|
||||||
@ -2131,16 +2143,15 @@ function initPlayground(transport) {
|
|||||||
output.classList.add('output');
|
output.classList.add('output');
|
||||||
output.appendChild(buttons);
|
output.appendChild(buttons);
|
||||||
output.appendChild(outpre);
|
output.appendChild(outpre);
|
||||||
output.style.display = "none";
|
output.style.display = 'none';
|
||||||
code.parentNode.insertBefore(output, button.nextSibling);
|
code.parentNode.insertBefore(output, button.nextSibling);
|
||||||
}
|
}
|
||||||
|
|
||||||
var play = document.querySelectorAll('div.playground');
|
var play = document.querySelectorAll('div.playground');
|
||||||
for (var i = 0; i < play.length; i++) {
|
for (var i = 0; i < play.length; i++) {
|
||||||
init(play[i]);
|
init(play[i], i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
`,
|
`,
|
||||||
|
|
||||||
"playground.js": `// Copyright 2012 The Go Authors. All rights reserved.
|
"playground.js": `// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
Loading…
Reference in New Issue
Block a user